2023-06-27 17:01:40 +02:00
|
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
#
|
|
|
|
|
# The OpenSearch Contributors require contributions made to
|
|
|
|
|
# this file be licensed under the Apache-2.0 license or a
|
|
|
|
|
# compatible open source license.
|
|
|
|
|
#
|
|
|
|
|
# Modifications Copyright OpenSearch Contributors. See
|
|
|
|
|
# GitHub history for details.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from __future__ import unicode_literals
|
|
|
|
|
|
2024-06-18 11:44:21 -04:00
|
|
|
import os
|
2023-06-27 17:01:40 +02:00
|
|
|
from unittest import TestCase
|
|
|
|
|
|
|
|
|
|
from opensearchpy.connection.connections import add_connection
|
|
|
|
|
from opensearchpy.exceptions import NotFoundError
|
|
|
|
|
from opensearchpy.helpers.test import get_test_client
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestSecurityPlugin(TestCase):
|
|
|
|
|
ROLE_NAME = "test-role"
|
|
|
|
|
ROLE_CONTENT = {
|
|
|
|
|
"cluster_permissions": ["cluster_monitor"],
|
|
|
|
|
"index_permissions": [
|
|
|
|
|
{
|
|
|
|
|
"index_patterns": ["index", "test-*"],
|
|
|
|
|
"allowed_actions": [
|
|
|
|
|
"data_access",
|
|
|
|
|
"indices_monitor",
|
|
|
|
|
],
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
USER_NAME = "test-user"
|
2023-07-21 10:08:09 -07:00
|
|
|
USER_CONTENT = {"password": "opensearchpy@123", "opendistro_security_roles": []}
|
2023-06-27 17:01:40 +02:00
|
|
|
|
2023-11-06 13:08:19 -05:00
|
|
|
def setUp(self) -> None:
|
2024-06-18 11:44:21 -04:00
|
|
|
password = os.environ.get("OPENSEARCH_INITIAL_ADMIN_PASSWORD", "admin")
|
|
|
|
|
self.client = get_test_client(verify_certs=False, http_auth=("admin", password))
|
2023-06-27 17:01:40 +02:00
|
|
|
add_connection("default", self.client)
|
|
|
|
|
|
2023-11-06 13:08:19 -05:00
|
|
|
def tearDown(self) -> None:
|
2023-06-27 17:01:40 +02:00
|
|
|
if self.client:
|
|
|
|
|
self.client.close()
|
|
|
|
|
|
2023-11-06 13:08:19 -05:00
|
|
|
def test_create_role(self) -> None:
|
2023-06-27 17:01:40 +02:00
|
|
|
# Test to create role
|
2023-07-26 15:38:49 -07:00
|
|
|
response = self.client.security.create_role(
|
|
|
|
|
self.ROLE_NAME, body=self.ROLE_CONTENT
|
|
|
|
|
)
|
2023-06-27 17:01:40 +02:00
|
|
|
|
|
|
|
|
self.assertNotIn("errors", response)
|
|
|
|
|
self.assertIn(response.get("status"), ["CREATED", "OK"])
|
|
|
|
|
|
2023-11-06 13:08:19 -05:00
|
|
|
def test_create_role_with_body_param_empty(self) -> None:
|
2023-07-26 15:38:49 -07:00
|
|
|
try:
|
|
|
|
|
self.client.security.create_role(self.ROLE_NAME, body="")
|
|
|
|
|
except ValueError as error:
|
|
|
|
|
assert str(error) == "Empty value passed for a required argument."
|
|
|
|
|
else:
|
|
|
|
|
assert False
|
|
|
|
|
|
2023-11-06 13:08:19 -05:00
|
|
|
def test_get_role(self) -> None:
|
2023-06-27 17:01:40 +02:00
|
|
|
# Create a role
|
|
|
|
|
self.test_create_role()
|
|
|
|
|
|
|
|
|
|
# Test to fetch the role
|
|
|
|
|
response = self.client.security.get_role(self.ROLE_NAME)
|
|
|
|
|
|
|
|
|
|
self.assertNotIn("errors", response)
|
|
|
|
|
self.assertIn(self.ROLE_NAME, response)
|
|
|
|
|
|
2023-11-06 13:08:19 -05:00
|
|
|
def test_update_role(self) -> None:
|
2023-06-27 17:01:40 +02:00
|
|
|
# Create a role
|
|
|
|
|
self.test_create_role()
|
|
|
|
|
|
|
|
|
|
role_content = self.ROLE_CONTENT.copy()
|
|
|
|
|
role_content["cluster_permissions"] = ["cluster_all"]
|
|
|
|
|
|
|
|
|
|
# Test to update role
|
2023-07-26 15:38:49 -07:00
|
|
|
response = self.client.security.create_role(self.ROLE_NAME, body=role_content)
|
2023-06-27 17:01:40 +02:00
|
|
|
|
|
|
|
|
self.assertNotIn("errors", response)
|
|
|
|
|
self.assertEqual("OK", response.get("status"))
|
|
|
|
|
|
2023-11-06 13:08:19 -05:00
|
|
|
def test_delete_role(self) -> None:
|
2023-06-27 17:01:40 +02:00
|
|
|
# Create a role
|
|
|
|
|
self.test_create_role()
|
|
|
|
|
|
|
|
|
|
# Test to delete the role
|
|
|
|
|
response = self.client.security.delete_role(self.ROLE_NAME)
|
|
|
|
|
|
|
|
|
|
self.assertNotIn("errors", response)
|
|
|
|
|
|
|
|
|
|
# Try fetching the role
|
|
|
|
|
with self.assertRaises(NotFoundError):
|
|
|
|
|
response = self.client.security.get_role(self.ROLE_NAME)
|
|
|
|
|
|
2023-11-06 13:08:19 -05:00
|
|
|
def test_create_user(self) -> None:
|
2023-06-27 17:01:40 +02:00
|
|
|
# Test to create user
|
2023-07-26 15:38:49 -07:00
|
|
|
response = self.client.security.create_user(
|
|
|
|
|
self.USER_NAME, body=self.USER_CONTENT
|
|
|
|
|
)
|
2023-06-27 17:01:40 +02:00
|
|
|
|
|
|
|
|
self.assertNotIn("errors", response)
|
|
|
|
|
self.assertIn(response.get("status"), ["CREATED", "OK"])
|
|
|
|
|
|
2023-11-06 13:08:19 -05:00
|
|
|
def test_create_user_with_body_param_empty(self) -> None:
|
2023-07-26 15:38:49 -07:00
|
|
|
try:
|
|
|
|
|
self.client.security.create_user(self.USER_NAME, body="")
|
|
|
|
|
except ValueError as error:
|
|
|
|
|
assert str(error) == "Empty value passed for a required argument."
|
|
|
|
|
else:
|
|
|
|
|
assert False
|
|
|
|
|
|
2023-11-09 10:51:20 -05:00
|
|
|
def test_create_user_with_role(self) -> None:
|
2023-06-27 17:01:40 +02:00
|
|
|
self.test_create_role()
|
|
|
|
|
|
|
|
|
|
# Test to create user
|
2023-07-26 15:38:49 -07:00
|
|
|
response = self.client.security.create_user(
|
2023-06-27 17:01:40 +02:00
|
|
|
self.USER_NAME,
|
|
|
|
|
body={
|
2023-07-21 10:08:09 -07:00
|
|
|
"password": "opensearchpy@123",
|
2023-06-27 17:01:40 +02:00
|
|
|
"opendistro_security_roles": [self.ROLE_NAME],
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
self.assertNotIn("errors", response)
|
|
|
|
|
self.assertIn(response.get("status"), ["CREATED", "OK"])
|
|
|
|
|
|
2023-11-06 13:08:19 -05:00
|
|
|
def test_get_user(self) -> None:
|
2023-06-27 17:01:40 +02:00
|
|
|
# Create a user
|
|
|
|
|
self.test_create_user()
|
|
|
|
|
|
|
|
|
|
# Test to fetch the user
|
|
|
|
|
response = self.client.security.get_user(self.USER_NAME)
|
|
|
|
|
|
|
|
|
|
self.assertNotIn("errors", response)
|
|
|
|
|
self.assertIn(self.USER_NAME, response)
|
|
|
|
|
|
2023-11-06 13:08:19 -05:00
|
|
|
def test_update_user(self) -> None:
|
2023-06-27 17:01:40 +02:00
|
|
|
# Create a user
|
|
|
|
|
self.test_create_user()
|
|
|
|
|
|
|
|
|
|
user_content = self.USER_CONTENT.copy()
|
2023-07-21 10:08:09 -07:00
|
|
|
user_content["password"] = "123@opensearchpy"
|
2023-06-27 17:01:40 +02:00
|
|
|
|
|
|
|
|
# Test to update user
|
2023-07-26 15:38:49 -07:00
|
|
|
response = self.client.security.create_user(self.USER_NAME, body=user_content)
|
2023-06-27 17:01:40 +02:00
|
|
|
|
|
|
|
|
self.assertNotIn("errors", response)
|
|
|
|
|
self.assertEqual("OK", response.get("status"))
|
|
|
|
|
|
2023-11-06 13:08:19 -05:00
|
|
|
def test_delete_user(self) -> None:
|
2023-06-27 17:01:40 +02:00
|
|
|
# Create a user
|
|
|
|
|
self.test_create_user()
|
|
|
|
|
|
|
|
|
|
# Test to delete the user
|
|
|
|
|
response = self.client.security.delete_user(self.USER_NAME)
|
|
|
|
|
|
|
|
|
|
self.assertNotIn("errors", response)
|
|
|
|
|
|
|
|
|
|
# Try fetching the user
|
|
|
|
|
with self.assertRaises(NotFoundError):
|
|
|
|
|
response = self.client.security.get_user(self.USER_NAME)
|
2023-09-26 09:46:18 -07:00
|
|
|
|
2023-11-06 13:08:19 -05:00
|
|
|
def test_health_check(self) -> None:
|
2023-09-26 09:46:18 -07:00
|
|
|
response = self.client.security.health_check()
|
|
|
|
|
self.assertNotIn("errors", response)
|
|
|
|
|
self.assertEqual("UP", response.get("status"))
|
|
|
|
|
|
2023-11-06 13:08:19 -05:00
|
|
|
def test_health(self) -> None:
|
2023-09-26 09:46:18 -07:00
|
|
|
response = self.client.security.health()
|
|
|
|
|
self.assertNotIn("errors", response)
|
|
|
|
|
self.assertEqual("UP", response.get("status"))
|
|
|
|
|
|
|
|
|
|
AUDIT_CONFIG_SETTINGS = {
|
|
|
|
|
"enabled": True,
|
|
|
|
|
"audit": {
|
|
|
|
|
"ignore_users": [],
|
|
|
|
|
"ignore_requests": [],
|
|
|
|
|
"disabled_rest_categories": ["AUTHENTICATED", "GRANTED_PRIVILEGES"],
|
|
|
|
|
"disabled_transport_categories": ["AUTHENTICATED", "GRANTED_PRIVILEGES"],
|
|
|
|
|
"log_request_body": False,
|
|
|
|
|
"resolve_indices": False,
|
|
|
|
|
"resolve_bulk_requests": False,
|
|
|
|
|
"exclude_sensitive_headers": True,
|
|
|
|
|
"enable_transport": False,
|
|
|
|
|
"enable_rest": True,
|
|
|
|
|
},
|
|
|
|
|
"compliance": {
|
|
|
|
|
"enabled": True,
|
|
|
|
|
"write_log_diffs": False,
|
|
|
|
|
"read_watched_fields": {},
|
|
|
|
|
"read_ignore_users": [],
|
|
|
|
|
"write_watched_indices": [],
|
|
|
|
|
"write_ignore_users": [],
|
|
|
|
|
"read_metadata_only": True,
|
|
|
|
|
"write_metadata_only": True,
|
|
|
|
|
"external_config": False,
|
|
|
|
|
"internal_config": True,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-06 13:08:19 -05:00
|
|
|
def test_update_audit_config(self) -> None:
|
2023-09-26 09:46:18 -07:00
|
|
|
response = self.client.security.update_audit_config(
|
|
|
|
|
body=self.AUDIT_CONFIG_SETTINGS
|
|
|
|
|
)
|
|
|
|
|
self.assertNotIn("errors", response)
|
|
|
|
|
self.assertEqual("OK", response.get("status"))
|
|
|
|
|
|
2023-11-06 13:08:19 -05:00
|
|
|
def test_update_audit_configuration(self) -> None:
|
2023-09-26 09:46:18 -07:00
|
|
|
response = self.client.security.update_audit_configuration(
|
|
|
|
|
body=self.AUDIT_CONFIG_SETTINGS
|
|
|
|
|
)
|
|
|
|
|
self.assertNotIn("errors", response)
|
|
|
|
|
self.assertEqual("OK", response.get("status"))
|