pythonamazon-web-serviceselasticsearchurllibopensearch

OpenSearch python client authentication error


I cannot connect to my AWS OpenSearch instance. Here is the code and the corresponding error. Environment variables are loaded properly. I tried the elasticsearch client but it does not appear to support AWS authentication now that RequestsHttpConnection has been removed.

import os
from dotenv import load_dotenv
from opensearchpy import OpenSearch, helpers
from requests_aws4auth import AWS4Auth


load_dotenv()

host = os.environ.get("ES_HOST")
region = os.environ.get("ES_REGION")
service = os.environ.get("ES_SERVICE")
port = os.environ.get("ES_PORT")
index = os.environ.get("ES_INDEX")
access_key = os.environ.get("AWS_ACCESS_KEY_ID")
secret_key = os.environ.get("AWS_SECRET_ACCESS_KEY")

awsauth = AWS4Auth(access_key, secret_key, region, 'es')

es = OpenSearch(
    hosts=[{'host': host, 'port': port, 'scheme': 'https'}],
    http_auth=awsauth,
    use_ssl=True,
    verify_certs=True,
    )

print(es.cluster.health())
Traceback (most recent call last):
  File "/repo/.venv/lib/python3.9/site-packages/opensearchpy/connection/http_urllib3.py", line 276, in perform_request
    request_headers.update(self.http_auth(method, full_url, body))
TypeError: __call__() takes 2 positional arguments but 4 were given

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/repo/scratch/test_new.py", line 26, in <module>
    print(es.cluster.health())
  File "/repo/.venv/lib/python3.9/site-packages/opensearchpy/client/utils.py", line 176, in _wrapped
    return func(*args, params=params, headers=headers, **kwargs)
  File "/repo/.venv/lib/python3.9/site-packages/opensearchpy/client/cluster.py", line 131, in health
    return self.transport.perform_request(
  File "/repo/.venv/lib/python3.9/site-packages/opensearchpy/transport.py", line 453, in perform_request
    raise e
  File "/repo/.venv/lib/python3.9/site-packages/opensearchpy/transport.py", line 416, in perform_request
    status, headers_response, data = connection.perform_request(
  File "/repo/.venv/lib/python3.9/site-packages/opensearchpy/connection/http_urllib3.py", line 295, in perform_request
    raise ConnectionError("N/A", str(e), e)
opensearchpy.exceptions.ConnectionError: ConnectionError(__call__() takes 2 positional arguments but 4 were given) caused by: TypeError(__call__() takes 2 positional arguments but 4 were given)

Python version: 3.9.12

Package versions:


Solution

  • I believe you need to use the RequestsHttpConnection class with your OpenSearch client in order to be able to use the requests_aws4auth library. Right now, it looks like opensearch-py defaults to using http_urllib3.

    Change your code to:

    import os
    from dotenv import load_dotenv
    from opensearchpy import OpenSearch, helpers, RequestsHttpConnection
    from requests_aws4auth import AWS4Auth
    
    
    load_dotenv()
    
    host = os.environ.get("ES_HOST")
    region = os.environ.get("ES_REGION")
    service = os.environ.get("ES_SERVICE")
    port = os.environ.get("ES_PORT")
    index = os.environ.get("ES_INDEX")
    access_key = os.environ.get("AWS_ACCESS_KEY_ID")
    secret_key = os.environ.get("AWS_SECRET_ACCESS_KEY")
    
    awsauth = AWS4Auth(access_key, secret_key, region, 'es')
    
    es = OpenSearch(
        hosts=[{'host': host, 'port': port, 'scheme': 'https'}],
        http_auth=awsauth,
        use_ssl=True,
        verify_certs=True,
        connection_class=RequestsHttpConnection,
        )
    
    print(es.cluster.health())