Security plugin support (#399)

* feat(plugins): add security client plugin

Signed-off-by: florian <florian@harfanglab.fr>

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

Signed-off-by: florian <florian@harfanglab.fr>

* fix(security): remove non-ASCII character

Signed-off-by: florian <florian@harfanglab.fr>

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

Signed-off-by: florian <florian@harfanglab.fr>

* test(plugins): add asynchronous tests version

Signed-off-by: florian <florian@harfanglab.fr>

* test: remove some warnings

Signed-off-by: florian <florian@harfanglab.fr>

* chore(USER_GUIDE): add a security plugin part

Signed-off-by: florian <florian@harfanglab.fr>

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

Signed-off-by: florian <florian@harfanglab.fr>

* chore: apply reviews

Signed-off-by: florian <florian@harfanglab.fr>

---------

Signed-off-by: florian <florian@harfanglab.fr>
This commit is contained in:
florianvazelle
2023-06-27 17:01:40 +02: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 \
--name "$node_name" \
--network "$network_name" \
--env "ES_JAVA_OPTS=-Xms1g -Xmx1g" \
--env "OPENSEARCH_JAVA_OPTS=-Xms1g -Xmx1g" \
"${environment[@]}" \
"${volumes[@]}" \
"${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 '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 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))
- 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)
+65
View File
@@ -21,6 +21,11 @@
- [**Creating a destination**](#creating-a-destination)
- [**Getting alerts**](#getting-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 IAM credentials](#using-iam-credentials)
- [Pre-requisites to use `AWSV4SignerAuth`](#pre-requisites-to-use-awsv4signerauth)
@@ -420,6 +425,66 @@ query = {
response = client.plugins.alerting.acknowledge_alert(query)
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
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/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
from ..plugins.alerting import AlertingClient
from ..plugins.security import SecurityClient
from .utils import NamespacedClient
@@ -23,7 +24,7 @@ class PluginsClient(NamespacedClient):
# self.anomaly_detection = AnomalyDetectionClient(client)
# self.trace_analytics = TraceAnalyticsClient(client)
# self.index_management = IndexManagementClient(client)
# self.security = SecurityClient(client)
self.security = SecurityClient(client)
self._dynamic_lookup(client)
@@ -38,7 +39,7 @@ class PluginsClient(NamespacedClient):
# "anomaly_detection",
# "trace_analytics",
# "index_management",
# "security"
"security",
]
for plugin in plugins:
if not hasattr(client, plugin):
+1
View File
@@ -14,4 +14,5 @@ from .utils import NamespacedClient as NamespacedClient
class PluginsClient(NamespacedClient):
alerting: Any
security: Any
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
from ..plugins.alerting import AlertingClient
from ..plugins.security import SecurityClient
from .utils import NamespacedClient
@@ -24,7 +25,7 @@ class PluginsClient(NamespacedClient):
# self.anomaly_detection = AnomalyDetectionClient(client)
# self.trace_analytics = TraceAnalyticsClient(client)
# self.index_management = IndexManagementClient(client)
# self.security = SecurityClient(client)
self.security = SecurityClient(client)
self._dynamic_lookup(client)
@@ -39,7 +40,7 @@ class PluginsClient(NamespacedClient):
# "anomaly_detection",
# "trace_analytics",
# "index_management",
# "security"
"security",
]
for plugin in plugins:
if not hasattr(client, plugin):
+1
View File
@@ -14,4 +14,5 @@ from .utils import NamespacedClient as NamespacedClient
class PluginsClient(NamespacedClient):
alerting: Any
security: Any
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):
__test__ = False
def __init__(self, host="localhost", port=8080):
super().__init__((host, port), TestHTTPRequestHandler)
self._server_thread = None
+3
View File
@@ -121,6 +121,7 @@ def run_all(argv=None):
"test_opensearchpy/test_server/",
"test_opensearchpy/test_server_secured/",
"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__))
if 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(
[
"test_opensearchpy/test_server/",
@@ -9,15 +9,25 @@
# GitHub history for details.
import sys
import uuid
import pytest
from ..test_cases import TestCase
from mock import Mock
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(
sys.version_info < (3, 6), reason="AWSV4SignerAsyncAuth requires python3.6+"
)
@@ -27,10 +37,10 @@ class TestAsyncSigner(TestCase):
from opensearchpy.helpers.asyncsigner import AWSV4SignerAsyncAuth
auth = AWSV4SignerAsyncAuth(self.mock_session(), region)
headers = auth("GET", "http://localhost")
self.assertIn("Authorization", headers)
self.assertIn("X-Amz-Date", headers)
self.assertIn("X-Amz-Security-Token", headers)
headers = auth("GET", "http://localhost", {}, {})
assert "Authorization" in headers
assert "X-Amz-Date" in headers
assert "X-Amz-Security-Token" in headers
@pytest.mark.skipif(
sys.version_info < (3, 6), reason="AWSV4SignerAuth requires python3.6+"
@@ -60,9 +70,6 @@ class TestAsyncSigner(TestCase):
AWSV4SignerAsyncAuth(None, region)
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(
sys.version_info < (3, 6), reason="AWSV4SignerAsyncAuth requires python3.6+"
)
@@ -73,8 +80,8 @@ class TestAsyncSigner(TestCase):
from opensearchpy.helpers.asyncsigner import AWSV4SignerAsyncAuth
auth = AWSV4SignerAsyncAuth(self.mock_session(), region, service)
headers = auth("GET", "http://localhost")
self.assertIn("Authorization", headers)
self.assertIn("X-Amz-Date", headers)
self.assertIn("X-Amz-Security-Token", headers)
self.assertIn("X-Amz-Content-SHA256", headers)
headers = auth("GET", "http://localhost", {}, {})
assert "Authorization" in headers
assert "X-Amz-Date" in headers
assert "X-Amz-Security-Token" in headers
assert "X-Amz-Content-SHA256" in headers
+14 -14
View File
@@ -100,7 +100,7 @@ class TestAIOHttpConnection:
assert con.use_ssl
assert con.session.connector._ssl == context
def test_opaque_id(self):
async def test_opaque_id(self):
con = AIOHttpConnection(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]
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()
assert con._get_default_user_agent() == "opensearch-py/%s (Python %s)" % (
__versionstr__,
python_version(),
)
def test_timeout_set(self):
async def test_timeout_set(self):
con = AIOHttpConnection(timeout=42)
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()
assert {
"connection": "keep-alive",
@@ -173,7 +173,7 @@ class TestAIOHttpConnection:
"user-agent": con._get_default_user_agent(),
} == con.headers
def test_http_auth(self):
async def test_http_auth(self):
con = AIOHttpConnection(http_auth="username:secret")
assert {
"authorization": "Basic dXNlcm5hbWU6c2VjcmV0",
@@ -182,7 +182,7 @@ class TestAIOHttpConnection:
"user-agent": con._get_default_user_agent(),
} == con.headers
def test_http_auth_tuple(self):
async def test_http_auth_tuple(self):
con = AIOHttpConnection(http_auth=("username", "secret"))
assert {
"authorization": "Basic dXNlcm5hbWU6c2VjcmV0",
@@ -191,7 +191,7 @@ class TestAIOHttpConnection:
"user-agent": con._get_default_user_agent(),
} == con.headers
def test_http_auth_list(self):
async def test_http_auth_list(self):
con = AIOHttpConnection(http_auth=["username", "secret"])
assert {
"authorization": "Basic dXNlcm5hbWU6c2VjcmV0",
@@ -200,7 +200,7 @@ class TestAIOHttpConnection:
"user-agent": con._get_default_user_agent(),
} == 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:
con = AIOHttpConnection(use_ssl=True, verify_certs=False)
assert 1 == len(w)
@@ -223,17 +223,17 @@ class TestAIOHttpConnection:
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()
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()
with warnings.catch_warnings(record=True) as w:
AIOHttpConnection(ssl_context=ctx)
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 (
{"ssl_show_warn": False},
{"ssl_show_warn": True},
@@ -256,21 +256,21 @@ class TestAIOHttpConnection:
)
@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.touch()
AIOHttpConnection(use_ssl=True, ca_certs=str(path))
load_verify_locations.assert_called_once_with(cafile=str(path))
@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)
load_verify_locations.assert_called_once_with(
cafile=Connection.default_ca_certs()
)
@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)
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"]
def test_settings_are_saved():
async def test_settings_are_saved():
i = AsyncIndex("i")
i.settings(number_of_replicas=0)
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
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,
FLAT_DATA,
TEST_GIT_DATA,
create_flat_git_index,
create_git_index,
)
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 (
from test_opensearchpy.test_async.test_server.test_helpers.test_document import (
Comment,
History,
PullRequest,
@@ -79,8 +79,8 @@ async def data_client(client):
@fixture
def pull_request(write_client):
PullRequest.init()
async def pull_request(write_client):
await PullRequest.init()
pr = PullRequest(
_id=42,
comments=[
@@ -98,7 +98,7 @@ def pull_request(write_client):
],
created_at=datetime(2018, 1, 9, 9, 17, 3, 21184),
)
pr.save(refresh=True)
await pr.save(refresh=True)
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.search import AsyncMultiSearch, AsyncSearch
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
@@ -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 isinstance(t.connection_pool.connections[0], MyConnection)
def test_add_connection(self):
async def test_add_connection(self):
t = AsyncTransport([{}], randomize_hosts=False)
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)