def alert(): """ Recieves alert from AWS SNS topic """ data = request.get_json(force=True) try: validatesns.validate(data) except validatesns.ValidationError as err: logging.error(err) abort(403) client = nexmo.Client(key=app.config['NEXMO_KEY'], secret=app.config['NEXMO_SECRET']) if data['Type'] == 'Notification': client.send_message({ 'from': app.config['NEXMO_FROM'], 'to': app.config['NEXMO_TO'], 'text': '\n'.join([data['Subject'], data['Message']]), }) if data['Type'] == 'SubscriptionConfirmation': urllib.request.urlopen(data['SubscribeURL']).read() client.send_message({ 'from': app.config['NEXMO_FROM'], 'to': app.config['NEXMO_TO'], 'text': 'Subscribed to ' + data['TopicArn'], }) return success_response()
def sns_callback_handler(): message_type = request.headers.get('x-amz-sns-message-type') try: verify_message_type(message_type) except InvalidMessageTypeException: raise InvalidRequest("SES-SNS callback failed: invalid message type", 400) try: message = json.loads(request.data) except json.decoder.JSONDecodeError: raise InvalidRequest("SES-SNS callback failed: invalid JSON given", 400) try: validatesns.validate(message, get_certificate=get_certificate) except validatesns.ValidationError: raise InvalidRequest("SES-SNS callback failed: validation failed", 400) if autoconfirm_subscription(message): return jsonify(result="success", message="SES-SNS auto-confirm callback succeeded"), 200 ok, retry = process_ses_results(message) if ok: return jsonify(result="success", message="SES-SNS callback succeeded"), 200 if retry: raise InvalidRequest("SES callback failed, should retry", 500) raise InvalidRequest("SES-SNS callback failed", 400)
def errors(): data = json.loads(request.data.decode('utf-8')) try: validatesns.validate(data) except validatesns.ValidationError: abort(400) message_type = data['Type'] if message_type == 'SubscriptionConfirmation': requests.get(data['SubscribeURL']) elif message_type == 'Notification': try: message_data = json.loads(data['Message']) except JSONDecodeError: # This handles the case where the notification is not an actual # deployment. This happens when you setup a new trigger channel_id = CHANNEL_MAP['semabot'] message = '**{}**\n'.format(data['Subject']) message += data['Message'] flow.send_message(ORG_ID, channel_id, message) return 'foop' new_state_value = message_data['NewStateValue'] if new_state_value == 'ALARM': metric_name = message_data['Trigger']['MetricName'] print(metric_name) return 'fwip'
def lambda_handler(event, context): validatesns.validate(event, get_certificate=get_certificate) if event['Type'] == 'SubscriptionConfirmation': r = requests.get(event['SubscribeURL']) r.raise_for_status() r.close() print "Subscription confirmed" return # Todo: actually handle notification print json.dumps(event, indent=4)
def sns_smtp_callback_handler(): message_type = request.headers.get('x-amz-sns-message-type') try: verify_message_type(message_type) except InvalidMessageTypeException: raise InvalidRequest( "SES-SNS SMTP callback failed: invalid message type", 400) try: message = json.loads(request.data) except decoder.JSONDecodeError: raise InvalidRequest( "SES-SNS SMTP callback failed: invalid JSON given", 400) try: validatesns.validate(message, get_certificate=get_certificate) except validatesns.ValidationError: raise InvalidRequest("SES-SNS SMTP callback failed: validation failed", 400) if message.get('Type') == 'SubscriptionConfirmation': url = message.get('SubscribeURL') response = requests.get(url) try: response.raise_for_status() except Exception as e: current_app.logger.warning("Response: {}".format(response.text)) raise e return jsonify(result="success", message="SES-SNS auto-confirm callback succeeded"), 200 process_ses_smtp_results.apply_async([{ "Message": message.get("Message") }], queue=QueueNames.NOTIFY) return jsonify(result="success", message="SES-SNS callback succeeded"), 200
def handle_s3_sns(body_dict): # check SNS signature authenticity try: validatesns.validate( body_dict, get_certificate=_get_certificate, certificate_url_regex=VALIDATION_CERTIFICATE_URL_REGEX, max_age=VALIDATION_MAX_AGE, ) except (validatesns.ValidationError, requests.exceptions.RequestException) as e: current_app.logger.warning( "SNS request body failed signature validation: {validation_error}", extra={ "validation_error": e, }) abort(400, "SNS request body failed signature validation") supported_topic_name = f"s3_file_upload_notification_{current_app.config['DM_ENVIRONMENT']}" if body_dict["Type"] == "SubscriptionConfirmation": # SNS starts out sending us a SubscriptionConfirmation message when the Topic is initially subscribed to an URL. # We need to handle this in a specific way to "confirm" that we do actually want these notification messages # sent here. return _handle_subscription_confirmation(body_dict, supported_topic_name) elif body_dict["Type"] != "Notification": current_app.logger.warning("Unrecognized request type {request_type}", extra={ "request_type": body_dict["Type"], }) abort(400, f"Unrecognized request type {body_dict['Type']}") current_app.logger.info( "Processing message id {message_id} for subscription {subscription_arn}", extra={ "message_id": body_dict["MessageId"], "subscription_arn": request.headers.get("x-amz-sns-subscription-arn"), }, ) try: body_message = json.loads(body_dict["Message"]) except (ValueError, KeyError, TypeError): current_app.logger.warning( "Message contents didn't match expected format: {message_contents!r}", extra={ "message_contents": body_dict.get("Message"), }) abort(400, f"Message contents didn't match expected format") if "Records" in body_message: for record in body_message["Records"]: scan_and_tag_s3_object( s3_client=boto3.client("s3", region_name=record["awsRegion"]), s3_bucket_name=record["s3"]["bucket"]["name"], s3_object_key=unquote_plus(record["s3"]["object"]["key"]), s3_object_version=record["s3"]["object"]["versionId"], sns_message_id=body_dict["MessageId"], ) elif body_message.get("Event") == "s3:TestEvent": # these happen sometimes - amazon keeping us on our toes current_app.logger.info("Received S3 test event") else: current_app.logger.warning( "Unrecognized message format {body_message}", extra={ "body_message": body_message, }) abort(400, f"Unrecognized message format {body_message}") return jsonify(status="ok"), 200
def deployments(): data = json.loads(request.data.decode('utf-8')) try: validatesns.validate(data) except validatesns.ValidationError: abort(400) message_type = data['Type'] if message_type == 'SubscriptionConfirmation': requests.get(data['SubscribeURL']) elif message_type == 'Notification': try: message_data = json.loads(data['Message']) except JSONDecodeError: # This handles the case where the notification is not an actual # deployment. This happens when you setup a new trigger channel_id = CHANNEL_MAP['semabot'] message = '**{}**\n'.format(data['Subject']) message += data['Message'] flow.send_message(ORG_ID, channel_id, message) return 'foop' deployment_id = message_data['deploymentId'] instance_id = message_data['instanceId'] client = boto3.client('codedeploy') deployment_instances = client.get_deployment_instance( deploymentId=deployment_id, instanceId=instance_id) deployment_info = client.get_deployment( deploymentId=deployment_id)['deploymentInfo'] logs = [] if message_data['instanceStatus'].lower() == 'failed': for event in deployment_instances['instanceSummary'][ 'lifecycleEvents']: if event['status'] == 'Failed': logs.append({ 'event': event['lifecycleEventName'], 'log': event['diagnostics']['logTail'] }) client = boto3.client('ec2') instance_info = client.describe_instances(InstanceIds=[instance_id]) tags = instance_info['Reservations'][0]['Instances'][0]['Tags'] instance_name = [t['Value'] for t in tags if t['Key'] == 'Name'][0] message = '**{status}: AWS CodeDeploy {deployment_id} in {region} to {appname} ({group}) on {instance_name}**' message = message.format(status=message_data['instanceStatus'], group=deployment_info['deploymentGroupName'], deployment_id=deployment_id, region=message_data['region'], appname=deployment_info['applicationName'], instance_name=instance_name) if logs: message += '\n\n' for log in logs: message += '**[Lifecycle Event: {event}]**\n\n```\n{log}\n```'.format( **log) try: channel_id = CHANNEL_MAP[deployment_info['applicationName']] except KeyError: channel_id = CHANNEL_MAP['semabot'] flow.send_message(ORG_ID, channel_id, message) return 'foop'