|
9 | 9 | import sched |
10 | 10 | import time |
11 | 11 |
|
12 | | -from elasticsearch import Elasticsearch |
| 12 | +from elasticsearch import Elasticsearch, RequestsHttpConnection |
13 | 13 | from elasticsearch.exceptions import ConnectionTimeout |
14 | 14 | from jog import JogFormatter |
15 | 15 | from prometheus_client import start_http_server |
|
26 | 26 | from .scheduler import schedule_job |
27 | 27 | from .utils import log_exceptions, nice_shutdown |
28 | 28 |
|
| 29 | +try: |
| 30 | + from requests_aws4auth import AWS4Auth |
| 31 | + from botocore.session import Session |
| 32 | +except ImportError, ModuleNotFoundError: |
| 33 | + pass |
| 34 | + |
29 | 35 | log = logging.getLogger(__name__) |
30 | 36 |
|
31 | 37 | CONTEXT_SETTINGS = { |
@@ -209,10 +215,20 @@ def run_query(es_client, query_name, indices, query, |
209 | 215 | metrics = parse_response(response, [query_name]) |
210 | 216 | metric_dict = group_metrics(metrics) |
211 | 217 |
|
212 | | - except Exception: |
| 218 | + except Exception as e: |
213 | 219 | log.exception('Error while querying indices %(indices)s, query %(query)s.', |
214 | 220 | {'indices': indices, 'query': query}) |
215 | 221 |
|
| 222 | + # NOTE(mjozefcz): If there is an 401 exception, and the AWS signing was |
| 223 | + # set, re-raise it and exit the exporter. It might be wrongly-configured |
| 224 | + # credentials or old session. |
| 225 | + try: |
| 226 | + if e.status_code == 401 and type(es_client.transport.kwargs.get("http_auth")) is AWS4Auth: |
| 227 | + # TODO (mjozefcz): Consider re-initialization of AWS4AUTH if possible. |
| 228 | + raise e |
| 229 | + except NameError: |
| 230 | + pass |
| 231 | + |
216 | 232 | # If this query has successfully run before, we need to handle any |
217 | 233 | # metrics produced by that previous run. |
218 | 234 | if query_name in METRICS_BY_QUERY: |
@@ -404,6 +420,9 @@ def conv(value): |
404 | 420 |
|
405 | 421 |
|
406 | 422 | @click.command(context_settings=CONTEXT_SETTINGS) |
| 423 | +@click.option('--aws-sign-request', default=False, is_flag=True, |
| 424 | + help='This should be set if you want your requests to be signed with AWS credentials retrieved from your environment.') |
| 425 | +@click.option('--aws-region', help='Region name to be used while signing request with AWS credentials') |
407 | 426 | @click.option('--es-cluster', '-e', default='localhost', |
408 | 427 | help='Addresses of nodes in a Elasticsearch cluster to run queries on. ' |
409 | 428 | 'Nodes should be separated by commas e.g. es1,es2. ' |
@@ -516,6 +535,8 @@ def cli(**options): |
516 | 535 | raise click.BadOptionUsage('basic_password', 'Password provided with no username.') |
517 | 536 | elif options['basic_user']: |
518 | 537 | http_auth = (options['basic_user'], options['basic_password']) |
| 538 | + elif options['aws_sign_request'] and not options['aws_region']: |
| 539 | + raise click.BadOptionUsage('aws_sign_requst', 'AWS requests signing enabled but region not provided.') |
519 | 540 | else: |
520 | 541 | http_auth = None |
521 | 542 |
|
@@ -562,19 +583,30 @@ def cli(**options): |
562 | 583 | port = options['port'] |
563 | 584 | es_cluster = options['es_cluster'].split(',') |
564 | 585 |
|
| 586 | + kwargs = { |
| 587 | + "https_auth": http_auth, |
| 588 | + "headers": options['header'], |
| 589 | + "verify_certs": False |
| 590 | + } |
| 591 | + |
| 592 | + if options['aws_sign_request'] and options['aws_region']: |
| 593 | + service = 'es' |
| 594 | + credentials = Session().get_credentials() |
| 595 | + http_auth = AWS4Auth(credentials.access_key, credentials.secret_key, options['aws_region'], service, session_token=credentials.token) |
| 596 | + kwargs.update({ |
| 597 | + "http_auth": http_auth, |
| 598 | + "connection_class": RequestsHttpConnection |
| 599 | + }) |
| 600 | + |
565 | 601 | 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) |
| 602 | + kwargs.update({ |
| 603 | + "verify_certs": True, |
| 604 | + "ca_certs": options['ca_certs'], |
| 605 | + "client_cert": options['client_cert'], |
| 606 | + "client_key": options['client_key'] |
| 607 | + }) |
| 608 | + |
| 609 | + es_client = Elasticsearch(es_cluster, **kwargs) |
578 | 610 |
|
579 | 611 | scheduler = None |
580 | 612 |
|
|
0 commit comments