How do I send slack notification using lambda (python) of sns alert - amazon-web-services

I get sns event in json object to my emails but I want specific part to be sent to slack notification using lambda. I want time, event name, group id, event id etc to be parsed and send to slack. I tried various example online but keep getting error. I have a cloudwatch event which monitor if someone used 0.0.0.0/0 on a given security group. If this happen this will trigger cloud watch event associated to sns alert. I have integrated email alert but i want this done on slack. I Need guidance on this, i tried other example online ?
*{
"version": "0",
"id": "5391448e-1276-49f1-d5a2-5b4898b1f863",
"detail-type": "AWS API Call via CloudTrail",
"source": "aws.ec2",
"account": "982239453305",
"time": "2019-10-02T10:07:07Z",
"region": "eu-west-1",
"resources": [],
"detail": {
"eventVersion": "1.05",
"userIdentity": {
"type": "AssumedRole",
"principalId": "AROAIZE22Q5MDGTLWB2FW:jahmed",
"arn": "arn:aws:sts::988339453305:assumed-role/dp-admins/arahman",
"accountId": "988339453305",
"accessKeyId": "*******",
"sessionContext": {
"sessionIssuer": {
"type": "Role",
"principalId": "********",
"arn": "arn:aws:iam::988569453305:role/dp-admins",
"accountId": "988569453305",
"userName": "dp-admins"
},
"webIdFederationData": {},
"attributes": {
"mfaAuthenticated": "true",
"creationDate": "2019-10-02T10:05:55Z"
}
}
},
"eventTime": "2019-10-02T10:07:07Z",
"eventSource": "ec2.amazonaws.com",
"eventName": "RevokeSecurityGroupIngress",
"awsRegion": "eu-west-1",
"sourceIPAddress": "195.89.75.182",
"userAgent": "console.ec2.amazonaws.com",
"requestParameters": {
"groupId": "sg-00d088d28c60e6bd0",
"ipPermissions": {
"items": [
{
"ipProtocol": "tcp",
"fromPort": 0,
"toPort": 0,
"groups": {},
"ipRanges": {
"items": [
{
"cidrIp": "0.0.0.0/0",
"description": "test-MUST-REMOVE!"
}
]
},
"ipv6Ranges": {},
"prefixListIds": {}
},
{
"ipProtocol": "tcp",
"fromPort": 0,
"toPort": 0,
"groups": {},
"ipRanges": {},
"ipv6Ranges": {
"items": [
{
"cidrIpv6": "::/0",
"description": "test-MUST-REMOVE!"
}
]
},
"prefixListIds": {}
}
]
}
},
"responseElements": {
"requestId": "93fc850f-65e7-464f-b2e0-3db1753a0c94",
"_return": true
},
"requestID": "93fc850f-65e7-464f-b2e0-3db1753a0c94",
"eventID": "2aa40c8d-cc28-45af-89c8-e8885d98dc00",
"eventType": "AwsApiCall"
}
}*

This is the code i have used to integrate with slack
Read the SNS message then post the message on slack webhook url.
import json
import logging
import os
from urllib2 import Request, urlopen, URLError, HTTPError
# Read all the environment variables
SLACK_WEBHOOK_URL = os.environ['SLACK_WEBHOOK_URL']
SLACK_USER = os.environ['SLACK_USER']
SLACK_CHANNEL = os.environ['SLACK_CHANNEL']
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
logger.info("Event: " + str(event))
# Read message posted on SNS Topic
message = json.loads(event['Records'][0]['Sns']['Message'])
logger.info("Message: " + str(message))
# Construct a new slack message
slack_message = {
'channel': SLACK_CHANNEL,
'username': SLACK_USER,
'text': "%s" % (message)
}
# Post message on SLACK_WEBHOOK_URL
req = Request(SLACK_WEBHOOK_URL, json.dumps(slack_message))
try:
response = urlopen(req)
response.read()
logger.info("Message posted to %s", slack_message['channel'])
except HTTPError as e:
logger.error("Request failed: %d %s", e.code, e.reason)
except URLError as e:
logger.error("Server connection failed: %s", e.reason)

Related

AWS Lambda Test S3 Event Notification is Null

I have the following Kotlin code:
override fun execute(input: APIGatewayProxyRequestEvent): APIGatewayProxyResponseEvent {
val response = APIGatewayProxyResponseEvent()
val body = input.body
if(body != null) {
val json = JSONObject(body)
val s3 = json.optJSONArray("Records").getJSONObject(0).getJSONObject("s3")
val bucketName = s3.getJSONObject("bucket").getString("name")
try {
val jsonResponse = objectMapper.writeValueAsString(mapOf("message" to bucketName))
response.statusCode = 200
response.body = jsonResponse
} catch (e: JsonProcessingException) {
response.statusCode = 500
}
}
return response
}
I want to basically get the function to be triggered on a new S3 put and just get the bucket name. When I try locally to pass a APIGatewayProxyRequestEvent with the following body:
{
"Records": [
{
"eventVersion": "2.0",
"eventSource": "aws:s3",
"awsRegion": "us-east-1",
"eventTime": "1970-01-01T00:00:00.000Z",
"eventName": "ObjectCreated:Put",
"userIdentity": {
"principalId": "EXAMPLE"
},
"requestParameters": {
"sourceIPAddress": "127.0.0.1"
},
"responseElements": {
"x-amz-request-id": "EXAMPLE123456789",
"x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH"
},
"s3": {
"s3SchemaVersion": "1.0",
"configurationId": "testConfigRule",
"bucket": {
"name": "example-bucket",
"ownerIdentity": {
"principalId": "EXAMPLE"
},
"arn": "arn:aws:s3:::example-bucket"
},
"object": {
"key": "test%2Fkey",
"size": 1024,
"eTag": "0123456789abcdef0123456789abcdef",
"sequencer": "0A1B2C3D4E5F678901"
}
}
}
]
}
The kotlin code works as expected. When I deploy this on AWS lambda, and I either provide the exact same body in a test event or actually uploading an object on S3 to trigger the function, the input.body is null. I don't understand why.

How to get ip address of spot instance created with boto3

I am able to create spot instance with boto3 with the following code
import boto3
import datetime, random, string
client = boto3.client('ec2')
response = client.request_spot_instances(
DryRun=False,
ClientToken=''.join(random.choices(string.ascii_uppercase + string.digits, k=10)),
InstanceCount=1,
Type='one-time',
LaunchSpecification={
'ImageId': 'ami-053ebee0bc662f9b3',
'SecurityGroups': ['default'],
'InstanceType': 't3.medium',
'Placement': {
'AvailabilityZone': 'us-east-1a',
},
'BlockDeviceMappings': [
{
},
],
'EbsOptimized': True,
'Monitoring': {
'Enabled': True
},
'SecurityGroupIds': [
'sg-03432e1f',
]
}
)
print(response)
And the response I got is below. How can I get ip address of all the machines created. I know that the request is asynchronous but if I want to poll for the details of created instances, what is the way?
{
"SpotInstanceRequests": [
{
"CreateTime": "2022-05-22 05:21:54+00:00",
"LaunchSpecification": {
"SecurityGroups": [
{
"GroupName": "default",
"GroupId": "sg-03432e1f"
}
],
"EbsOptimized": true,
"ImageId": "ami-053ebee0bc662f9b3",
"InstanceType": "t3.medium",
"Placement": {
"AvailabilityZone": "us-east-1a"
},
"SubnetId": "subnet-b9f4aadf",
"Monitoring": {
"Enabled": true
}
},
"ProductDescription": "Linux/UNIX",
"SpotInstanceRequestId": "sir-88tef9gh",
"SpotPrice": "0.041600",
"State": "open",
"Status": {
"Code": "pending-evaluation",
"Message": "Your Spot request has been submitted for review, and is pending evaluation.",
"UpdateTime": "2022-05-22 05:21:55+00:00"
},
"Type": "one-time",
"InstanceInterruptionBehavior": "terminate"
}
],
"ResponseMetadata": {
"RequestId": "ac39fdad-cb4d-4e26-82a5-1f55c1f0d5af",
"HTTPStatusCode": 200,
"HTTPHeaders": {
"x-amzn-requestid": "ac39fdad-cb4d-4e26-82a5-1f55c1f0d5af",
"cache-control": "no-cache, no-store",
"strict-transport-security": "max-age=31536000; includeSubDomains",
"content-type": "text/xml;charset=UTF-8",
"content-length": "1696",
"date": "Sun, 22 May 2022 05:21:54 GMT",
"server": "AmazonEC2"
},
"RetryAttempts": 0
}
}
The same as with regular instances. You have to get NetworkInterfaceId of the spot instances which you can get using describe_instances. The outcome of the call gives you InstanceLifecycle equal to spot for spot instances.
Once you have NetworkInterfaceId of your spot instances you can use describe_network_interfaces to get PublicIp associated with the interface.

S3 - Getting metadata from Post S3 Upload lambda function

I'm generating a presigned URL using s3.getSignedUrl('putObject', params) and for my params
var params = {
Bucket: bucketName,
Key: photoId + "-" + photoNumber + "-of-" + numberImages + ".jpeg",
Expires: signedUrlExpireSeconds,
ContentType: contentType,
Metadata : { testkey1 : "hello" }
};
I'm trying to receive the Metadata in my S3 successful upload lambda function, however it's not appearing. Anyone know why? The upload is successful and for my printed logs, I'm receiving everything but the metadata tag in the event:
console.log(event);
"Records": [
{
"eventVersion": "2.1",
"eventSource": "aws:s3",
"awsRegion": "us-east-1",
"eventTime": "2020-01-15T06:51:57.171Z",
"eventName": "ObjectCreated:Put",
"userIdentity": {
"principalId":
},
"requestParameters": {
"sourceIPAddress":
},
"responseElements": {
"x-amz-request-id": "4C32689CE5B70A82",
"x-amz-id-2": "AS0f97RHlLW2DF6tVfRwbTeoEpk2bEne/0LrWqHpLJRHY5GMBjy/NQOHqYAMhd2JjiiUcuw0nUTMJS8pDAch1Abc5xzzWVMv"
},
"s3": {
"s3SchemaVersion": "1.0",
"configurationId": "9a9a755e-e809-4dbf-abf8-3450aaa208ed",
"bucket": {
"name": ,
"ownerIdentity": {
"principalId": "A3SZPXLS03IWBG"
},
"arn":
},
"object": {
"key": "BcGMYe-1-of-1.jpeg",
"size": 19371,
"eTag": "45c719f2f6b5349cc360db9a13d0cee4",
"sequencer": "005E1EB6921E08F7E4"
}
}
}
]
This is s3 event message structure. the message structure originally doesn't contain metadata.
You need to get metadata in the lambda function in person.
You would get metadata through s3 head-object command with the bucket-name and object-key in the event received.
{
"Records":[
{
"eventVersion":"2.2",
"eventSource":"aws:s3",
"awsRegion":"us-west-2",
"eventTime":The time, in ISO-8601 format, for example, 1970-01-01T00:00:00.000Z, when Amazon S3 finished processing the request,
"eventName":"event-type",
"userIdentity":{
"principalId":"Amazon-customer-ID-of-the-user-who-caused-the-event"
},
"requestParameters":{
"sourceIPAddress":"ip-address-where-request-came-from"
},
"responseElements":{
"x-amz-request-id":"Amazon S3 generated request ID",
"x-amz-id-2":"Amazon S3 host that processed the request"
},
"s3":{
"s3SchemaVersion":"1.0",
"configurationId":"ID found in the bucket notification configuration",
"bucket":{
"name":"bucket-name",
"ownerIdentity":{
"principalId":"Amazon-customer-ID-of-the-bucket-owner"
},
"arn":"bucket-ARN"
},
"object":{
"key":"object-key",
"size":object-size,
"eTag":"object eTag",
"versionId":"object version if bucket is versioning-enabled, otherwise null",
"sequencer": "a string representation of a hexadecimal value used to determine event sequence,
only used with PUTs and DELETEs"
}
},
"glacierEventData": {
"restoreEventData": {
"lifecycleRestorationExpiryTime": "The time, in ISO-8601 format, for example, 1970-01-01T00:00:00.000Z, of Restore Expiry",
"lifecycleRestoreStorageClass": "Source storage class for restore"
}
}
}
]
}

Cloudformation does not support create vpc links in apigateway

In aws api gateway there is a section called API Link and I can manually set that.
The problem is I cannot find any section in cloudformation documentation on how I can create vpc link via cloud formation on api gateway.
Is it sth that cloudformation does not support or am I missing it?
You can use swagger to define an API Gateway using VPC Link. This is a complete CloudFormation template you can deploy to test it out...
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Test backend access via API Gateway. This template provisions a Regional API Gateway proxing requests to a backend via VPC Link and Direct Connect to on-premises resources using private ip addresses.",
"Parameters": {
"VPCId": {
"Description": "VPC Id for API Gateway VPC Link",
"Type": "AWS::EC2::VPC::Id"
},
"NLBSubnetList": {
"Type": "List<AWS::EC2::Subnet::Id>",
"Description": "Subnet Ids for provisioning load balancer supporting the VPC Link"
},
"BackendBaseEndpoint": {
"Description": "The backend service base url including protocol. e.g.: https://<url>",
"Type": "String",
"Default": "https://mybackend.dev.mycompany.com"
},
"TargetIpAddresses": {
"Type": "CommaDelimitedList",
"Description": "Comma separated list of NLB target ip addresses. Specify two entries.",
"Default": "10.78.80.1, 10.79.80.1"
}
},
"Resources": {
"API": {
"Type": "AWS::ApiGateway::RestApi",
"Properties": {
"Name": "Test Api",
"Description": "Test Api using VPC_LINK and AWS_IAM authorisation",
"Body": {
"swagger": "2.0",
"info": {
"title": "Test Api"
},
"schemes": [
"https"
],
"paths": {
"/{proxy+}": {
"x-amazon-apigateway-any-method": {
"parameters": [
{
"name": "proxy",
"in": "path",
"required": true,
"type": "string"
}
],
"responses": {},
"security": [
{
"sigv4": []
}
],
"x-amazon-apigateway-integration": {
"responses": {
"default": {
"statusCode": "200"
}
},
"requestParameters": {
"integration.request.path.proxy": "method.request.path.proxy"
},
"uri": {
"Fn::Join": [
"",
[
{
"Ref": "BackendBaseEndpoint"
},
"/{proxy}"
]
]
},
"passthroughBehavior": "when_no_match",
"connectionType": "VPC_LINK",
"connectionId": "${stageVariables.vpcLinkId}",
"httpMethod": "GET",
"type": "http_proxy"
}
}
}
},
"securityDefinitions": {
"sigv4": {
"type": "apiKey",
"name": "Authorization",
"in": "header",
"x-amazon-apigateway-authtype": "awsSigv4"
}
}
},
"EndpointConfiguration": {
"Types": [
"REGIONAL"
]
}
},
"DependsOn": "VPCLink"
},
"APIStage": {
"Type": "AWS::ApiGateway::Stage",
"Properties": {
"StageName": "dev",
"Description": "dev Stage",
"RestApiId": {
"Ref": "API"
},
"DeploymentId": {
"Ref": "APIDeployment"
},
"MethodSettings": [
{
"ResourcePath": "/*",
"HttpMethod": "GET",
"MetricsEnabled": "true",
"DataTraceEnabled": "true",
"LoggingLevel": "ERROR"
}
],
"Variables": {
"vpcLinkId": {
"Ref": "VPCLink"
}
}
}
},
"APIDeployment": {
"Type": "AWS::ApiGateway::Deployment",
"Properties": {
"RestApiId": {
"Ref": "API"
},
"Description": "Test Deployment"
}
},
"VPCLink": {
"Type": "AWS::ApiGateway::VpcLink",
"Properties": {
"Description": "Vpc link to GIS platform",
"Name": "VPCLink",
"TargetArns": [
{
"Ref": "NLB"
}
]
}
},
"NLBTargetGroup": {
"Type": "AWS::ElasticLoadBalancingV2::TargetGroup",
"Properties": {
"Name": "NLBTargetGroup",
"Port": 443,
"Protocol": "TCP",
"TargetGroupAttributes": [
{
"Key": "deregistration_delay.timeout_seconds",
"Value": "20"
}
],
"TargetType": "ip",
"Targets": [
{
"Id": { "Fn::Select" : [ "0", {"Ref": "TargetIpAddresses"} ] },
"Port": 443,
"AvailabilityZone": "all"
},
{
"Id": { "Fn::Select" : [ "1", {"Ref": "TargetIpAddresses"} ] },
"Port": 443,
"AvailabilityZone": "all"
}
],
"VpcId": {
"Ref": "VPCId"
},
"Tags": [
{
"Key": "Project",
"Value": "API and VPC Link Test"
}
]
}
},
"NLB": {
"Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",
"Properties": {
"Type": "network",
"Scheme": "internal",
"Subnets": {
"Ref": "NLBSubnetList"
}
}
},
"NLBListener": {
"Type": "AWS::ElasticLoadBalancingV2::Listener",
"Properties": {
"DefaultActions": [
{
"Type": "forward",
"TargetGroupArn": {
"Ref": "NLBTargetGroup"
}
}
],
"LoadBalancerArn": {
"Ref": "NLB"
},
"Port": "443",
"Protocol": "TCP"
}
}
},
"Outputs": {
"NetworkLoadBalancerArn": {
"Value": {
"Ref": "NLB"
},
"Description": "The network elastic load balancer Amazon resource name"
}
}
}
Unfortunately, CloudFormation does not support API Gateway's VPC Links at this time.
You can create a Lambda-backed custom resource to manage the VPC Link using CloudFormation.
Here is a Lambda function (using python3.6) for a CloudFormation custom resource I use to manage VPC links:
import copy
import json
import re
import time
import boto3
from botocore.vendored import requests
SUCCESS = "SUCCESS"
FAILED = "FAILED"
FAILED_PHYSICAL_RESOURCE_ID = "FAILED_PHYSICAL_RESOURCE_ID"
class AddOrUpdateTargetArnsError(Exception):
def __init__(self):
self.message = 'Target arns are not allowed to be changed/added.'
super().__init__(self.message)
class FailedVpcLinkError(Exception):
def __init__(self, status_message):
self.message = f'statusMessages: {status_message}'
super().__init__(self.message)
def lambda_handler(event, context):
try:
_lambda_handler(event, context)
except Exception as e:
send(
event,
context,
response_status=FAILED,
# Do not fail on delete to avoid rollback failure
response_data=None,
physical_resource_id=event.get('PhysicalResourceId', FAILED_PHYSICAL_RESOURCE_ID),
reason=e
)
# Must raise, otherwise the Lambda will be marked as successful, and the exception
# will not be logged to CloudWatch logs.
raise
def _lambda_handler(event, context):
print("Received event: ")
print(event)
resource_type = event['ResourceType']
if resource_type != "Custom::ApiGatewayVpcLink":
raise ValueError(f'Unexpected resource_type: {resource_type}')
request_type = event['RequestType']
wait_for = event.get('WaitFor', None)
resource_properties = event['ResourceProperties']
physical_resource_id = event.get('PhysicalResourceId', None)
apigateway = boto3.client('apigateway')
if wait_for:
handle_self_invocation(
wait_for=wait_for,
physical_resource_id=physical_resource_id,
event=event,
context=context,
)
else:
if request_type == 'Create':
kwargs = dict(
name=resource_properties['Name'],
targetArns=resource_properties['TargetArns'],
description=resource_properties.get('Description', None)
)
response = apigateway.create_vpc_link(**kwargs)
event_copy = copy.deepcopy(event)
event_copy['WaitFor'] = 'CreateComplete'
event_copy['PhysicalResourceId'] = response['id']
print('Reinvoking function because VPC link creation is asynchronous')
relaunch_lambda(event=event_copy, context=context)
return
elif request_type == 'Update':
old_resource_properties = event['OldResourceProperties']
current_target_arns = apigateway.get_vpc_link(
vpcLinkId=physical_resource_id,
)['targetArns']
# must compare current_target_arns to resource_properties['TargetArns'], to protect against
# UPDATE created by UPDATE_FAILED. In that particular case, current_target_arns will be the same as
# resource_properties['TargetArns'] but different than old_resource_properties['TargetArns']
if set(current_target_arns) != set(resource_properties['TargetArns']) and \
set(resource_properties['TargetArns']) != set(old_resource_properties['TargetArns']):
raise AddOrUpdateTargetArnsError()
patch_operations = []
if resource_properties['Name'] != old_resource_properties['Name']:
patch_operations.append(dict(
op='replace',
path='/name',
value=resource_properties['Name'],
))
if 'Description' in resource_properties and 'Description' in old_resource_properties:
if resource_properties['Description'] != old_resource_properties['Description']:
patch_operations.append(dict(
op='replace',
path='/description',
value=resource_properties['Description'],
))
elif 'Description' in resource_properties and 'Description' not in old_resource_properties:
patch_operations.append(dict(
op='replace',
path='/description',
value=resource_properties['Description'],
))
elif 'Description' not in resource_properties and 'Description' in old_resource_properties:
patch_operations.append(dict(
op='replace',
path='/description',
value=None,
))
apigateway.update_vpc_link(
vpcLinkId=physical_resource_id,
patchOperations=patch_operations,
)
elif request_type == 'Delete':
delete = True
if physical_resource_id == FAILED_PHYSICAL_RESOURCE_ID:
delete = False
print('Custom resource was never properly created, skipping deletion.')
stack_name = re.match("arn:aws:cloudformation:.+:stack/(?P<stack_name>.+)/.+", event['StackId']).group('stack_name')
if stack_name in physical_resource_id:
delete = False
print(f'Skipping deletion, because VPC link was not created properly. Heuristic: stack name ({stack_name}) found in physical resource ID ({physical_resource_id})')
logical_resource_id = event['LogicalResourceId']
if logical_resource_id in physical_resource_id:
delete = False
print(f'Skipping deletion, because VPC link was not created properly. Heuristic: logical resource ID ({logical_resource_id}) found in physical resource ID ({physical_resource_id})')
if delete:
apigateway.delete_vpc_link(
vpcLinkId=physical_resource_id
)
event_copy = copy.deepcopy(event)
event_copy['WaitFor'] = 'DeleteComplete'
print('Reinvoking function because VPC link deletion is asynchronous')
relaunch_lambda(event=event_copy, context=context)
return
else:
print(f'Request type is {request_type}, doing nothing.')
send(
event,
context,
response_status=SUCCESS,
response_data=None,
physical_resource_id=physical_resource_id,
)
def handle_self_invocation(wait_for, physical_resource_id, event, context):
apigateway = boto3.client('apigateway')
if wait_for == 'CreateComplete':
print('Waiting for creation of VPC link: {vpc_link_id}'.format(vpc_link_id=physical_resource_id))
response = apigateway.get_vpc_link(
vpcLinkId=physical_resource_id,
)
status = response['status']
print('Status of VPC link {vpc_link_id} is {status}'.format(vpc_link_id=physical_resource_id, status=status))
if status == 'AVAILABLE':
send(
event,
context,
response_status=SUCCESS,
response_data=None,
physical_resource_id=physical_resource_id,
)
elif status == 'FAILED':
raise FailedVpcLinkError(status_message=response['statusMessage'])
elif status == 'PENDING':
# Sleeping here to avoid polluting CloudWatch Logs by reinvoking the Lambda too quickly
time.sleep(30)
relaunch_lambda(event, context)
else:
print('Unexpected status, doing nothing')
elif wait_for == 'DeleteComplete':
print('Waiting for deletion of VPC link: {vpc_link_id}'.format(vpc_link_id=physical_resource_id))
try:
response = apigateway.get_vpc_link(
vpcLinkId=physical_resource_id,
)
except apigateway.exceptions.NotFoundException:
print('VPC link {vpc_link_id} deleted successfully'.format(vpc_link_id=physical_resource_id))
send(
event,
context,
response_status=SUCCESS,
response_data=None,
physical_resource_id=physical_resource_id,
)
else:
status = response['status']
assert status == 'DELETING', f'status is {status}'
# Sleeping here to avoid polluting CloudWatch Logs by reinvoking the Lambda too quickly
time.sleep(10)
relaunch_lambda(event, context)
else:
raise ValueError(f'Unexpected WaitFor: {wait_for}')
def relaunch_lambda(event, context):
boto3.client("lambda").invoke(
FunctionName=context.function_name,
InvocationType='Event',
Payload=json.dumps(event),
)
def send(event, context, response_status, response_data, physical_resource_id, reason=None):
response_url = event['ResponseURL']
response_body = {
'Status': response_status,
'Reason': str(reason) if reason else 'See the details in CloudWatch Log Stream: ' + context.log_stream_name,
'PhysicalResourceId': physical_resource_id,
'StackId': event['StackId'],
'RequestId': event['RequestId'],
'LogicalResourceId': event['LogicalResourceId'],
'Data': response_data,
}
json_response_body = json.dumps(response_body)
headers = {
'content-type': '',
'content-length': str(len(json_response_body))
}
try:
requests.put(
response_url,
data=json_response_body,
headers=headers
)
except Exception as e:
print("send(..) failed executing requests.put(..): " + str(e))

Testing Event pattern in AWS lambda

I am pretty new to AWS and trying to update VPC security group when an Event is triggered by ELB
my Event pattern is something like below
{
"userIdentity": {
"invokedBy": [
"elasticloadbalancing.amazonaws.com"
]
},
"eventSource": [
"ec2.amazonaws.com"
],
"eventName": [
"CreateNetworkInterface"
]
}
and sample event is
{
"eventVersion": "1.05",
"userIdentity": {
"type": "Root",
"principalId": "233000205727",
"arn": "arn:aws:iam::233000205727:root",
"accountId": "233000205727",
"userName": "jmfe",
"invokedBy": "elasticloadbalancing.amazonaws.com"
},
"eventTime": "2017-04-15T09:10:30Z",
"eventSource": "ec2.amazonaws.com",
"eventName": "CreateNetworkInterface",
"awsRegion": "us-east-1",
"sourceIPAddress": "elasticloadbalancing.amazonaws.com",
"userAgent": "elasticloadbalancing.amazonaws.com",
"requestParameters": {
"subnetId": "subnet-2dbdf874",
"description": "ELB app/prod-artifactory-b-01-alb/73090a08b6f70469",
"groupSet": {
"items": [
{
"groupId": "sg-3a3b9a47"
}
]
},
"privateIpAddressesSet": {}
},
"responseElements": {
"networkInterface": {
"networkInterfaceId": "eni-4ad99293",
"internalInterfaceId": "interface-4ad99293",
"subnetId": "subnet-2dbdf874",
"vpcId": "vpc-876a77e2",
"availabilityZone": "us-east-1d",
"description": "ELB app/prod-artifactory-b-01-alb/73090a08b6f70469",
"ownerId": "233000205727",
"requesterId": "210368014644",
"requesterManaged": true,
"status": "pending",
"macAddress": "0e:61:f3:36:52:da",
"privateIpAddress": "10.19.84.120",
"privateDnsName": "ip-10-19-84-120.ec2.internal",
"sourceDestCheck": true,
"groupSet": {
"items": [
{
"groupId": "sg-3a3b9a47",
"groupName": "prod-artifactory-b-artifactory-01_client_sg"
}
]
},
"attachableToInstanceBySet": {},
"associableWithElasticIpBySet": {},
"privateIpAddressesSet": {
"item": [
{
"privateIpAddress": "10.19.84.120",
"privateDnsName": "ip-10-19-84-120.ec2.internal",
"primary": true
}
]
},
"ipv6AddressesSet": {},
"tagSet": {}
}
},
"requestID": "064477de-13d2-4e9c-b579-b69a2e6c4882",
"eventID": "0928e0db-89c3-4b33-abd5-62020854599a",
"eventType": "AwsApiCall",
"recipientAccountId": "233000205727"
}
{
"userIdentity": {
"invokedBy": ["elasticloadbalancing.amazonaws.com"]
},
"eventSource": ["ec2.amazonaws.com"],
"eventName": ["CreateNetworkInterface"]
}
I have created a rule with the above event pattern and want to call an AWS lambda function , the code is in python 3.6 and its just a simple hello world
def lambda_handler(event, context):
# TODO implement
return 'Hello from Lambda test'
When ever I test the lambda function with example event (from AWS console) it always Shows 'Hello from Lambda test' , I think I am not able to test the event and event pattern matching , I have changes the event and event pattern with garbage values and still the result is always pass, question is how to test the event and event pattern and see if the event pattern is working correctly within the rule