def main(): context = handle_args_and_set_context(sys.argv[1:]) profile = None if context.whereami == "ec2" else context.account_alias try: clients = ef_utils.create_aws_clients(EFConfig.DEFAULT_REGION, profile, "kms") except RuntimeError as error: ef_utils.fail( "Exception creating clients in region {} with profile {}".format( EFConfig.DEFAULT_REGION, profile), error) if context.secret_file: generate_secret_file(context.secret_file, context.match, context.service, context.env, clients) return if context.decrypt: decrypted = ef_utils.kms_decrypt(kms_client=clients['kms'], secret=context.decrypt) key_aliases = ef_utils.kms_key_alias(clients['kms'], decrypted.key_id) print("Decrypted Secret: {}; Key: {}".format(decrypted.plaintext, ', '.join(key_aliases))) return if context.plaintext: password = context.plaintext else: password = generate_secret(context.length) print("Generated Secret: {}".format(password)) encrypted_password = ef_utils.kms_encrypt(clients['kms'], context.service, context.env, password) print(format_secret(encrypted_password)) return
def run(self): if self.context.env in self.all_notification_channels.keys(): if self.config['token_kms_encrypted']: self.admin_token = kms_decrypt(self.clients['kms'], self.admin_token).plaintext newrelic = NewRelic(self.admin_token) for service in self.context.service_registry.iter_services(service_group="application_services"): service_name = service[0] service_environments = service[1]['environments'] service_alert_overrides = service[1]['alerts'] if "alerts" in service[1] else {} if self.context.env in service_environments: policy = AlertPolicy(env=self.context.env, service=service_name) # Create service alert policy if it doesn't already exist if not newrelic.alert_policy_exists(policy.name): newrelic.create_alert_policy(policy.name) logger.info("create alert policy {}".format(policy.name)) policy.id = next(alert['id'] for alert in newrelic.all_alerts if alert['name'] == policy.name) policy.notification_channels = self.all_notification_channels[self.context.env] policy.conditions = newrelic.get_policy_alert_conditions(policy.id) policy.config_conditions = deepcopy(self.conditions) # Add alert policy to notification channels if missing for channel in newrelic.all_channels: if channel['name'] in policy.notification_channels and policy.id not in channel['links']['policy_ids']: newrelic.add_policy_channels(policy.id, [channel['id']]) logger.info("add channel_ids {} to policy {}".format(policy.name, channel['id'])) # Replace symbols in config alert conditions for key, value in policy.config_conditions.items(): policy.config_conditions[key] = self.replace_symbols(value, policy.symbols) # Update policy.config_conditions with overrides from service_registry for condition_name, override_obj in service_alert_overrides.items(): if condition_name in policy.config_conditions.keys(): for override_key, override_value in override_obj.items(): if isinstance(override_value, dict): for inner_key, inner_val in override_value.items(): policy.config_conditions[condition_name][override_key][inner_key] = inner_val else: policy.config_conditions[condition_name][override_key] = override_value logger.debug("Policy {} alert condition values:\n{}".format(policy.name, policy.config_conditions)) # Remove conditions with values that differ from config for condition in policy.conditions: if condition['name'] in policy.config_conditions: config_condition = policy.config_conditions[condition['name']] for k, v in config_condition.items(): if condition[k] != v: newrelic.delete_policy_alert_condition(condition['id']) policy.conditions = newrelic.get_policy_alert_conditions(policy.id) logger.info("delete condition {} from policy {}. ".format(condition['name'], policy.name) + \ "current value differs from config") break # Create alert conditions for policies for key, value in policy.config_conditions.items(): if not any(d['name'] == key for d in policy.conditions): newrelic.create_alert_cond(policy.config_conditions[key]) logger.info("create condition {} for policy {}".format(key, policy.name))
def kms_decrypt_value(self, lookup): """ Args: lookup: the encrypted value to be decrypted by KMS; base64 encoded Returns: The decrypted lookup value """ decrypted_lookup = ef_utils.kms_decrypt(EFAwsResolver.__CLIENTS["kms"], lookup) return decrypted_lookup
def test_kms_decrypt_fails_client_error(self): """Ensures that function fails a generic ClientError despite any special handling for specific error codes""" self.mock_kms.decrypt.side_effect = self.client_error with self.assertRaises(SystemExit): ef_utils.kms_decrypt(self.mock_kms, self.secret)
def test_kms_decrypt_fails_without_b64_secret(self): """Ensures that function fails when passed a non-base64 encoded secret""" with self.assertRaises(SystemExit): ef_utils.kms_decrypt(self.mock_kms, self.secret)
def test_kms_decrypt_call(self): """Validates basic kms call parameters""" b64_secret = base64.b64encode(self.secret) ef_utils.kms_decrypt(self.mock_kms, b64_secret) self.mock_kms.decrypt.assert_called_once_with( CiphertextBlob=self.secret)