diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cf58a0ac..059f7314 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,5 @@ repos: -- repo: git://github.com/pre-commit/pre-commit-hooks +- repo: https://github.com/pre-commit/pre-commit-hooks sha: v1.1.1 hooks: - id: trailing-whitespace @@ -13,7 +13,7 @@ repos: - id: debug-statements - id: requirements-txt-fixer - id: name-tests-test -- repo: git://github.com/asottile/reorder_python_imports +- repo: https://github.com/asottile/reorder_python_imports sha: v0.3.5 hooks: - id: reorder-python-imports diff --git a/docs/source/elastalert.rst b/docs/source/elastalert.rst index f5884b97..3cf1df20 100755 --- a/docs/source/elastalert.rst +++ b/docs/source/elastalert.rst @@ -144,6 +144,10 @@ The environment variable ``ES_USE_SSL`` will override this field. ``es_password``: Optional; basic-auth password for connecting to ``es_host``. The environment variable ``ES_PASSWORD`` will override this field. +``es_bearer``: Optional; Bearer token for connecting to ``es_host``. The environment variable ``ES_BEARER`` will override this field. This authentication option will override the password authentication option. + +``es_api_key``: Optional; Base64 api-key token for connecting to ``es_host``. The environment variable ``ES_API_KEY`` will override this field. This authentication option will override both the bearer and the password authentication options. + ``es_url_prefix``: Optional; URL prefix for the Elasticsearch endpoint. The environment variable ``ES_URL_PREFIX`` will override this field. ``es_send_get_body_as``: Optional; Method for querying Elasticsearch - ``GET``, ``POST`` or ``source``. The default is ``GET`` diff --git a/docs/source/ruletypes.rst b/docs/source/ruletypes.rst index b41387bf..a54e4614 100644 --- a/docs/source/ruletypes.rst +++ b/docs/source/ruletypes.rst @@ -42,6 +42,8 @@ Rule Configuration Cheat Sheet +--------------------------------------------------------------+ | | ``es_bearer`` (string, no default) | | +--------------------------------------------------------------+ | +| ``es_api_token`` (string, no default) | | ++--------------------------------------------------------------+ | | ``es_url_prefix`` (string, no default) | | +--------------------------------------------------------------+ | | ``statsd_instance_tag`` (string, no default) | | @@ -50,7 +52,7 @@ Rule Configuration Cheat Sheet +--------------------------------------------------------------+ | | ``es_send_get_body_as`` (string, default "GET") | | +--------------------------------------------------------------+ | -| ``aggregation`` (time, no default) | | +| ``aggregation`` (time, no default) | | +--------------------------------------------------------------+ | | ``limit_execution`` (string, no default) | | +--------------------------------------------------------------+ | @@ -299,7 +301,12 @@ es_password es_bearer ^^^^^^^^^^^ -``es_bearer``: bearer-token authorization for connecting to ``es_host``. (Optional, string, no default) The environment variable ``ES_BEARER`` will override this field. +``es_bearer``: bearer-token authorization for connecting to ``es_host``. (Optional, string, no default) The environment variable ``ES_BEARER`` will override this field. This authentication option will override the password authentication option. + +es_api_key +^^^^^^^^^^^ + +``es_api_key``: api-key-token authorization for connecting to ``es_host``. (Optional, base64 string, no default) The environment variable ``ES_API_KEY`` will override this field. This authentication option will override both the bearer and the password authentication options. es_url_prefix ^^^^^^^^^^^^^ @@ -735,7 +742,7 @@ Some rules and alerts require additional options, which also go in the top level query_timezone ^^^^^^^^^^^^^^ -``query_timezone``: Whether to convert UTC time to the specified time zone in rule queries. +``query_timezone``: Whether to convert UTC time to the specified time zone in rule queries. If not set, start and end time of query will be used UTC. (Optional, string, default empty string) Example value : query_timezone: "Europe/Istanbul" @@ -1577,7 +1584,7 @@ AWS SES requires one option: ``ses_email``: An address or list of addresses to sent the alert to. -``ses_from_addr``: This sets the From header in the email. +``ses_from_addr``: This sets the From header in the email. Optional: @@ -1589,7 +1596,7 @@ Optional: ``ses_aws_profile``: The AWS profile to use. If none specified, the default will be used. -``ses_email_reply_to``: This sets the Reply-To header in the email. +``ses_email_reply_to``: This sets the Reply-To header in the email. ``ses_cc``: This adds the CC emails to the list of recipients. By default, this is left empty. @@ -1655,7 +1662,7 @@ Example When not using aws_profile usage:: sns_aws_access_key_id: 'XXXXXXXXXXXXXXXXXX'' sns_aws_secret_access_key: 'YYYYYYYYYYYYYYYYYYYY' sns_aws_region: 'us-east-1' # You must nest aws_region within your alert configuration so it is not used to sign AWS requests. - + Example When to use aws_profile usage:: # Create ~/.aws/credentials @@ -1742,7 +1749,7 @@ Example usage using new-style format:: Datadog ~~~~~~~ -This alert will create a [Datadog Event](https://docs.datadoghq.com/events/). Events are limited to 4000 characters. If an event is sent that contains +This alert will create a [Datadog Event](https://docs.datadoghq.com/events/). Events are limited to 4000 characters. If an event is sent that contains a message that is longer than 4000 characters, only his first 4000 characters will be displayed. This alert requires two additional options: diff --git a/elastalert/config.py b/elastalert/config.py index de6ae77e..b6c1fd45 100644 --- a/elastalert/config.py +++ b/elastalert/config.py @@ -6,8 +6,9 @@ from envparse import Env from elastalert import loaders -from elastalert.util import EAException, elastalert_logger, get_module - +from elastalert.util import EAException +from elastalert.util import elastalert_logger +from elastalert.util import get_module from elastalert.yaml import read_yaml # Required global (config.yaml) configuration options @@ -18,6 +19,7 @@ 'ES_BEARER': 'es_bearer', 'ES_PASSWORD': 'es_password', 'ES_USERNAME': 'es_username', + 'ES_API_KEY': 'es_api_key', 'ES_HOST': 'es_host', 'ES_PORT': 'es_port', 'ES_URL_PREFIX': 'es_url_prefix', diff --git a/elastalert/create_index.py b/elastalert/create_index.py index f8b4ecbb..d4dd08cb 100644 --- a/elastalert/create_index.py +++ b/elastalert/create_index.py @@ -153,6 +153,7 @@ def main(): parser.add_argument('--username', default=os.environ.get('ES_USERNAME', None), help='Elasticsearch username') parser.add_argument('--password', default=os.environ.get('ES_PASSWORD', None), help='Elasticsearch password') parser.add_argument('--bearer', default=os.environ.get('ES_BEARER', None), help='Elasticsearch bearer token') + parser.add_argument('--api-key', default=os.environ.get('ES_API_KEY', None), help='Elasticsearch api-key token') parser.add_argument('--url-prefix', help='Elasticsearch URL prefix') parser.add_argument('--no-auth', action='store_const', const=True, help='Suppress prompt for basic auth') parser.add_argument('--ssl', action='store_true', default=env('ES_USE_SSL', None), help='Use TLS') @@ -198,6 +199,7 @@ def main(): username = args.username if args.username else data.get('es_username') password = args.password if args.password else data.get('es_password') bearer = args.bearer if args.bearer else data.get('es_bearer') + api_key = args.api_key if args.api_key else data.get('es_api_key') url_prefix = args.url_prefix if args.url_prefix is not None else data.get('es_url_prefix', '') use_ssl = args.ssl if args.ssl is not None else data.get('use_ssl') verify_certs = args.verify_certs if args.verify_certs is not None else data.get('verify_certs') is not False @@ -212,6 +214,7 @@ def main(): username = args.username if args.username else None password = args.password if args.password else None bearer = args.bearer if args.bearer else None + api_key = args.api_key if args.api_key else None aws_region = args.aws_region host = args.host if args.host else input('Enter Elasticsearch host: ') port = args.port if args.port else int(input('Enter Elasticsearch port: ')) @@ -249,6 +252,8 @@ def main(): headers = {} if bearer is not None: headers.update({'Authorization': f'Bearer {bearer}'}) + if api_key is not None: + headers.update({'Authorization': f'ApiKey {api_key}'}) es = Elasticsearch( host=host, diff --git a/elastalert/util.py b/elastalert/util.py index 45d9cbb2..22d88120 100644 --- a/elastalert/util.py +++ b/elastalert/util.py @@ -323,13 +323,20 @@ def elasticsearch_client(conf): """ returns an :class:`ElasticSearchClient` instance configured using an es_conn_config """ es_conn_conf = build_es_conn_config(conf) auth = Auth() + username = es_conn_conf['es_username'] + password = es_conn_conf['es_password'] + if es_conn_conf['es_bearer'] or es_conn_conf['es_api_key']: + username = None + password = None es_conn_conf['http_auth'] = auth(host=es_conn_conf['es_host'], - username=None if es_conn_conf['es_bearer'] else es_conn_conf['es_username'], - password=None if es_conn_conf['es_bearer'] else es_conn_conf['es_password'], + username=username, + password=password, aws_region=es_conn_conf['aws_region'], profile_name=es_conn_conf['profile']) if es_conn_conf['es_bearer']: es_conn_conf['headers'] = {"Authorization": "Bearer " + es_conn_conf['es_bearer']} + if es_conn_conf['es_api_key']: + es_conn_conf['headers'] = {"Authorization": "ApiKey " + es_conn_conf['es_api_key']} return ElasticSearchClient(es_conn_conf) @@ -348,6 +355,7 @@ def build_es_conn_config(conf): parsed_conf['http_auth'] = None parsed_conf['es_username'] = None parsed_conf['es_password'] = None + parsed_conf['es_api_key'] = None parsed_conf['es_bearer'] = None parsed_conf['aws_region'] = None parsed_conf['profile'] = None @@ -366,6 +374,11 @@ def build_es_conn_config(conf): parsed_conf['es_username'] = conf['es_username'] parsed_conf['es_password'] = conf['es_password'] + if os.environ.get('ES_API_KEY'): + parsed_conf['es_api_key'] = os.environ.get('ES_API_KEY') + elif 'es_api_key' in conf: + parsed_conf['es_api_key'] = conf['es_api_key'] + if os.environ.get('ES_BEARER'): parsed_conf['es_bearer'] = os.environ.get('ES_BEARER') elif 'es_bearer' in conf: