Skip to content

Commit f375c0b

Browse files
committed
Sign requests using AWS4Auth
While using OpenSearch deployed on AWS infrastructure, the requests needs to be signed with AWS4Auth signature, in order to get the data. This commit adds this possibility. To enable it make sure that following dependencies are installed withing your python env: * requests-aws4auth * botocore
1 parent f656788 commit f375c0b

File tree

1 file changed

+45
-14
lines changed

1 file changed

+45
-14
lines changed

prometheus_es_exporter/__init__.py

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,16 @@
99
import sched
1010
import time
1111

12-
from elasticsearch import Elasticsearch
12+
from elasticsearch import Elasticsearch, RequestsHttpConnection
1313
from elasticsearch.exceptions import ConnectionTimeout
1414
from jog import JogFormatter
1515
from prometheus_client import start_http_server
1616
from prometheus_client.core import GaugeMetricFamily, REGISTRY
17+
try:
18+
from requests_aws4auth import AWS4Auth
19+
from botocore.session import Session
20+
except ImportError:
21+
pass
1722

1823
from . import cluster_health_parser
1924
from . import indices_aliases_parser
@@ -209,10 +214,20 @@ def run_query(es_client, query_name, indices, query,
209214
metrics = parse_response(response, [query_name])
210215
metric_dict = group_metrics(metrics)
211216

212-
except Exception:
217+
except Exception as e:
213218
log.exception('Error while querying indices %(indices)s, query %(query)s.',
214219
{'indices': indices, 'query': query})
215220

221+
# NOTE(mjozefcz): If there is an 401 exception, and the AWS signing was
222+
# set, re-raise it and exit the exporter. It might be wrongly-configured
223+
# credentials or old session.
224+
try:
225+
if e.status_code == 401 and type(es_client.transport.kwargs.get("http_auth")) is AWS4Auth:
226+
# TODO (mjozefcz): Consider re-initialization of AWS4AUTH if possible.
227+
raise e
228+
except NameError:
229+
pass
230+
216231
# If this query has successfully run before, we need to handle any
217232
# metrics produced by that previous run.
218233
if query_name in METRICS_BY_QUERY:
@@ -404,6 +419,9 @@ def conv(value):
404419

405420

406421
@click.command(context_settings=CONTEXT_SETTINGS)
422+
@click.option('--aws-sign-request', default=False, is_flag=True,
423+
help='This should be set if you want your requests to be signed with AWS credentials retrieved from your environment.')
424+
@click.option('--aws-region', help='Region name to be used while signing request with AWS credentials')
407425
@click.option('--es-cluster', '-e', default='localhost',
408426
help='Addresses of nodes in a Elasticsearch cluster to run queries on. '
409427
'Nodes should be separated by commas e.g. es1,es2. '
@@ -516,6 +534,8 @@ def cli(**options):
516534
raise click.BadOptionUsage('basic_password', 'Password provided with no username.')
517535
elif options['basic_user']:
518536
http_auth = (options['basic_user'], options['basic_password'])
537+
elif options['aws_sign_request'] and not options['aws_region']:
538+
raise click.BadOptionUsage('aws_sign_requst', 'AWS requests signing enabled but region not provided.')
519539
else:
520540
http_auth = None
521541

@@ -562,19 +582,30 @@ def cli(**options):
562582
port = options['port']
563583
es_cluster = options['es_cluster'].split(',')
564584

585+
kwargs = {
586+
"https_auth": http_auth,
587+
"headers": options['header'],
588+
"verify_certs": False
589+
}
590+
591+
if options['aws_sign_request'] and options['aws_region']:
592+
service = 'es'
593+
credentials = Session().get_credentials()
594+
http_auth = AWS4Auth(credentials.access_key, credentials.secret_key, options['aws_region'], service, session_token=credentials.token)
595+
kwargs.update({
596+
"http_auth": http_auth,
597+
"connection_class": RequestsHttpConnection
598+
})
599+
565600
if options['ca_certs']:
566-
es_client = Elasticsearch(es_cluster,
567-
verify_certs=True,
568-
ca_certs=options['ca_certs'],
569-
client_cert=options['client_cert'],
570-
client_key=options['client_key'],
571-
headers=options['header'],
572-
http_auth=http_auth)
573-
else:
574-
es_client = Elasticsearch(es_cluster,
575-
verify_certs=False,
576-
headers=options['header'],
577-
http_auth=http_auth)
601+
kwargs.update({
602+
"verify_certs": True,
603+
"ca_certs": options['ca_certs'],
604+
"client_cert": options['client_cert'],
605+
"client_key": options['client_key']
606+
})
607+
608+
es_client = Elasticsearch(es_cluster, **kwargs)
578609

579610
scheduler = None
580611

0 commit comments

Comments
 (0)