Reputation: 171
I have gone through many blogs but none of them solves my issue. SNS created by cloudformation is unable to trigger the lambda created by the same cloudformation, I see the trigger as sns in lambda but it didn't trigger it, below is the code.
Tried all solution suggested like using only SourceArn in lambda permission instead of SourceAccountId and all
LambdaBasicExecutionRole:
Type: "AWS::IAM::Role"
Properties:
RoleName: "LambdaBasicExecutionRole"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Principal:
Service:
- "lambda.amazonaws.com"
Action:
- "sts:AssumeRole"
Path: "/"
Policies:
-
PolicyName: "LambdaPolicyEC2KeyPair"
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action:
- "kms:ListGrants"
- "kms:CreateGrant"
- "kms:Encrypt"
- "kms:Decrypt"
Resource: "arn:aws:kms:*:*:*"
-
Effect: "Allow"
Action:
- "logs:CreateLogGroup"
- "logs:CreateLogStream"
- "logs:PutLogEvents"
Resource: "arn:aws:logs:*:*:*"
-
Effect: "Allow"
Action: "ec2:CreateKeyPair"
Resource: "*"
-
Effect: "Allow"
Action: "ssm:PutParameter"
Resource: "*"
LambdaFunctionEC2KeyPair:
Type: AWS::Lambda::Function
Properties:
FunctionName: LambdaFunctionEC2KeyPair
Description: "Lambda Function to create EC2 KeyPair and storing it's private key securely to paramater store"
Handler: index.handler
Runtime: python3.6
Role: !GetAtt LambdaBasicExecutionRole.Arn
Code:
ZipFile: |
import boto3, os, botocore, cfnresponse
client = boto3.client('ec2')
ssm = boto3.client("ssm")
def handler(event, context):
###############################
# Variable Defination from CF #
###############################
IIS = ['service', 'engine', 'micro']
namespace = "IIS"
keyid = os.environ['kmsid']
env = os.environ['env']
for iis_tier in IIS:
keyname = 'IIS-EC2-KeyPair-'+iis_tier+'-'+env
try:
response = client.create_key_pair(
KeyName=keyname
)
except botocore.exceptions.ClientError as e:
if e.response['Error']['Code'] == 'InvalidKeyPair':
print ("Invalid Key Pair Duplicate Error")
continue
else:
continue
try:
ssm_response = ssm.put_parameter(
Name=f"/{namespace}/{env}/EC2-KeyPair/{iis_tier}",
Value=response['KeyMaterial'],
Type="SecureString",
KeyId=keyid,
Description='Private key for '+iis_tier+' '+env+' EC2 instance for ssh connection, one would need it for making ssh connection with the instance for administrative purposes'
)
except botocore.exceptions.ClientError as e:
if e.response['Error']['Code'] == 'AccessDeniedException':
print ("Access Denied Error")
continue
else:
continue
cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, physicalResourceId )
return
Environment:
Variables:
env: !Ref Environment
kmsid: !Ref kmsKeyIIS
DependsOn: LambdaBasicExecutionRole
EC2KeyPair:
Type: Custom::EC2KeyPairResource
Properties:
ServiceToken: !GetAtt LambdaFunctionEC2KeyPair.Arn
Upvotes: 0
Views: 959
Reputation: 270304
It appears that you are wanting to trigger an AWS Lambda function when the CloudFormation stack deploys.
You can do this with an AWS Lambda-backed Custom Resource.
The template should include:
Custom::
entry to trigger your Lambda functionThe Lambda function will need to signal back when it is complete. There is a cfn-response Module provided to assist with this. It is available for Node.js and Python.
Here is a basic CloudFormation template that deploys and runs a Custom Resource:
AWSTemplateFormatVersion: 2010-09-09
Resources:
LambdaBasicExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: MyLambdaRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
-
Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
LambdaFunctionTest:
Type: AWS::Lambda::Function
DependsOn: LambdaBasicExecutionRole
Properties:
FunctionName: LambdaFunctionTest
Description: Lambda Function to test that Custom Resource works
Handler: index.handler
Runtime: python3.6
Role: !GetAtt LambdaBasicExecutionRole.Arn
Code:
ZipFile: |
import boto3
import cfnresponse
def handler(event, context):
print('This is in the handler')
responseData = {}
cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData)
return
CustomFunctionTest:
Type: Custom::CustomFunctionTest
Properties:
ServiceToken: !GetAtt LambdaFunctionTest.Arn
Upvotes: 1
Reputation: 4987
I have AWS::Serverless::Function
and there's Events attribute in the its properties. If you had that, then your configuration would be something like this:
LambdaFunctionEC2KeyPair:
Type: AWS::Lambda::Function
Properties:
FunctionName: LambdaFunctionEC2KeyPair
Description: "Lambda Function to create EC2 KeyPair and storing it's private key securely to paramater store"
Handler: index.handler
Runtime: python3.6
Role: !GetAtt LambdaBasicExecutionRole.Arn
Code:
ZipFile: |
My code
Environment:
Variables:
env: !Ref Environment
kmsid: !Ref kmsKeyIIS
Events:
SNSTopicMessage:
Type: SNS
Properties:
Topic:
Fn::Join:
- ':'
- - arn
- Ref: AWS::Partition
- sns
- Ref: AWS::Region
- Ref: AWS::AccountId
- SNSTopicLambdaInvoke
DependsOn: LambdaBasicExecutionRole
I am checking about your use case having AWS::Lambda::Function
.
You can check this example.
About the difference between a Serverless Function, and a Lambda Function you can check in this answer: What is the difference between a Serverless Function, and a Lambda Function
Upvotes: 0