Security plugin support (#399)

* feat(plugins): add security client plugin

Signed-off-by: florian <[email protected]>

* test(plugins): skip security plugin tests when disabled

Signed-off-by: florian <[email protected]>

* fix(security): remove non-ASCII character

Signed-off-by: florian <[email protected]>

* chore(CHANGELOG): added entry for security api support in changelog

Signed-off-by: florian <[email protected]>

* test(plugins): add asynchronous tests version

Signed-off-by: florian <[email protected]>

* test: remove some warnings

Signed-off-by: florian <[email protected]>

* chore(USER_GUIDE): add a security plugin part

Signed-off-by: florian <[email protected]>

* test(security): Split out security plugin tests in its own file

Signed-off-by: florian <[email protected]>

* chore: apply reviews

Signed-off-by: florian <[email protected]>

---------

Signed-off-by: florian <[email protected]>
This commit is contained in:
florianvazelle
2023-06-27 11:01:40 -04:00
committed by GitHub
parent db972e615b
commit c60c259d96
26 changed files with 2254 additions and 46 deletions
+1 -1
View File
@@ -81,7 +81,7 @@ END
docker run \ docker run \
--name "$node_name" \ --name "$node_name" \
--network "$network_name" \ --network "$network_name" \
--env "ES_JAVA_OPTS=-Xms1g -Xmx1g" \ --env "OPENSEARCH_JAVA_OPTS=-Xms1g -Xmx1g" \
"${environment[@]}" \ "${environment[@]}" \
"${volumes[@]}" \ "${volumes[@]}" \
"${security[@]}" \ "${security[@]}" \
+1
View File
@@ -8,6 +8,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- Added index lifecycle guide ([#362](https://github.com/opensearch-project/opensearch-py/pull/362)) - Added index lifecycle guide ([#362](https://github.com/opensearch-project/opensearch-py/pull/362))
- Added 'point in time' APIs to the pyi files in sync and async client ([#378](https://github.com/opensearch-project/opensearch-py/pull/378)) - Added 'point in time' APIs to the pyi files in sync and async client ([#378](https://github.com/opensearch-project/opensearch-py/pull/378))
- Added MacOS and Windows CI workflows ([#390](https://github.com/opensearch-project/opensearch-py/pull/390)) - Added MacOS and Windows CI workflows ([#390](https://github.com/opensearch-project/opensearch-py/pull/390))
- Added support for the security plugin ([#399](https://github.com/opensearch-project/opensearch-py/pull/399))
- Compatibility with OpenSearch 2.1.0 - 2.6.0 ([#381](https://github.com/opensearch-project/opensearch-py/pull/381)) - Compatibility with OpenSearch 2.1.0 - 2.6.0 ([#381](https://github.com/opensearch-project/opensearch-py/pull/381))
- Added 'allow_redirects' parameter in perform_request function for RequestsHttpConnection ([#401](https://github.com/opensearch-project/opensearch-py/pull/401)) - Added 'allow_redirects' parameter in perform_request function for RequestsHttpConnection ([#401](https://github.com/opensearch-project/opensearch-py/pull/401))
- Enhanced YAML test runner to use OpenSearch rest-api-spec YAML tests ([#414](https://github.com/opensearch-project/opensearch-py/pull/414) - Enhanced YAML test runner to use OpenSearch rest-api-spec YAML tests ([#414](https://github.com/opensearch-project/opensearch-py/pull/414)
+65
View File
@@ -21,6 +21,11 @@
- [**Creating a destination**](#creating-a-destination) - [**Creating a destination**](#creating-a-destination)
- [**Getting alerts**](#getting-alerts) - [**Getting alerts**](#getting-alerts)
- [**Acknowledge alerts**](#acknowledge-alerts) - [**Acknowledge alerts**](#acknowledge-alerts)
- [Security plugin](#security-plugin)
- [Creating a role](#creating-a-role)
- [Getting a role](#getting-a-role)
- [Creating a user](#creating-a-user)
- [Getting a user](#getting-a-user)
- [Using different authentication methods](#using-different-authentication-methods) - [Using different authentication methods](#using-different-authentication-methods)
- [Using IAM credentials](#using-iam-credentials) - [Using IAM credentials](#using-iam-credentials)
- [Pre-requisites to use `AWSV4SignerAuth`](#pre-requisites-to-use-awsv4signerauth) - [Pre-requisites to use `AWSV4SignerAuth`](#pre-requisites-to-use-awsv4signerauth)
@@ -420,6 +425,66 @@ query = {
response = client.plugins.alerting.acknowledge_alert(query) response = client.plugins.alerting.acknowledge_alert(query)
print(response) print(response)
``` ```
### Security plugin
#### Creating a role
[API definition](https://opensearch.org/docs/latest/security/access-control/api/#create-role)
```python
print('\Creating a role:')
role_name = "test-role"
role_content = {
"cluster_permissions": ["cluster_monitor"],
"index_permissions": [
{
"index_patterns": ["index", "test-*"],
"allowed_actions": [
"data_access",
"indices_monitor",
],
}
],
}
response = client.security.put_role(role_name, body=role_content)
print(response)
```
#### Getting a role
[API definition](https://opensearch.org/docs/latest/security/access-control/api/#get-role)
```python
print('\Getting a role:')
role_name = "test-role"
response = client.security.get_role(role_name)
print(response)
```
#### Creating a user
[API definition](https://opensearch.org/docs/latest/security/access-control/api/#create-user)
```python
print('\Creating a user:')
user_name = "test-user"
user_content = {"password": "test_password", "opendistro_security_roles": []}
response = client.security.put_role(user_name, body=user_content)
print(response)
```
#### Getting a user
[API definition](https://opensearch.org/docs/latest/security/access-control/api/#get-user)
```python
print('\Getting a user:')
user_name = "test-user"
response = client.security.get_user(user_name)
print(response)
```
## Using different authentication methods ## Using different authentication methods
It is possible to use different methods for the authentication to OpenSearch. The parameters of `connection_class` and `http_auth` can be used for this. The following examples show how to authenticate using IAM credentials and using Kerberos. It is possible to use different methods for the authentication to OpenSearch. The parameters of `connection_class` and `http_auth` can be used for this. The following examples show how to authenticate using IAM credentials and using Kerberos.
+1
View File
@@ -8,4 +8,5 @@ maxdepth: 1
--- ---
plugins/alerting_plugin plugins/alerting_plugin
plugins/security_plugin
``` ```
@@ -0,0 +1,5 @@
# Security Plugin
```{eval-rst}
.. autoclass:: opensearchpy.plugins.security.SecurityClient
```
+3 -2
View File
@@ -10,6 +10,7 @@
import warnings import warnings
from ..plugins.alerting import AlertingClient from ..plugins.alerting import AlertingClient
from ..plugins.security import SecurityClient
from .utils import NamespacedClient from .utils import NamespacedClient
@@ -23,7 +24,7 @@ class PluginsClient(NamespacedClient):
# self.anomaly_detection = AnomalyDetectionClient(client) # self.anomaly_detection = AnomalyDetectionClient(client)
# self.trace_analytics = TraceAnalyticsClient(client) # self.trace_analytics = TraceAnalyticsClient(client)
# self.index_management = IndexManagementClient(client) # self.index_management = IndexManagementClient(client)
# self.security = SecurityClient(client) self.security = SecurityClient(client)
self._dynamic_lookup(client) self._dynamic_lookup(client)
@@ -38,7 +39,7 @@ class PluginsClient(NamespacedClient):
# "anomaly_detection", # "anomaly_detection",
# "trace_analytics", # "trace_analytics",
# "index_management", # "index_management",
# "security" "security",
] ]
for plugin in plugins: for plugin in plugins:
if not hasattr(client, plugin): if not hasattr(client, plugin):
+1
View File
@@ -14,4 +14,5 @@ from .utils import NamespacedClient as NamespacedClient
class PluginsClient(NamespacedClient): class PluginsClient(NamespacedClient):
alerting: Any alerting: Any
security: Any
def __init__(self, client: AsyncOpenSearch) -> None: ... def __init__(self, client: AsyncOpenSearch) -> None: ...
+674
View File
@@ -0,0 +1,674 @@
# 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 ..client.utils import SKIP_IN_PATH, NamespacedClient, _make_path, query_params
class SecurityClient(NamespacedClient):
@query_params()
async def get_account_details(self, params=None, headers=None):
"""
Returns account details for the current user.
"""
return await self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "account"),
params=params,
headers=headers,
)
@query_params()
async def change_password(
self, current_password, password, params=None, headers=None
):
"""
Changes the password for the current user.
"""
return await self.transport.perform_request(
"PUT",
_make_path("_plugins", "_security", "api", "account"),
params=params,
headers=headers,
body={
"current_password": current_password,
"password": password,
},
)
@query_params()
async def get_action_group(self, action_group, params=None, headers=None):
"""
Retrieves one action group.
"""
if action_group in SKIP_IN_PATH:
raise ValueError(
"Empty value passed for a required argument 'action-group'."
)
return await self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "actiongroups", action_group),
params=params,
headers=headers,
)
@query_params()
async def get_action_groups(self, params=None, headers=None):
"""
Retrieves all action groups.
"""
return await self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "actiongroups"),
params=params,
headers=headers,
)
@query_params()
async def delete_action_group(self, action_group, params=None, headers=None):
"""
Deletes the specified action group.
"""
if action_group in SKIP_IN_PATH:
raise ValueError(
"Empty value passed for a required argument 'action-group'."
)
return await self.transport.perform_request(
"DELETE",
_make_path("_plugins", "_security", "api", "actiongroups", action_group),
params=params,
headers=headers,
)
@query_params()
async def put_action_group(self, action_group, body, params=None, headers=None):
"""
Creates or replaces the specified action group.
"""
if action_group in SKIP_IN_PATH:
raise ValueError(
"Empty value passed for a required argument 'action-group'."
)
return await self.transport.perform_request(
"PUT",
_make_path("_plugins", "_security", "api", "actiongroups", action_group),
params=params,
headers=headers,
body=body,
)
@query_params()
async def patch_action_group(self, action_group, body, params=None, headers=None):
"""
Updates individual attributes of an action group.
"""
if action_group in SKIP_IN_PATH:
raise ValueError(
"Empty value passed for a required argument 'action-group'."
)
return await self.transport.perform_request(
"PATCH",
_make_path("_plugins", "_security", "api", "actiongroups", action_group),
params=params,
headers=headers,
body=body,
)
@query_params()
async def patch_action_groups(self, body, params=None, headers=None):
"""
Creates, updates, or deletes multiple action groups in a single call.
"""
return await self.transport.perform_request(
"PATCH",
_make_path("_plugins", "_security", "api", "actiongroups"),
params=params,
headers=headers,
body=body,
)
@query_params()
async def get_user(self, username, params=None, headers=None):
"""
Retrieves one user.
"""
if username in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'username'.")
return await self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "internalusers", username),
params=params,
headers=headers,
)
@query_params()
async def get_users(self, params=None, headers=None):
"""
Retrieves all users.
"""
return await self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "internalusers"),
params=params,
headers=headers,
)
@query_params()
async def delete_user(self, username, params=None, headers=None):
"""
Deletes the specified user.
"""
if username in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'username'.")
return await self.transport.perform_request(
"DELETE",
_make_path("_plugins", "_security", "api", "internalusers", username),
params=params,
headers=headers,
)
@query_params()
async def put_user(self, username, body, params=None, headers=None):
"""
Creates or replaces the specified user.
"""
if username in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'username'.")
return await self.transport.perform_request(
"PUT",
_make_path("_plugins", "_security", "api", "internalusers", username),
params=params,
headers=headers,
body=body,
)
@query_params()
async def patch_user(self, username, body, params=None, headers=None):
"""
Updates individual attributes of an internal user.
"""
if username in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'username'.")
return await self.transport.perform_request(
"PATCH",
_make_path("_plugins", "_security", "api", "internalusers", username),
params=params,
headers=headers,
body=body,
)
@query_params()
async def patch_users(self, body, params=None, headers=None):
"""
Creates, updates, or deletes multiple internal users in a single call.
"""
return await self.transport.perform_request(
"PATCH",
_make_path("_plugins", "_security", "api", "internalusers"),
params=params,
headers=headers,
body=body,
)
@query_params()
async def get_role(self, role, params=None, headers=None):
"""
Retrieves one role.
"""
if role in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'role'.")
return await self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "roles", role),
params=params,
headers=headers,
)
@query_params()
async def get_roles(self, params=None, headers=None):
"""
Retrieves all roles.
"""
return await self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "roles"),
params=params,
headers=headers,
)
@query_params()
async def delete_role(self, role, params=None, headers=None):
"""
Deletes the specified role.
"""
if role in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'role'.")
return await self.transport.perform_request(
"DELETE",
_make_path("_plugins", "_security", "api", "roles", role),
params=params,
headers=headers,
)
@query_params()
async def put_role(self, role, body, params=None, headers=None):
"""
Creates or replaces the specified role.
"""
if role in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'role'.")
return await self.transport.perform_request(
"PUT",
_make_path("_plugins", "_security", "api", "roles", role),
params=params,
headers=headers,
body=body,
)
@query_params()
async def patch_role(self, role, body, params=None, headers=None):
"""
Updates individual attributes of a role.
"""
if role in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'role'.")
return await self.transport.perform_request(
"PATCH",
_make_path("_plugins", "_security", "api", "roles", role),
params=params,
headers=headers,
body=body,
)
@query_params()
async def patch_roles(self, body, params=None, headers=None):
"""
Creates, updates, or deletes multiple roles in a single call.
"""
return await self.transport.perform_request(
"PATCH",
_make_path("_plugins", "_security", "api", "roles"),
params=params,
headers=headers,
body=body,
)
@query_params()
async def get_role_mapping(self, role, params=None, headers=None):
"""
Retrieves one role mapping.
"""
if role in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'role'.")
return await self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "rolesmapping", role),
params=params,
headers=headers,
)
@query_params()
async def get_role_mappings(self, params=None, headers=None):
"""
Retrieves all role mappings.
"""
return await self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "rolesmapping"),
params=params,
headers=headers,
)
@query_params()
async def delete_role_mappings(self, role, params=None, headers=None):
"""
Deletes the specified role mapping.
"""
if role in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'role'.")
return await self.transport.perform_request(
"DELETE",
_make_path("_plugins", "_security", "api", "rolesmapping", role),
params=params,
headers=headers,
)
@query_params()
async def put_role_mappings(self, role, body, params=None, headers=None):
"""
Creates or replaces the specified role mapping.
"""
if role in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'role'.")
return await self.transport.perform_request(
"PUT",
_make_path("_plugins", "_security", "api", "rolesmapping", role),
params=params,
headers=headers,
body=body,
)
@query_params()
async def patch_role_mapping(self, role, body, params=None, headers=None):
"""
Updates individual attributes of a role mapping.
"""
if role in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'role'.")
return await self.transport.perform_request(
"PATCH",
_make_path("_plugins", "_security", "api", "rolesmapping", role),
params=params,
headers=headers,
body=body,
)
@query_params()
async def patch_role_mappings(self, body, params=None, headers=None):
"""
Creates or updates multiple role mappings in a single call.
"""
return await self.transport.perform_request(
"PATCH",
_make_path("_plugins", "_security", "api", "rolesmapping"),
params=params,
headers=headers,
body=body,
)
@query_params()
async def get_tenant(self, tenant, params=None, headers=None):
"""
Retrieves one tenant.
"""
if tenant in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'tenant'.")
return await self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "tenants", tenant),
params=params,
headers=headers,
)
@query_params()
async def get_tenants(self, params=None, headers=None):
"""
Retrieves all tenants.
"""
return await self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "tenants"),
params=params,
headers=headers,
)
@query_params()
async def delete_tenant(self, tenant, params=None, headers=None):
"""
Deletes the specified tenant.
"""
if tenant in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'tenant'.")
return await self.transport.perform_request(
"DELETE",
_make_path("_plugins", "_security", "api", "tenants", tenant),
params=params,
headers=headers,
)
@query_params()
async def put_tenant(self, tenant, body, params=None, headers=None):
"""
Creates or replaces the specified tenant.
"""
if tenant in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'tenant'.")
return await self.transport.perform_request(
"PUT",
_make_path("_plugins", "_security", "api", "tenants", tenant),
params=params,
headers=headers,
body=body,
)
@query_params()
async def patch_tenant(self, tenant, body, params=None, headers=None):
"""
Add, delete, or modify a single tenant.
"""
if tenant in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'tenant'.")
return await self.transport.perform_request(
"PATCH",
_make_path("_plugins", "_security", "api", "tenants", tenant),
params=params,
headers=headers,
body=body,
)
@query_params()
async def patch_tenants(self, body, params=None, headers=None):
"""
Add, delete, or modify multiple tenants in a single call.
"""
return await self.transport.perform_request(
"PATCH",
_make_path("_plugins", "_security", "api", "tenants"),
params=params,
headers=headers,
body=body,
)
@query_params()
async def get_configuration(self, params=None, headers=None):
"""
Retrieves the current Security plugin configuration in JSON format.
"""
return await self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "securityconfig"),
params=params,
headers=headers,
)
@query_params()
async def put_configuration(self, body, params=None, headers=None):
"""
Retrieves the current Security plugin configuration in JSON format.
"""
return await self.transport.perform_request(
"PUT",
_make_path("_plugins", "_security", "api", "securityconfig", "config"),
params=params,
headers=headers,
body=body,
)
@query_params()
async def patch_configuration(self, body, params=None, headers=None):
"""
Updates the existing configuration using the REST API.
"""
return await self.transport.perform_request(
"PATCH",
_make_path("_plugins", "_security", "api", "securityconfig"),
params=params,
headers=headers,
body=body,
)
@query_params()
async def get_distinguished_names(
self, cluster_name=None, params=None, headers=None
):
"""
Retrieves all distinguished names in the allow list.
"""
return await self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "nodesdn", cluster_name),
params=params,
headers=headers,
)
@query_params()
async def put_distinguished_names(
self, cluster_name, body, params=None, headers=None
):
"""
Adds or updates the specified distinguished names in the cluster's or node's allow list.
"""
if cluster_name in SKIP_IN_PATH:
raise ValueError(
"Empty value passed for a required argument 'cluster-name'."
)
return await self.transport.perform_request(
"PUT",
_make_path("_plugins", "_security", "api", "nodesdn", cluster_name),
params=params,
headers=headers,
body=body,
)
@query_params()
async def delete_distinguished_names(self, cluster_name, params=None, headers=None):
"""
Deletes all distinguished names in the specified cluster's or node's allow list.
"""
if cluster_name in SKIP_IN_PATH:
raise ValueError(
"Empty value passed for a required argument 'cluster-name'."
)
return await self.transport.perform_request(
"DELETE",
_make_path("_plugins", "_security", "api", "nodesdn", cluster_name),
params=params,
headers=headers,
)
@query_params()
async def get_certificates(self, params=None, headers=None):
"""
Retrieves the cluster's security certificates.
"""
return await self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "ssl", "certs"),
params=params,
headers=headers,
)
@query_params()
async def reload_transport_certificates(self, params=None, headers=None):
"""
Reloads SSL certificates that are about to expire without restarting the OpenSearch node.
"""
return await self.transport.perform_request(
"PUT",
_make_path(
"_opendistro", "_security", "api", "ssl", "transport", "reloadcerts"
),
params=params,
headers=headers,
)
@query_params()
async def reload_http_certificates(self, params=None, headers=None):
"""
Reloads SSL certificates that are about to expire without restarting the OpenSearch node.
"""
return await self.transport.perform_request(
"PUT",
_make_path("_opendistro", "_security", "api", "ssl", "http", "reloadcerts"),
params=params,
headers=headers,
)
@query_params()
async def flush_cache(self, params=None, headers=None):
"""
Flushes the Security plugin user, authentication, and authorization cache.
"""
return await self.transport.perform_request(
"DELETE",
_make_path("_plugins", "_security", "api", "cache"),
params=params,
headers=headers,
)
@query_params()
async def health_check(self, params=None, headers=None):
"""
Checks to see if the Security plugin is up and running.
"""
return await self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "health"),
params=params,
headers=headers,
)
@query_params()
async def get_audit_configuration(self, params=None, headers=None):
"""
A GET call retrieves the audit configuration.
"""
return await self.transport.perform_request(
"GET",
_make_path("_opendistro", "_security", "api", "audit"),
params=params,
headers=headers,
)
@query_params()
async def put_audit_configuration(self, body, params=None, headers=None):
"""
A PUT call updates the audit configuration.
"""
return await self.transport.perform_request(
"PUT",
_make_path("_opendistro", "_security", "api", "audit", "config"),
params=params,
headers=headers,
body=body,
)
@query_params()
async def patch_audit_configuration(self, body, params=None, headers=None):
"""
A PATCH call is used to update specified fields in the audit configuration.
"""
return await self.transport.perform_request(
"PATCH",
_make_path("_opendistro", "_security", "api", "audit"),
params=params,
headers=headers,
body=body,
)
+207
View File
@@ -0,0 +1,207 @@
# 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 typing import Any, Union
from ..client.utils import NamespacedClient as NamespacedClient
class SecurityClient(NamespacedClient):
async def get_account_details(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def change_password(
self,
current_password: Any,
current_papasswordssword: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Any: ...
async def get_action_group(
self,
action_group: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Any: ...
async def get_action_groups(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def delete_action_group(
self,
action_group: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Any: ...
async def put_action_group(
self,
action_group: Any,
body: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Any: ...
async def patch_action_group(
self,
action_group: Any,
body: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Any: ...
async def patch_action_groups(
self, body: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def get_user(
self,
username: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Any: ...
async def get_users(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def delete_user(
self,
username: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Any: ...
async def put_user(
self,
username: Any,
body: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Any: ...
async def patch_user(
self,
username: Any,
body: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Any: ...
async def patch_users(
self, body: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def get_role(
self, role: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def get_roles(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def delete_role(
self, role: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def put_role(
self, role: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def patch_role(
self, role: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def patch_roles(
self, body: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def get_role_mapping(
self, role: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def get_role_mappings(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def delete_role_mappings(
self, role: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def put_role_mappings(
self, role: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def patch_role_mapping(
self, role: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def patch_role_mappings(
self, body: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def get_tenant(
self,
tenant: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Any: ...
async def get_tenants(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def delete_tenant(
self,
tenant: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Any: ...
async def put_tenant(
self,
tenant: Any,
body: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Any: ...
async def patch_tenant(
self,
tenant: Any,
body: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Any: ...
async def patch_tenants(
self, body: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def get_configuration(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def put_configuration(
self, body: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def patch_configuration(
self, body: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def get_distinguished_names(
self,
cluster_name: Union[Any, None] = ...,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Any: ...
async def put_distinguished_names(
self,
cluster_name: Any,
body: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Any: ...
async def delete_distinguished_names(
self,
cluster_name: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Any: ...
async def get_certificates(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def reload_transport_certificates(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def reload_http_certificates(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def flush_cache(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def health_check(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def get_audit_configuration(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def put_audit_configuration(
self, body: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
async def patch_audit_configuration(
self, body: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Any: ...
+3 -2
View File
@@ -11,6 +11,7 @@
import warnings import warnings
from ..plugins.alerting import AlertingClient from ..plugins.alerting import AlertingClient
from ..plugins.security import SecurityClient
from .utils import NamespacedClient from .utils import NamespacedClient
@@ -24,7 +25,7 @@ class PluginsClient(NamespacedClient):
# self.anomaly_detection = AnomalyDetectionClient(client) # self.anomaly_detection = AnomalyDetectionClient(client)
# self.trace_analytics = TraceAnalyticsClient(client) # self.trace_analytics = TraceAnalyticsClient(client)
# self.index_management = IndexManagementClient(client) # self.index_management = IndexManagementClient(client)
# self.security = SecurityClient(client) self.security = SecurityClient(client)
self._dynamic_lookup(client) self._dynamic_lookup(client)
@@ -39,7 +40,7 @@ class PluginsClient(NamespacedClient):
# "anomaly_detection", # "anomaly_detection",
# "trace_analytics", # "trace_analytics",
# "index_management", # "index_management",
# "security" "security",
] ]
for plugin in plugins: for plugin in plugins:
if not hasattr(client, plugin): if not hasattr(client, plugin):
+1
View File
@@ -14,4 +14,5 @@ from .utils import NamespacedClient as NamespacedClient
class PluginsClient(NamespacedClient): class PluginsClient(NamespacedClient):
alerting: Any alerting: Any
security: Any
def __init__(self, client: OpenSearch) -> None: ... def __init__(self, client: OpenSearch) -> None: ...
+668
View File
@@ -0,0 +1,668 @@
# 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 ..client.utils import SKIP_IN_PATH, NamespacedClient, _make_path, query_params
class SecurityClient(NamespacedClient):
@query_params()
def get_account_details(self, params=None, headers=None):
"""
Returns account details for the current user.
"""
return self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "account"),
params=params,
headers=headers,
)
@query_params()
def change_password(self, current_password, password, params=None, headers=None):
"""
Changes the password for the current user.
"""
return self.transport.perform_request(
"PUT",
_make_path("_plugins", "_security", "api", "account"),
params=params,
headers=headers,
body={
"current_password": current_password,
"password": password,
},
)
@query_params()
def get_action_group(self, action_group, params=None, headers=None):
"""
Retrieves one action group.
"""
if action_group in SKIP_IN_PATH:
raise ValueError(
"Empty value passed for a required argument 'action-group'."
)
return self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "actiongroups", action_group),
params=params,
headers=headers,
)
@query_params()
def get_action_groups(self, params=None, headers=None):
"""
Retrieves all action groups.
"""
return self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "actiongroups"),
params=params,
headers=headers,
)
@query_params()
def delete_action_group(self, action_group, params=None, headers=None):
"""
Deletes the specified action group.
"""
if action_group in SKIP_IN_PATH:
raise ValueError(
"Empty value passed for a required argument 'action-group'."
)
return self.transport.perform_request(
"DELETE",
_make_path("_plugins", "_security", "api", "actiongroups", action_group),
params=params,
headers=headers,
)
@query_params()
def put_action_group(self, action_group, body, params=None, headers=None):
"""
Creates or replaces the specified action group.
"""
if action_group in SKIP_IN_PATH:
raise ValueError(
"Empty value passed for a required argument 'action-group'."
)
return self.transport.perform_request(
"PUT",
_make_path("_plugins", "_security", "api", "actiongroups", action_group),
params=params,
headers=headers,
body=body,
)
@query_params()
def patch_action_group(self, action_group, body, params=None, headers=None):
"""
Updates individual attributes of an action group.
"""
if action_group in SKIP_IN_PATH:
raise ValueError(
"Empty value passed for a required argument 'action-group'."
)
return self.transport.perform_request(
"PATCH",
_make_path("_plugins", "_security", "api", "actiongroups", action_group),
params=params,
headers=headers,
body=body,
)
@query_params()
def patch_action_groups(self, body, params=None, headers=None):
"""
Creates, updates, or deletes multiple action groups in a single call.
"""
return self.transport.perform_request(
"PATCH",
_make_path("_plugins", "_security", "api", "actiongroups"),
params=params,
headers=headers,
body=body,
)
@query_params()
def get_user(self, username, params=None, headers=None):
"""
Retrieves one user.
"""
if username in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'username'.")
return self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "internalusers", username),
params=params,
headers=headers,
)
@query_params()
def get_users(self, params=None, headers=None):
"""
Retrieves all users.
"""
return self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "internalusers"),
params=params,
headers=headers,
)
@query_params()
def delete_user(self, username, params=None, headers=None):
"""
Deletes the specified user.
"""
if username in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'username'.")
return self.transport.perform_request(
"DELETE",
_make_path("_plugins", "_security", "api", "internalusers", username),
params=params,
headers=headers,
)
@query_params()
def put_user(self, username, body, params=None, headers=None):
"""
Creates or replaces the specified user.
"""
if username in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'username'.")
return self.transport.perform_request(
"PUT",
_make_path("_plugins", "_security", "api", "internalusers", username),
params=params,
headers=headers,
body=body,
)
@query_params()
def patch_user(self, username, body, params=None, headers=None):
"""
Updates individual attributes of an internal user.
"""
if username in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'username'.")
return self.transport.perform_request(
"PATCH",
_make_path("_plugins", "_security", "api", "internalusers", username),
params=params,
headers=headers,
body=body,
)
@query_params()
def patch_users(self, body, params=None, headers=None):
"""
Creates, updates, or deletes multiple internal users in a single call.
"""
return self.transport.perform_request(
"PATCH",
_make_path("_plugins", "_security", "api", "internalusers"),
params=params,
headers=headers,
body=body,
)
@query_params()
def get_role(self, role, params=None, headers=None):
"""
Retrieves one role.
"""
if role in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'role'.")
return self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "roles", role),
params=params,
headers=headers,
)
@query_params()
def get_roles(self, params=None, headers=None):
"""
Retrieves all roles.
"""
return self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "roles"),
params=params,
headers=headers,
)
@query_params()
def delete_role(self, role, params=None, headers=None):
"""
Deletes the specified role.
"""
if role in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'role'.")
return self.transport.perform_request(
"DELETE",
_make_path("_plugins", "_security", "api", "roles", role),
params=params,
headers=headers,
)
@query_params()
def put_role(self, role, body, params=None, headers=None):
"""
Creates or replaces the specified role.
"""
if role in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'role'.")
return self.transport.perform_request(
"PUT",
_make_path("_plugins", "_security", "api", "roles", role),
params=params,
headers=headers,
body=body,
)
@query_params()
def patch_role(self, role, body, params=None, headers=None):
"""
Updates individual attributes of a role.
"""
if role in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'role'.")
return self.transport.perform_request(
"PATCH",
_make_path("_plugins", "_security", "api", "roles", role),
params=params,
headers=headers,
body=body,
)
@query_params()
def patch_roles(self, body, params=None, headers=None):
"""
Creates, updates, or deletes multiple roles in a single call.
"""
return self.transport.perform_request(
"PATCH",
_make_path("_plugins", "_security", "api", "roles"),
params=params,
headers=headers,
body=body,
)
@query_params()
def get_role_mapping(self, role, params=None, headers=None):
"""
Retrieves one role mapping.
"""
if role in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'role'.")
return self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "rolesmapping", role),
params=params,
headers=headers,
)
@query_params()
def get_role_mappings(self, params=None, headers=None):
"""
Retrieves all role mappings.
"""
return self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "rolesmapping"),
params=params,
headers=headers,
)
@query_params()
def delete_role_mappings(self, role, params=None, headers=None):
"""
Deletes the specified role mapping.
"""
if role in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'role'.")
return self.transport.perform_request(
"DELETE",
_make_path("_plugins", "_security", "api", "rolesmapping", role),
params=params,
headers=headers,
)
@query_params()
def put_role_mappings(self, role, body, params=None, headers=None):
"""
Creates or replaces the specified role mapping.
"""
if role in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'role'.")
return self.transport.perform_request(
"PUT",
_make_path("_plugins", "_security", "api", "rolesmapping", role),
params=params,
headers=headers,
body=body,
)
@query_params()
def patch_role_mapping(self, role, body, params=None, headers=None):
"""
Updates individual attributes of a role mapping.
"""
if role in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'role'.")
return self.transport.perform_request(
"PATCH",
_make_path("_plugins", "_security", "api", "rolesmapping", role),
params=params,
headers=headers,
body=body,
)
@query_params()
def patch_role_mappings(self, body, params=None, headers=None):
"""
Creates or updates multiple role mappings in a single call.
"""
return self.transport.perform_request(
"PATCH",
_make_path("_plugins", "_security", "api", "rolesmapping"),
params=params,
headers=headers,
body=body,
)
@query_params()
def get_tenant(self, tenant, params=None, headers=None):
"""
Retrieves one tenant.
"""
if tenant in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'tenant'.")
return self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "tenants", tenant),
params=params,
headers=headers,
)
@query_params()
def get_tenants(self, params=None, headers=None):
"""
Retrieves all tenants.
"""
return self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "tenants"),
params=params,
headers=headers,
)
@query_params()
def delete_tenant(self, tenant, params=None, headers=None):
"""
Deletes the specified tenant.
"""
if tenant in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'tenant'.")
return self.transport.perform_request(
"DELETE",
_make_path("_plugins", "_security", "api", "tenants", tenant),
params=params,
headers=headers,
)
@query_params()
def put_tenant(self, tenant, body, params=None, headers=None):
"""
Creates or replaces the specified tenant.
"""
if tenant in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'tenant'.")
return self.transport.perform_request(
"PUT",
_make_path("_plugins", "_security", "api", "tenants", tenant),
params=params,
headers=headers,
body=body,
)
@query_params()
def patch_tenant(self, tenant, body, params=None, headers=None):
"""
Add, delete, or modify a single tenant.
"""
if tenant in SKIP_IN_PATH:
raise ValueError("Empty value passed for a required argument 'tenant'.")
return self.transport.perform_request(
"PATCH",
_make_path("_plugins", "_security", "api", "tenants", tenant),
params=params,
headers=headers,
body=body,
)
@query_params()
def patch_tenants(self, body, params=None, headers=None):
"""
Add, delete, or modify multiple tenants in a single call.
"""
return self.transport.perform_request(
"PATCH",
_make_path("_plugins", "_security", "api", "tenants"),
params=params,
headers=headers,
body=body,
)
@query_params()
def get_configuration(self, params=None, headers=None):
"""
Retrieves the current Security plugin configuration in JSON format.
"""
return self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "securityconfig"),
params=params,
headers=headers,
)
@query_params()
def put_configuration(self, body, params=None, headers=None):
"""
Retrieves the current Security plugin configuration in JSON format.
"""
return self.transport.perform_request(
"PUT",
_make_path("_plugins", "_security", "api", "securityconfig", "config"),
params=params,
headers=headers,
body=body,
)
@query_params()
def patch_configuration(self, body, params=None, headers=None):
"""
Updates the existing configuration using the REST API.
"""
return self.transport.perform_request(
"PATCH",
_make_path("_plugins", "_security", "api", "securityconfig"),
params=params,
headers=headers,
body=body,
)
@query_params()
def get_distinguished_names(self, cluster_name=None, params=None, headers=None):
"""
Retrieves all distinguished names in the allow list.
"""
return self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "nodesdn", cluster_name),
params=params,
headers=headers,
)
@query_params()
def put_distinguished_names(self, cluster_name, body, params=None, headers=None):
"""
Adds or updates the specified distinguished names in the cluster's or node's allow list.
"""
if cluster_name in SKIP_IN_PATH:
raise ValueError(
"Empty value passed for a required argument 'cluster-name'."
)
return self.transport.perform_request(
"PUT",
_make_path("_plugins", "_security", "api", "nodesdn", cluster_name),
params=params,
headers=headers,
body=body,
)
@query_params()
def delete_distinguished_names(self, cluster_name, params=None, headers=None):
"""
Deletes all distinguished names in the specified cluster's or node's allow list.
"""
if cluster_name in SKIP_IN_PATH:
raise ValueError(
"Empty value passed for a required argument 'cluster-name'."
)
return self.transport.perform_request(
"DELETE",
_make_path("_plugins", "_security", "api", "nodesdn", cluster_name),
params=params,
headers=headers,
)
@query_params()
def get_certificates(self, params=None, headers=None):
"""
Retrieves the cluster's security certificates.
"""
return self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "api", "ssl", "certs"),
params=params,
headers=headers,
)
@query_params()
def reload_transport_certificates(self, params=None, headers=None):
"""
Reloads SSL certificates that are about to expire without restarting the OpenSearch node.
"""
return self.transport.perform_request(
"PUT",
_make_path(
"_opendistro", "_security", "api", "ssl", "transport", "reloadcerts"
),
params=params,
headers=headers,
)
@query_params()
def reload_http_certificates(self, params=None, headers=None):
"""
Reloads SSL certificates that are about to expire without restarting the OpenSearch node.
"""
return self.transport.perform_request(
"PUT",
_make_path("_opendistro", "_security", "api", "ssl", "http", "reloadcerts"),
params=params,
headers=headers,
)
@query_params()
def flush_cache(self, params=None, headers=None):
"""
Flushes the Security plugin user, authentication, and authorization cache.
"""
return self.transport.perform_request(
"DELETE",
_make_path("_plugins", "_security", "api", "cache"),
params=params,
headers=headers,
)
@query_params()
def health_check(self, params=None, headers=None):
"""
Checks to see if the Security plugin is up and running.
"""
return self.transport.perform_request(
"GET",
_make_path("_plugins", "_security", "health"),
params=params,
headers=headers,
)
@query_params()
def get_audit_configuration(self, params=None, headers=None):
"""
A GET call retrieves the audit configuration.
"""
return self.transport.perform_request(
"GET",
_make_path("_opendistro", "_security", "api", "audit"),
params=params,
headers=headers,
)
@query_params()
def put_audit_configuration(self, body, params=None, headers=None):
"""
A PUT call updates the audit configuration.
"""
return self.transport.perform_request(
"PUT",
_make_path("_opendistro", "_security", "api", "audit", "config"),
params=params,
headers=headers,
body=body,
)
@query_params()
def patch_audit_configuration(self, body, params=None, headers=None):
"""
A PATCH call is used to update specified fields in the audit configuration.
"""
return self.transport.perform_request(
"PATCH",
_make_path("_opendistro", "_security", "api", "audit"),
params=params,
headers=headers,
body=body,
)
+207
View File
@@ -0,0 +1,207 @@
# 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 typing import Any, Union
from ..client.utils import NamespacedClient as NamespacedClient
class SecurityClient(NamespacedClient):
def get_account_details(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def change_password(
self,
current_password: Any,
current_papasswordssword: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Union[bool, Any]: ...
def get_action_group(
self,
action_group: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Union[bool, Any]: ...
def get_action_groups(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def delete_action_group(
self,
action_group: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Union[bool, Any]: ...
def put_action_group(
self,
action_group: Any,
body: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Union[bool, Any]: ...
def patch_action_group(
self,
action_group: Any,
body: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Union[bool, Any]: ...
def patch_action_groups(
self, body: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def get_user(
self,
username: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Union[bool, Any]: ...
def get_users(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def delete_user(
self,
username: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Union[bool, Any]: ...
def put_user(
self,
username: Any,
body: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Union[bool, Any]: ...
def patch_user(
self,
username: Any,
body: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Union[bool, Any]: ...
def patch_users(
self, body: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def get_role(
self, role: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def get_roles(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def delete_role(
self, role: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def put_role(
self, role: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def patch_role(
self, role: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def patch_roles(
self, body: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def get_role_mapping(
self, role: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def get_role_mappings(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def delete_role_mappings(
self, role: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def put_role_mappings(
self, role: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def patch_role_mapping(
self, role: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def patch_role_mappings(
self, body: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def get_tenant(
self,
tenant: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Union[bool, Any]: ...
def get_tenants(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def delete_tenant(
self,
tenant: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Union[bool, Any]: ...
def put_tenant(
self,
tenant: Any,
body: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Union[bool, Any]: ...
def patch_tenant(
self,
tenant: Any,
body: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Union[bool, Any]: ...
def patch_tenants(
self, body: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def get_configuration(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def put_configuration(
self, body: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def patch_configuration(
self, body: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def get_distinguished_names(
self,
cluster_name: Union[Any, None] = ...,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Union[bool, Any]: ...
def put_distinguished_names(
self,
cluster_name: Any,
body: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Union[bool, Any]: ...
def delete_distinguished_names(
self,
cluster_name: Any,
params: Union[Any, None] = ...,
headers: Union[Any, None] = ...,
) -> Union[bool, Any]: ...
def get_certificates(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def reload_transport_certificates(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def reload_http_certificates(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def flush_cache(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def health_check(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def get_audit_configuration(
self, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def put_audit_configuration(
self, body: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
def patch_audit_configuration(
self, body: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ...
) -> Union[bool, Any]: ...
+2
View File
@@ -38,6 +38,8 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler):
class TestHTTPServer(HTTPServer): class TestHTTPServer(HTTPServer):
__test__ = False
def __init__(self, host="localhost", port=8080): def __init__(self, host="localhost", port=8080):
super().__init__((host, port), TestHTTPRequestHandler) super().__init__((host, port), TestHTTPRequestHandler)
self._server_thread = None self._server_thread = None
+3
View File
@@ -121,6 +121,7 @@ def run_all(argv=None):
"test_opensearchpy/test_server/", "test_opensearchpy/test_server/",
"test_opensearchpy/test_server_secured/", "test_opensearchpy/test_server_secured/",
"test_opensearchpy/test_async/test_server/", "test_opensearchpy/test_async/test_server/",
"test_opensearchpy/test_async/test_server_secured/",
] ]
) )
@@ -129,6 +130,8 @@ def run_all(argv=None):
test_dir = abspath(dirname(__file__)) test_dir = abspath(dirname(__file__))
if secured: if secured:
argv.append(join(test_dir, "test_server_secured")) argv.append(join(test_dir, "test_server_secured"))
if sys.version_info >= (3, 6):
argv.append(join(test_dir, "test_async/test_server_secured"))
ignores.extend( ignores.extend(
[ [
"test_opensearchpy/test_server/", "test_opensearchpy/test_server/",
@@ -9,15 +9,25 @@
# GitHub history for details. # GitHub history for details.
import sys import sys
import uuid
import pytest import pytest
from mock import Mock
from ..test_cases import TestCase
pytestmark = pytest.mark.asyncio pytestmark = pytest.mark.asyncio
class TestAsyncSigner(TestCase): class TestAsyncSigner:
def mock_session(self):
access_key = uuid.uuid4().hex
secret_key = uuid.uuid4().hex
token = uuid.uuid4().hex
dummy_session = Mock()
dummy_session.access_key = access_key
dummy_session.secret_key = secret_key
dummy_session.token = token
return dummy_session
@pytest.mark.skipif( @pytest.mark.skipif(
sys.version_info < (3, 6), reason="AWSV4SignerAsyncAuth requires python3.6+" sys.version_info < (3, 6), reason="AWSV4SignerAsyncAuth requires python3.6+"
) )
@@ -27,10 +37,10 @@ class TestAsyncSigner(TestCase):
from opensearchpy.helpers.asyncsigner import AWSV4SignerAsyncAuth from opensearchpy.helpers.asyncsigner import AWSV4SignerAsyncAuth
auth = AWSV4SignerAsyncAuth(self.mock_session(), region) auth = AWSV4SignerAsyncAuth(self.mock_session(), region)
headers = auth("GET", "http://localhost") headers = auth("GET", "http://localhost", {}, {})
self.assertIn("Authorization", headers) assert "Authorization" in headers
self.assertIn("X-Amz-Date", headers) assert "X-Amz-Date" in headers
self.assertIn("X-Amz-Security-Token", headers) assert "X-Amz-Security-Token" in headers
@pytest.mark.skipif( @pytest.mark.skipif(
sys.version_info < (3, 6), reason="AWSV4SignerAuth requires python3.6+" sys.version_info < (3, 6), reason="AWSV4SignerAuth requires python3.6+"
@@ -60,9 +70,6 @@ class TestAsyncSigner(TestCase):
AWSV4SignerAsyncAuth(None, region) AWSV4SignerAsyncAuth(None, region)
assert str(e.value) == "Credentials cannot be empty" assert str(e.value) == "Credentials cannot be empty"
with pytest.raises(ValueError) as e:
assert str(e.value) == "Credentials cannot be empty"
@pytest.mark.skipif( @pytest.mark.skipif(
sys.version_info < (3, 6), reason="AWSV4SignerAsyncAuth requires python3.6+" sys.version_info < (3, 6), reason="AWSV4SignerAsyncAuth requires python3.6+"
) )
@@ -73,8 +80,8 @@ class TestAsyncSigner(TestCase):
from opensearchpy.helpers.asyncsigner import AWSV4SignerAsyncAuth from opensearchpy.helpers.asyncsigner import AWSV4SignerAsyncAuth
auth = AWSV4SignerAsyncAuth(self.mock_session(), region, service) auth = AWSV4SignerAsyncAuth(self.mock_session(), region, service)
headers = auth("GET", "http://localhost") headers = auth("GET", "http://localhost", {}, {})
self.assertIn("Authorization", headers) assert "Authorization" in headers
self.assertIn("X-Amz-Date", headers) assert "X-Amz-Date" in headers
self.assertIn("X-Amz-Security-Token", headers) assert "X-Amz-Security-Token" in headers
self.assertIn("X-Amz-Content-SHA256", headers) assert "X-Amz-Content-SHA256" in headers
+14 -14
View File
@@ -100,7 +100,7 @@ class TestAIOHttpConnection:
assert con.use_ssl assert con.use_ssl
assert con.session.connector._ssl == context assert con.session.connector._ssl == context
def test_opaque_id(self): async def test_opaque_id(self):
con = AIOHttpConnection(opaque_id="app-1") con = AIOHttpConnection(opaque_id="app-1")
assert con.headers["x-opaque-id"] == "app-1" assert con.headers["x-opaque-id"] == "app-1"
@@ -154,18 +154,18 @@ class TestAIOHttpConnection:
method, yarl_url = con.session.request.call_args[0] method, yarl_url = con.session.request.call_args[0]
assert method == "GET" and str(yarl_url) == "http://localhost:9200/_search/" assert method == "GET" and str(yarl_url) == "http://localhost:9200/_search/"
def test_default_user_agent(self): async def test_default_user_agent(self):
con = AIOHttpConnection() con = AIOHttpConnection()
assert con._get_default_user_agent() == "opensearch-py/%s (Python %s)" % ( assert con._get_default_user_agent() == "opensearch-py/%s (Python %s)" % (
__versionstr__, __versionstr__,
python_version(), python_version(),
) )
def test_timeout_set(self): async def test_timeout_set(self):
con = AIOHttpConnection(timeout=42) con = AIOHttpConnection(timeout=42)
assert 42 == con.timeout assert 42 == con.timeout
def test_keep_alive_is_on_by_default(self): async def test_keep_alive_is_on_by_default(self):
con = AIOHttpConnection() con = AIOHttpConnection()
assert { assert {
"connection": "keep-alive", "connection": "keep-alive",
@@ -173,7 +173,7 @@ class TestAIOHttpConnection:
"user-agent": con._get_default_user_agent(), "user-agent": con._get_default_user_agent(),
} == con.headers } == con.headers
def test_http_auth(self): async def test_http_auth(self):
con = AIOHttpConnection(http_auth="username:secret") con = AIOHttpConnection(http_auth="username:secret")
assert { assert {
"authorization": "Basic dXNlcm5hbWU6c2VjcmV0", "authorization": "Basic dXNlcm5hbWU6c2VjcmV0",
@@ -182,7 +182,7 @@ class TestAIOHttpConnection:
"user-agent": con._get_default_user_agent(), "user-agent": con._get_default_user_agent(),
} == con.headers } == con.headers
def test_http_auth_tuple(self): async def test_http_auth_tuple(self):
con = AIOHttpConnection(http_auth=("username", "secret")) con = AIOHttpConnection(http_auth=("username", "secret"))
assert { assert {
"authorization": "Basic dXNlcm5hbWU6c2VjcmV0", "authorization": "Basic dXNlcm5hbWU6c2VjcmV0",
@@ -191,7 +191,7 @@ class TestAIOHttpConnection:
"user-agent": con._get_default_user_agent(), "user-agent": con._get_default_user_agent(),
} == con.headers } == con.headers
def test_http_auth_list(self): async def test_http_auth_list(self):
con = AIOHttpConnection(http_auth=["username", "secret"]) con = AIOHttpConnection(http_auth=["username", "secret"])
assert { assert {
"authorization": "Basic dXNlcm5hbWU6c2VjcmV0", "authorization": "Basic dXNlcm5hbWU6c2VjcmV0",
@@ -200,7 +200,7 @@ class TestAIOHttpConnection:
"user-agent": con._get_default_user_agent(), "user-agent": con._get_default_user_agent(),
} == con.headers } == con.headers
def test_uses_https_if_verify_certs_is_off(self): async def test_uses_https_if_verify_certs_is_off(self):
with warnings.catch_warnings(record=True) as w: with warnings.catch_warnings(record=True) as w:
con = AIOHttpConnection(use_ssl=True, verify_certs=False) con = AIOHttpConnection(use_ssl=True, verify_certs=False)
assert 1 == len(w) assert 1 == len(w)
@@ -223,17 +223,17 @@ class TestAIOHttpConnection:
assert isinstance(con.session, aiohttp.ClientSession) assert isinstance(con.session, aiohttp.ClientSession)
def test_doesnt_use_https_if_not_specified(self): async def test_doesnt_use_https_if_not_specified(self):
con = AIOHttpConnection() con = AIOHttpConnection()
assert not con.use_ssl assert not con.use_ssl
def test_no_warning_when_using_ssl_context(self): async def test_no_warning_when_using_ssl_context(self):
ctx = ssl.create_default_context() ctx = ssl.create_default_context()
with warnings.catch_warnings(record=True) as w: with warnings.catch_warnings(record=True) as w:
AIOHttpConnection(ssl_context=ctx) AIOHttpConnection(ssl_context=ctx)
assert w == [], str([x.message for x in w]) assert w == [], str([x.message for x in w])
def test_warns_if_using_non_default_ssl_kwargs_with_ssl_context(self): async def test_warns_if_using_non_default_ssl_kwargs_with_ssl_context(self):
for kwargs in ( for kwargs in (
{"ssl_show_warn": False}, {"ssl_show_warn": False},
{"ssl_show_warn": True}, {"ssl_show_warn": True},
@@ -256,21 +256,21 @@ class TestAIOHttpConnection:
) )
@patch("ssl.SSLContext.load_verify_locations") @patch("ssl.SSLContext.load_verify_locations")
def test_uses_given_ca_certs(self, load_verify_locations, tmp_path): async def test_uses_given_ca_certs(self, load_verify_locations, tmp_path):
path = tmp_path / "ca_certs.pem" path = tmp_path / "ca_certs.pem"
path.touch() path.touch()
AIOHttpConnection(use_ssl=True, ca_certs=str(path)) AIOHttpConnection(use_ssl=True, ca_certs=str(path))
load_verify_locations.assert_called_once_with(cafile=str(path)) load_verify_locations.assert_called_once_with(cafile=str(path))
@patch("ssl.SSLContext.load_verify_locations") @patch("ssl.SSLContext.load_verify_locations")
def test_uses_default_ca_certs(self, load_verify_locations): async def test_uses_default_ca_certs(self, load_verify_locations):
AIOHttpConnection(use_ssl=True) AIOHttpConnection(use_ssl=True)
load_verify_locations.assert_called_once_with( load_verify_locations.assert_called_once_with(
cafile=Connection.default_ca_certs() cafile=Connection.default_ca_certs()
) )
@patch("ssl.SSLContext.load_verify_locations") @patch("ssl.SSLContext.load_verify_locations")
def test_uses_no_ca_certs(self, load_verify_locations): async def test_uses_no_ca_certs(self, load_verify_locations):
AIOHttpConnection(use_ssl=True, verify_certs=False) AIOHttpConnection(use_ssl=True, verify_certs=False)
load_verify_locations.assert_not_called() load_verify_locations.assert_not_called()
@@ -0,0 +1,25 @@
# 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.
#
# Licensed to Elasticsearch B.V. under one or more contributor
# license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright
# ownership. Elasticsearch B.V. licenses this file to you under
# the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
@@ -83,7 +83,7 @@ async def test_cloned_index_has_analysis_attribute():
assert i.to_dict()["settings"]["analysis"] == i2.to_dict()["settings"]["analysis"] assert i.to_dict()["settings"]["analysis"] == i2.to_dict()["settings"]["analysis"]
def test_settings_are_saved(): async def test_settings_are_saved():
i = AsyncIndex("i") i = AsyncIndex("i")
i.settings(number_of_replicas=0) i.settings(number_of_replicas=0)
i.settings(number_of_shards=1) i.settings(number_of_shards=1)
@@ -0,0 +1,25 @@
# 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.
#
# Licensed to Elasticsearch B.V. under one or more contributor
# license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright
# ownership. Elasticsearch B.V. licenses this file to you under
# the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
@@ -13,18 +13,18 @@ from datetime import datetime
import pytest import pytest
from pytest import fixture from pytest import fixture
from test_data import (
from opensearchpy._async.helpers.actions import async_bulk
from opensearchpy._async.helpers.test import get_test_client
from opensearchpy.connection.async_connections import add_connection
from test_opensearchpy.test_async.test_server.test_helpers.test_data import (
DATA, DATA,
FLAT_DATA, FLAT_DATA,
TEST_GIT_DATA, TEST_GIT_DATA,
create_flat_git_index, create_flat_git_index,
create_git_index, create_git_index,
) )
from test_opensearchpy.test_async.test_server.test_helpers.test_document import (
from opensearchpy._async.helpers.actions import async_bulk
from opensearchpy._async.helpers.test import get_test_client
from opensearchpy.connection.async_connections import add_connection
from test_opensearchpy.test_server.test_helpers.test_document import (
Comment, Comment,
History, History,
PullRequest, PullRequest,
@@ -79,8 +79,8 @@ async def data_client(client):
@fixture @fixture
def pull_request(write_client): async def pull_request(write_client):
PullRequest.init() await PullRequest.init()
pr = PullRequest( pr = PullRequest(
_id=42, _id=42,
comments=[ comments=[
@@ -98,7 +98,7 @@ def pull_request(write_client):
], ],
created_at=datetime(2018, 1, 9, 9, 17, 3, 21184), created_at=datetime(2018, 1, 9, 9, 17, 3, 21184),
) )
pr.save(refresh=True) await pr.save(refresh=True)
return pr return pr
@@ -16,7 +16,7 @@ from opensearchpy import Date, Keyword, Q, Text, TransportError
from opensearchpy._async.helpers.document import AsyncDocument from opensearchpy._async.helpers.document import AsyncDocument
from opensearchpy._async.helpers.search import AsyncMultiSearch, AsyncSearch from opensearchpy._async.helpers.search import AsyncMultiSearch, AsyncSearch
from opensearchpy.helpers.response import aggs from opensearchpy.helpers.response import aggs
from test_opensearchpy.test_server.test_helpers.test_data import FLAT_DATA from test_opensearchpy.test_async.test_server.test_helpers.test_data import FLAT_DATA
pytestmark = pytest.mark.asyncio pytestmark = pytest.mark.asyncio
@@ -0,0 +1,8 @@
# 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.
@@ -0,0 +1,160 @@
# -*- coding: utf-8 -*-
# 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
from unittest import IsolatedAsyncioTestCase
import pytest
from opensearchpy._async.helpers.test import get_test_client
from opensearchpy.connection.async_connections import add_connection
from opensearchpy.exceptions import NotFoundError
pytestmark = pytest.mark.asyncio
class TestSecurityPlugin(IsolatedAsyncioTestCase):
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"
USER_CONTENT = {"password": "test_password", "opendistro_security_roles": []}
async def asyncSetUp(self):
self.client = await get_test_client(
verify_certs=False, http_auth=("admin", "admin")
)
await add_connection("default", self.client)
async def asyncTearDown(self):
if self.client:
await self.client.close()
async def test_create_role(self):
# Test to create role
response = await self.client.security.put_role(
self.ROLE_NAME, body=self.ROLE_CONTENT
)
self.assertNotIn("errors", response)
self.assertIn(response.get("status"), ["CREATED", "OK"])
async def test_get_role(self):
# Create a role
await self.test_create_role()
# Test to fetch the role
response = await self.client.security.get_role(self.ROLE_NAME)
self.assertNotIn("errors", response)
self.assertIn(self.ROLE_NAME, response)
async def test_update_role(self):
# Create a role
await self.test_create_role()
role_content = self.ROLE_CONTENT.copy()
role_content["cluster_permissions"] = ["cluster_all"]
# Test to update role
response = await self.client.security.put_role(
self.ROLE_NAME, body=role_content
)
self.assertNotIn("errors", response)
self.assertEqual("OK", response.get("status"))
async def test_delete_role(self):
# Create a role
await self.test_create_role()
# Test to delete the role
response = await self.client.security.delete_role(self.ROLE_NAME)
self.assertNotIn("errors", response)
# Try fetching the role
with self.assertRaises(NotFoundError):
response = await self.client.security.get_role(self.ROLE_NAME)
async def test_create_user(self):
# Test to create user
response = await self.client.security.put_user(
self.USER_NAME, body=self.USER_CONTENT
)
self.assertNotIn("errors", response)
self.assertIn(response.get("status"), ["CREATED", "OK"])
async def test_create_user_with_role(self):
await self.test_create_role()
# Test to create user
response = await self.client.security.put_user(
self.USER_NAME,
body={
"password": "test_password",
"opendistro_security_roles": [self.ROLE_NAME],
},
)
self.assertNotIn("errors", response)
self.assertIn(response.get("status"), ["CREATED", "OK"])
async def test_get_user(self):
# Create a user
await self.test_create_user()
# Test to fetch the user
response = await self.client.security.get_user(self.USER_NAME)
self.assertNotIn("errors", response)
self.assertIn(self.USER_NAME, response)
async def test_update_user(self):
# Create a user
await self.test_create_user()
user_content = self.USER_CONTENT.copy()
user_content["password"] = "password_test"
# Test to update user
response = await self.client.security.put_user(
self.USER_NAME, body=user_content
)
self.assertNotIn("errors", response)
self.assertEqual("OK", response.get("status"))
async def test_delete_user(self):
# Create a user
await self.test_create_user()
# Test to delete the user
response = await self.client.security.delete_user(self.USER_NAME)
self.assertNotIn("errors", response)
# Try fetching the user
with self.assertRaises(NotFoundError):
response = await self.client.security.get_user(self.USER_NAME)
@@ -259,7 +259,7 @@ class TestTransport:
assert 1 == len(t.connection_pool.connections) assert 1 == len(t.connection_pool.connections)
assert isinstance(t.connection_pool.connections[0], MyConnection) assert isinstance(t.connection_pool.connections[0], MyConnection)
def test_add_connection(self): async def test_add_connection(self):
t = AsyncTransport([{}], randomize_hosts=False) t = AsyncTransport([{}], randomize_hosts=False)
t.add_connection({"host": "google.com", "port": 1234}) t.add_connection({"host": "google.com", "port": 1234})
@@ -0,0 +1,146 @@
# -*- coding: utf-8 -*-
# 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
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"
USER_CONTENT = {"password": "test_password", "opendistro_security_roles": []}
def setUp(self):
self.client = get_test_client(verify_certs=False, http_auth=("admin", "admin"))
add_connection("default", self.client)
def tearDown(self):
if self.client:
self.client.close()
def test_create_role(self):
# Test to create role
response = self.client.security.put_role(self.ROLE_NAME, body=self.ROLE_CONTENT)
self.assertNotIn("errors", response)
self.assertIn(response.get("status"), ["CREATED", "OK"])
def test_get_role(self):
# 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)
def test_update_role(self):
# Create a role
self.test_create_role()
role_content = self.ROLE_CONTENT.copy()
role_content["cluster_permissions"] = ["cluster_all"]
# Test to update role
response = self.client.security.put_role(self.ROLE_NAME, body=role_content)
self.assertNotIn("errors", response)
self.assertEqual("OK", response.get("status"))
def test_delete_role(self):
# 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)
def test_create_user(self):
# Test to create user
response = self.client.security.put_user(self.USER_NAME, body=self.USER_CONTENT)
self.assertNotIn("errors", response)
self.assertIn(response.get("status"), ["CREATED", "OK"])
def test_create_user_with_role(self):
self.test_create_role()
# Test to create user
response = self.client.security.put_user(
self.USER_NAME,
body={
"password": "test_password",
"opendistro_security_roles": [self.ROLE_NAME],
},
)
self.assertNotIn("errors", response)
self.assertIn(response.get("status"), ["CREATED", "OK"])
def test_get_user(self):
# 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)
def test_update_user(self):
# Create a user
self.test_create_user()
user_content = self.USER_CONTENT.copy()
user_content["password"] = "password_test"
# Test to update user
response = self.client.security.put_user(self.USER_NAME, body=user_content)
self.assertNotIn("errors", response)
self.assertEqual("OK", response.get("status"))
def test_delete_user(self):
# 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)