From 3725134f879097b6a1b04b9c0ab0017840e6807f Mon Sep 17 00:00:00 2001 From: Adi Pandit <39402771+adiosspandit@users.noreply.github.com> Date: Tue, 5 Oct 2021 15:54:43 -0400 Subject: [PATCH] feat: add script to add OMA webhook (#34) Also update store_policies to save policy names in db/account_id/alert_policies omalaertquality also adds channel specified to policies listed in a file --- library/clients/alertsclient.py | 5 ++ library/template/__init__.py | 0 library/template/aqmwebhook.json | 43 ++++++++++++++++ omalertquality.py | 84 ++++++++++++++++++++++++++++++++ store_policies.py | 10 ++++ 5 files changed, 142 insertions(+) create mode 100644 library/template/__init__.py create mode 100644 library/template/aqmwebhook.json create mode 100644 omalertquality.py diff --git a/library/clients/alertsclient.py b/library/clients/alertsclient.py index c838d3a..119cb20 100644 --- a/library/clients/alertsclient.py +++ b/library/clients/alertsclient.py @@ -7,6 +7,7 @@ import re import library.clients.entityclient as ec from library.clients.endpoints import Endpoints +import library.clients.gql as nerdGraph logger = migrationlogger.get_logger(os.path.basename(__file__)) @@ -36,6 +37,10 @@ def setup_headers(api_key): return {'Api-Key': api_key, 'Content-Type': 'application/json'} +def gql_headers(api_key): + return {'api-key': api_key, 'Content-Type': 'application/json'} + + def get_all_alert_policies(api_key, region=Endpoints.REGION_US): return utils.get_paginated_entities(api_key, Endpoints.of(region).ALERT_POLICIES_URL, POLICIES) diff --git a/library/template/__init__.py b/library/template/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/library/template/aqmwebhook.json b/library/template/aqmwebhook.json new file mode 100644 index 0000000..807eea8 --- /dev/null +++ b/library/template/aqmwebhook.json @@ -0,0 +1,43 @@ +{ + "id": 123456, + "name": "REPLACE_WEBHOOK_NAME", + "type": "webhook", + "configuration": { + "payload_type": "application/json", + "headers": { + "X-Insert-Key": "REPLACE_INSERT_KEY" + }, + "base_url": "REPLACE_BASE_URL", + "payload": { + "eventType": "nrAQMIncident", + "account_id": "$ACCOUNT_ID", + "account_name": "$ACCOUNT_NAME", + "closed_violations_count_critical": "$CLOSED_VIOLATIONS_COUNT_CRITICAL", + "closed_violations_count_warning": "$CLOSED_VIOLATIONS_COUNT_WARNING", + "condition_description": "$DESCRIPTION", + "condition_family_id": "$CONDITION_FAMILY_ID", + "condition_name": "$CONDITION_NAME", + "current_state": "$EVENT_STATE", + "details": "$EVENT_DETAILS", + "duration": "$DURATION", + "event_type": "$EVENT_TYPE", + "incident_acknowledge_url": "$INCIDENT_ACKNOWLEDGE_URL", + "incident_id": "$INCIDENT_ID", + "incident_url": "$INCIDENT_URL", + "metadata": "$METADATA", + "open_violations_count_critical": "$OPEN_VIOLATIONS_COUNT_CRITICAL", + "open_violations_count_warning": "$OPEN_VIOLATIONS_COUNT_WARNING", + "owner": "$EVENT_OWNER", + "policy_name": "$POLICY_NAME", + "policy_url": "$POLICY_URL", + "runbook_url": "$RUNBOOK_URL", + "severity": "$SEVERITY", + "targets": "$TARGETS", + "timestamp": "$TIMESTAMP", + "timestamp_utc_string": "$TIMESTAMP_UTC_STRING", + "violation_callback_url": "$VIOLATION_CALLBACK_URL", + "violation_chart_url": "$VIOLATION_CHART_URL", + "restangularEtag": "W/\"51a3b11f2876a8c8cf7f101bf9ac9928\"" + } + } +} \ No newline at end of file diff --git a/omalertquality.py b/omalertquality.py new file mode 100644 index 0000000..3b9164a --- /dev/null +++ b/omalertquality.py @@ -0,0 +1,84 @@ +import os +import json +import argparse +import library.utils as utils +import library.migrationlogger as m_logger +import library.clients.alertsclient as ac +import library.localstore as store + +log = m_logger.get_logger(os.path.basename(__file__)) + + +def configure_parser(): + parser = argparse.ArgumentParser(description='Alert Quality Management Webhook operations') + parser.add_argument('--targetAccount', nargs=1, type=str, required=True, help='Account ID') + parser.add_argument('--targetApiKey', nargs=1, type=str, required=True, help='User API Key') + parser.add_argument('--targetRegion', type=str, nargs=1, required=False, help='targetRegion us(default) or eu') + parser.add_argument('--createChannel', type=str, nargs=1, required=False, + help='Pass channel name to create AQM Webhook Notification Channel') + parser.add_argument('--insertKey', type=str, nargs=1, required=False, help='Insights Insert API Key') + parser.add_argument('--addChannel', type=str, nargs=1, required=False, help='Add this Channel name to policies ' + 'listed in policyFile') + parser.add_argument('--policyFile', type=str, nargs=1, required=False, help='File containing alert policy names. ' + 'One per line. This can be generated ' + 'using store_policies') + return parser + + +def prepare_aqm_webhook_channel(account_id, insert_api_key, channel_name): + webhook_channel = store.load_json_from_file('library/template', 'aqmwebhook.json') + webhook_channel['name'] = channel_name + webhook_channel['configuration']['headers']['X-Insert-Key'] = insert_api_key + base_url = "https://insights-collector.newrelic.com/v1/accounts/" + str(account_id) + "/events" + webhook_channel['configuration']['base_url'] = base_url + return webhook_channel + + +def create_aqm_webhook(account_id, user_api_key, insert_api_key, channel_name, region): + aqm_channel = prepare_aqm_webhook_channel(account_id, insert_api_key, channel_name) + result = ac.create_channel(user_api_key, aqm_channel, region) + if 'errors' in result: + log.error(json.dumps(result)) + else: + log.info(json.dumps(result)) + + +def add_channel_to_policies(account_id, user_api_key, channel_name, policy_file, region): + log.info("Adding channel " + channel_name + " to policies in " + policy_file) + all_channels = ac.get_channels(user_api_key, region) + log.info(json.dumps(all_channels)) + channel_id = -1 + for channel in all_channels['channels']: + if channel['name'] == channel_name: + channel_id = channel['id'] + if channel_id == -1: + utils.error_message_and_exit("Notification channel not found " + channel_name) + policy_names = store.load_names(policy_file) + for policy_name in policy_names: + result = ac.get_policy(user_api_key, policy_name, region) + if not result['policyFound']: + log.warn("Did not find policy skipping " + policy_name) + log.info("Found Policy adding channel to " + policy_name) + ac.put_channel_ids(user_api_key, result['policy']['id'], [channel_id], region) + + +def main(): + parser = configure_parser() + args = parser.parse_args() + target_api_key = utils.ensure_target_api_key(args) + if not target_api_key: + utils.error_and_exit('target_api_key', 'ENV_TARGET_API_KEY') + region = utils.ensure_target_region(args) + if args.createChannel: + if not args.insertKey: + utils.error_message_and_exit("insertKey must be passed or creating channel") + create_aqm_webhook(args.targetAccount[0], target_api_key, args.insertKey[0], args.createChannel[0], region) + if args.addChannel: + if not args.policyFile: + utils.error_message_and_exit("policyFile not found. Pass policyFile listing policies to which channel " + "should be added") + add_channel_to_policies(args.targetAccount[0], target_api_key, args.addChannel[0], args.policyFile[0], region) + + +if __name__ == '__main__': + main() diff --git a/store_policies.py b/store_policies.py index 8588375..b827f05 100644 --- a/store_policies.py +++ b/store_policies.py @@ -32,6 +32,16 @@ def store_alert_policies(src_account, src_api_key, src_region): log.info('Starting store alert policies.') policies = ac.get_all_alert_policies(src_api_key, src_region) store.save_alert_policies(src_account, policies) + policy_file_name = str(src_account)+'_policies.csv' + policy_names_file = store.create_output_file(policy_file_name) + with policy_names_file.open('a') as policy_names_out: + for policy in policies['policies']: + policy_name = policy['name'] + policy_name = store.sanitize(policy_name) + policy_names_out.write(policy_name + "\n") + policy_names_out.close() + log.info("Policy names stored in " + policy_file_name) + log.info("Policies JSON stored in " + "db/"+str(src_account)+"/alert_policies/alert_policies.json") log.info('Finished store alert policies.')