Skip to content

Commit

Permalink
Add documentation.
Browse files Browse the repository at this point in the history
Signed-off-by: dblock <[email protected]>
  • Loading branch information
dblock committed Oct 20, 2023
1 parent 6500c2b commit f8f2b62
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 48 deletions.
2 changes: 1 addition & 1 deletion DEVELOPER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ You can also run individual tests matching a pattern (`pytest -k [pattern]`).
```
./.ci/run-tests true 1.3.0 test_no_http_compression
test_opensearchpy/test_connection.py::TestUrllib3Connection::test_no_http_compression PASSED [ 33%]
test_opensearchpy/test_connection.py::TestUrllib3HttpConnection::test_no_http_compression PASSED [ 33%]
test_opensearchpy/test_connection.py::TestRequestsConnection::test_no_http_compression PASSED [ 66%]
test_opensearchpy/test_async/test_connection.py::TestAIOHttpConnection::test_no_http_compression PASSED [100%]
```
Expand Down
8 changes: 4 additions & 4 deletions guides/auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,24 @@ OpenSearch allows you to use different methods for the authentication via `conne

## IAM Authentication

Opensearch-py supports IAM-based authentication via `AWSV4SignerAuth`, which uses `RequestHttpConnection` as the transport class for communicating with OpenSearch clusters running in Amazon Managed OpenSearch and OpenSearch Serverless, and works in conjunction with [botocore](https://pypi.org/project/botocore/).
Opensearch-py supports IAM-based authentication via `RequestsAWSV4SignerAuth` and `Urllib3AWSV4SignerAuth`, which use `RequestHttpConnection` and `Urllib3HttpConnection` respectively, as the transport classes for communicating with OpenSearch clusters running in Amazon Managed OpenSearch and OpenSearch Serverless, and works in conjunction with [botocore](https://pypi.org/project/botocore/).

```python
from opensearchpy import OpenSearch, RequestsHttpConnection, AWSV4SignerAuth
from opensearchpy import OpenSearch, Urllib3HttpConnection, Urllib3AWSV4SignerAuth
import boto3

host = '' # cluster endpoint, for example: my-test-domain.us-east-1.es.amazonaws.com
region = 'us-west-2'
service = 'es' # 'aoss' for OpenSearch Serverless
credentials = boto3.Session().get_credentials()
auth = AWSV4SignerAuth(credentials, region, service)
auth = Urllib3AWSV4SignerAuth(credentials, region, service)

client = OpenSearch(
hosts = [{'host': host, 'port': 443}],
http_auth = auth,
use_ssl = True,
verify_certs = True,
connection_class = RequestsHttpConnection,
connection_class = Urllib3HttpConnection,
pool_maxsize = 20
)

Expand Down
4 changes: 2 additions & 2 deletions opensearchpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
AWSV4SignerAsyncAuth,
AWSV4SignerAuth,
RequestsAWSV4SignerAuth,
UrlLib3AWSV4SignerAuth,
Urllib3AWSV4SignerAuth,
)
from .helpers.aggs import A
from .helpers.analysis import analyzer, char_filter, normalizer, token_filter, tokenizer
Expand Down Expand Up @@ -171,7 +171,7 @@
"OpenSearchWarning",
"OpenSearchDeprecationWarning",
"AWSV4SignerAuth",
"UrlLib3AWSV4SignerAuth",
"Urllib3AWSV4SignerAuth",
"RequestsAWSV4SignerAuth",
"AWSV4SignerAsyncAuth",
"A",
Expand Down
4 changes: 2 additions & 2 deletions opensearchpy/helpers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
)
from .asyncsigner import AWSV4SignerAsyncAuth
from .errors import BulkIndexError, ScanError
from .signer import AWSV4SignerAuth, RequestsAWSV4SignerAuth, UrlLib3AWSV4SignerAuth
from .signer import AWSV4SignerAuth, RequestsAWSV4SignerAuth, Urllib3AWSV4SignerAuth

__all__ = [
"BulkIndexError",
Expand All @@ -55,7 +55,7 @@
"AWSV4SignerAuth",
"AWSV4SignerAsyncAuth",
"RequestsAWSV4SignerAuth",
"UrlLib3AWSV4SignerAuth",
"Urllib3AWSV4SignerAuth",
]


Expand Down
2 changes: 1 addition & 1 deletion opensearchpy/helpers/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,6 @@ try:
from .._async.helpers.actions import async_streaming_bulk as async_streaming_bulk
from .asyncsigner import AWSV4SignerAsyncAuth as AWSV4SignerAsyncAuth
from .signer import AWSV4SignerAuth as AWSV4SignerAuth
from .signer import RequestsAWSV4SignerAuth, UrlLib3AWSV4SignerAuth
from .signer import RequestsAWSV4SignerAuth, Urllib3AWSV4SignerAuth
except (ImportError, SyntaxError):
pass
10 changes: 4 additions & 6 deletions opensearchpy/helpers/signer.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# GitHub history for details.

import sys
from typing import Any, Callable
from typing import Any, Callable, Dict

import requests

Expand Down Expand Up @@ -62,9 +62,7 @@ def __init__(self, credentials, region: str, service: str = "es") -> Any: # typ
raise ValueError("Service name cannot be empty")
self.service = service

def sign(self, method: str, url: str, body: Any) -> dict[str, str]:
print(f"SIGN: {method}: {url} ({body})")

def sign(self, method: str, url: str, body: Any) -> Dict[str, str]:
"""
This method signs the request and returns headers.
:param method: HTTP method
Expand Down Expand Up @@ -137,9 +135,9 @@ class AWSV4SignerAuth(RequestsAWSV4SignerAuth):
pass


class UrlLib3AWSV4SignerAuth(Callable): # type: ignore
class Urllib3AWSV4SignerAuth(Callable): # type: ignore
def __init__(self, credentials, region, service="es"): # type: ignore
self.signer = AuthSigner(credentials, region, service)

def __call__(self, method: str, url: str, body: Any) -> dict[str, str]:
def __call__(self, method: str, url: str, body: Any) -> Dict[str, str]:
return self.signer.sign(method, url, body)
4 changes: 2 additions & 2 deletions samples/sigv4/requests-hello.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from urllib.parse import urlparse

from boto3 import Session
from opensearchpy import AWSV4SignerAuth, OpenSearch, RequestsHttpConnection
from opensearchpy import RequestsAWSV4SignerAuth, OpenSearch, RequestsHttpConnection

# verbose logging
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO)
Expand All @@ -26,7 +26,7 @@

credentials = Session().get_credentials()

auth = AWSV4SignerAuth(credentials, region, service)
auth = RequestsAWSV4SignerAuth(credentials, region, service)

client = OpenSearch(
hosts=[{
Expand Down
4 changes: 2 additions & 2 deletions samples/sigv4/urllib3-hello.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from urllib.parse import urlparse

from boto3 import Session
from opensearchpy import UrlLib3AWSV4SignerAuth, OpenSearch, Urllib3HttpConnection
from opensearchpy import Urllib3AWSV4SignerAuth, OpenSearch, Urllib3HttpConnection

# verbose logging
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO)
Expand All @@ -26,7 +26,7 @@

credentials = Session().get_credentials()

auth = UrlLib3AWSV4SignerAuth(credentials, region, service)
auth = Urllib3AWSV4SignerAuth(credentials, region, service)

client = OpenSearch(
hosts=[{
Expand Down
56 changes: 28 additions & 28 deletions test_opensearchpy/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ def test_no_ca_certs(self):
assert Connection.default_ca_certs() is None


class TestUrllib3Connection(TestCase):
class TestUrllib3HttpConnection(TestCase):
def _get_mock_connection(self, connection_params={}, response_body=b"{}"):
con = Urllib3HttpConnection(**connection_params)

Expand Down Expand Up @@ -323,62 +323,62 @@ def test_http_auth_list(self):
)

@pytest.mark.skipif(
sys.version_info < (3, 6), reason="AWSV4SignerAuth requires python3.6+"
sys.version_info < (3, 6), reason="RequestsAWSV4SignerAuth requires python3.6+"
)
def test_aws_signer_as_http_auth(self):
region = "us-west-2"

from opensearchpy.helpers.signer import UrlLib3AWSV4SignerAuth
from opensearchpy.helpers.signer import Urllib3AWSV4SignerAuth

auth = UrlLib3AWSV4SignerAuth(self.mock_session(), region)
auth = Urllib3AWSV4SignerAuth(self.mock_session(), region)
headers = auth("GET", "http://localhost", None)
self.assertIn("Authorization", headers)
self.assertIn("X-Amz-Date", headers)
self.assertIn("X-Amz-Security-Token", headers)
self.assertIn("X-Amz-Content-SHA256", headers)

@pytest.mark.skipif(
sys.version_info < (3, 6), reason="AWSV4SignerAuth requires python3.6+"
sys.version_info < (3, 6), reason="RequestsAWSV4SignerAuth requires python3.6+"
)
def test_aws_signer_when_region_is_null(self):
session = self.mock_session()

from opensearchpy.helpers.signer import AWSV4SignerAuth
from opensearchpy.helpers.signer import RequestsAWSV4SignerAuth

with pytest.raises(ValueError) as e:
AWSV4SignerAuth(session, None)
RequestsAWSV4SignerAuth(session, None)
assert str(e.value) == "Region cannot be empty"

with pytest.raises(ValueError) as e:
AWSV4SignerAuth(session, "")
RequestsAWSV4SignerAuth(session, "")
assert str(e.value) == "Region cannot be empty"

@pytest.mark.skipif(
sys.version_info < (3, 6), reason="AWSV4SignerAuth requires python3.6+"
sys.version_info < (3, 6), reason="RequestsAWSV4SignerAuth requires python3.6+"
)
def test_aws_signer_when_credentials_is_null(self):
region = "us-west-1"

from opensearchpy.helpers.signer import AWSV4SignerAuth
from opensearchpy.helpers.signer import RequestsAWSV4SignerAuth

with pytest.raises(ValueError) as e:
AWSV4SignerAuth(None, region)
RequestsAWSV4SignerAuth(None, region)
assert str(e.value) == "Credentials cannot be empty"

with pytest.raises(ValueError) as e:
AWSV4SignerAuth("", region)
RequestsAWSV4SignerAuth("", region)
assert str(e.value) == "Credentials cannot be empty"

@pytest.mark.skipif(
sys.version_info < (3, 6), reason="AWSV4SignerAuth requires python3.6+"
sys.version_info < (3, 6), reason="Urllib3AWSV4SignerAuth requires python3.6+"
)
def test_aws_signer_when_service_is_specified(self):
region = "us-west-1"
service = "aoss"

from opensearchpy.helpers.signer import UrlLib3AWSV4SignerAuth
from opensearchpy.helpers.signer import Urllib3AWSV4SignerAuth

auth = UrlLib3AWSV4SignerAuth(self.mock_session(), region, service)
auth = Urllib3AWSV4SignerAuth(self.mock_session(), region, service)
headers = auth("GET", "http://localhost", None)
self.assertIn("Authorization", headers)
self.assertIn("X-Amz-Date", headers)
Expand Down Expand Up @@ -494,7 +494,7 @@ def urlopen_raise(*_, **__):
assert str(e.value) == "Wasn't modified!"


class TestSignerWithFrozenCredentials(TestUrllib3Connection):
class TestSignerWithFrozenCredentials(TestUrllib3HttpConnection):
def mock_session(self):
access_key = uuid.uuid4().hex
secret_key = uuid.uuid4().hex
Expand All @@ -508,16 +508,16 @@ def mock_session(self):
return dummy_session

@pytest.mark.skipif(
sys.version_info < (3, 6), reason="AWSV4SignerAuth requires python3.6+"
sys.version_info < (3, 6), reason="RequestsAWSV4SignerAuth requires python3.6+"
)
def test_urllib3_http_connection_aws_signer_frozen_credentials_as_http_auth(self):
region = "us-west-2"

from opensearchpy.helpers.signer import UrlLib3AWSV4SignerAuth
from opensearchpy.helpers.signer import Urllib3AWSV4SignerAuth

mock_session = self.mock_session()

auth = UrlLib3AWSV4SignerAuth(mock_session, region)
auth = Urllib3AWSV4SignerAuth(mock_session, region)
headers = auth("GET", "http://localhost", None)
self.assertIn("Authorization", headers)
self.assertIn("X-Amz-Date", headers)
Expand All @@ -526,18 +526,18 @@ def test_urllib3_http_connection_aws_signer_frozen_credentials_as_http_auth(self
mock_session.get_frozen_credentials.assert_called_once()

@pytest.mark.skipif(
sys.version_info < (3, 6), reason="AWSV4SignerAuth requires python3.6+"
sys.version_info < (3, 6), reason="RequestsAWSV4SignerAuth requires python3.6+"
)
def test_requests_http_connection_aws_signer_frozen_credentials_as_http_auth(self):
region = "us-west-2"

import requests

from opensearchpy.helpers.signer import AWSV4SignerAuth
from opensearchpy.helpers.signer import RequestsAWSV4SignerAuth

mock_session = self.mock_session()

auth = AWSV4SignerAuth(mock_session, region)
auth = RequestsAWSV4SignerAuth(mock_session, region)
con = RequestsHttpConnection(http_auth=auth)
prepared_request = requests.Request("GET", "http://localhost").prepare()
auth(prepared_request)
Expand Down Expand Up @@ -919,16 +919,16 @@ def mock_session(self):
return dummy_session

@pytest.mark.skipif(
sys.version_info < (3, 6), reason="AWSV4SignerAuth requires python3.6+"
sys.version_info < (3, 6), reason="RequestsAWSV4SignerAuth requires python3.6+"
)
def test_aws_signer_as_http_auth(self):
region = "us-west-2"

import requests

from opensearchpy.helpers.signer import AWSV4SignerAuth
from opensearchpy.helpers.signer import RequestsAWSV4SignerAuth

auth = AWSV4SignerAuth(self.mock_session(), region)
auth = RequestsAWSV4SignerAuth(self.mock_session(), region)
con = RequestsHttpConnection(http_auth=auth)
prepared_request = requests.Request("GET", "http://localhost").prepare()
auth(prepared_request)
Expand All @@ -939,17 +939,17 @@ def test_aws_signer_as_http_auth(self):
self.assertIn("X-Amz-Content-SHA256", prepared_request.headers)

@pytest.mark.skipif(
sys.version_info < (3, 6), reason="AWSV4SignerAuth requires python3.6+"
sys.version_info < (3, 6), reason="RequestsAWSV4SignerAuth requires python3.6+"
)
def test_aws_signer_when_service_is_specified(self):
region = "us-west-1"
service = "aoss"

import requests

from opensearchpy.helpers.signer import AWSV4SignerAuth
from opensearchpy.helpers.signer import RequestsAWSV4SignerAuth

auth = AWSV4SignerAuth(self.mock_session(), region, service)
auth = RequestsAWSV4SignerAuth(self.mock_session(), region, service)
con = RequestsHttpConnection(http_auth=auth)
prepared_request = requests.Request("GET", "http://localhost").prepare()
auth(prepared_request)
Expand Down

0 comments on commit f8f2b62

Please sign in to comment.