AWS SAM Template get rule name with intrinsic function - amazon-web-services

Let's say I have a scheduled function declared in a SAM template.yaml
myScheduledFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: ./bin
Handler: myScheduledFunction
Policies:
- AWSLambdaBasicExecutionRole
Events:
CloudwatchEvents:
Type: Schedule
Properties:
Schedule: rate(1 minute)
Enabled: true
and then I have another function that enable/disable the scheduled rule
myFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: ./bin
Handler: myFunction
Environment:
Variables:
RULE_NAME: !Ref MyRuleName
Policies:
- AWSLambdaBasicExecutionRole
- EventBridgePutEventsPolicy:
EventBusName: default
Events:
SomeEvent: ...
Now, how can I reference the rule name in environment variable RULE_NAME: !Ref MyRuleName?
It is possible to do it in SAM? Maybe using something like !GetAtt myScheduledFunction.RuleName?
I couldn't find anything regarding this and I know that there is a way to do it in Cloudformation, but I would know if it is possible in SAM as well, thanks.

I don't think this is possible to retrieve with the template as written. A work around would be to create the CloudWatch rule as a top-level resource instead of creating it in the Events property.
For example:
myScheduledFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: ./bin
Handler: myScheduledFunction
Policies:
- AWSLambdaBasicExecutionRole
myRule:
Type: AWS::Events::Rule
Properties:
Description: "ScheduledRule"
ScheduleExpression: "rate(1 minutes)"
State: "ENABLED"
Targets:
- Arn:
Fn::GetAtt:
- "myScheduledFunction"
- "Arn"
PermissionForEventsToInvokeLambda:
Type: AWS::Lambda::Permission
Properties:
FunctionName:
Ref: "myScheduledFunction"
Action: "lambda:InvokeFunction"
Principal: "events.amazonaws.com"
SourceArn:
Fn::GetAtt:
- "myRule"
- "Arn"
myFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: ./bin
Handler: myFunction
Environment:
Variables:
RULE_NAME: !Ref myRule
Policies:
- AWSLambdaBasicExecutionRole
- EventBridgePutEventsPolicy:
EventBusName: default
Events:
SomeEvent: ...
This code snippet for the rule/permission was taken from the Cloudwatch Rule cloudformation documentation.

Related

Register SQS as trigger of lambda on deployment

I have lambda function and SQS queue. I would like to connect this two thing on deployment automatically. So I have this template.yaml. But somewhere in my config is error, because this doesn't create trigger nor EventSourceMapping. Can you help me? I must be missing something.
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: Create contract function
Resources:
CreateContractFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: src/
Handler: index.handler
Runtime: nodejs14.x
Timeout: 30
Environment:
Variables:
QUEUE_REQUEST: !ImportValue request:Queue
AutoPublishAlias: live
Policies:
- Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- "sqs:SendMessage"
- "sqs:ReceiveMessage"
- "sqs:DeleteMessage"
- "sqs:GetQueueAttributes"
Resource: "*"
- Effect: "Allow"
Action:
- "lambda:InvokeFunction"
- "lambda:InvokeAsync"
Resource: "*"
Events:
SQSEvent:
Type: SQS
Properties:
Queue: *arn*
BatchSize: 10
MaximumBatchingWindowInSeconds: 30
Enabled: true
DeploymentPreference:
Type: AllAtOnce
Outputs:
LogFunction:
Value: !GetAtt CreateFunction.Arn
Export:
Name: lambda-create

SQS Event Source not being created on AWS SAM Lambda function

Please help. I have an AWS Lambda defined in an AWS SAM YAML file that has been deployed but does not create the event source along with it. Please, what could I likely be missing here? I have already tried adding certain permissions to the SQS and SQSPoller permissions to the Lambda but that did not work. I have already spent too much time on this already. Thank you very much
BootstrapFunction:
Type: AWS::Serverless::Function
Properties:
PackageType: Zip
FunctionName: !Sub '${appName}-${env}-${sourceCodeName}-bootstrap'
CodeUri:
Bucket: !Ref sourceCodeBucketName
Key: !Sub '${sourceCodeName}/${sourceCodeTag}.zip'
Description: Bootstrap the Project State Machine
Handler: build/src/bootstrapHandler.bootstrap
Policies:
- AWSLambdaExecute
Runtime: nodejs14.x
MemorySize: 1024
Timeout: 30
Environment:
Variables:
LOG_LEVEL: 'debug'
REGION: !Ref AWS::Region
VpcConfig:
SecurityGroupIds:
- !Ref clusterSecurityGroupId
SubnetIds: !Ref subnetIds
Events:
BootstrapFunctionSQSEvent:
Type: SQS
Properties:
Queue: !GetAtt TaskQueue.Arn
BatchSize: 1
Enabled: true
TaskQueue:
Type: AWS::SQS::Queue
Properties:
QueueName: !Sub '${appName}-${env}-${sourceCodeName}-task'
MessageRetentionPeriod: !Ref sqsMessageRetentionSeconds
RedrivePolicy:
deadLetterTargetArn: !GetAtt TaskDlQueue.Arn
maxReceiveCount: !Ref maxReceiveCountForDlq
TaskQueueWritePolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName: !Sub '${appName}-${env}-${sourceCodeName}-task-queue-write-policy'
PolicyDocument:
Version: 2012-10-17
Statement:
- Sid: AllowQueueAccess
Effect: Allow
Action:
- sqs:SendMessage
- sqs:ChangeMessageVisibility
Resource:
- !GetAtt TaskQueue.Arn
TaskQueueReadPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName: !Sub '${appName}-${env}-${sourceCodeName}-task-queue-read-policy'
PolicyDocument:
Version: 2012-10-17
Statement:
- Sid: AllowQueueAccess
Effect: Allow
Action:
- sqs:ChangeMessageVisibility
- sqs:ReceiveMessage
- sqs:DeleteMessage
Resource:
- !GetAtt TaskQueue.Arn
Events should be indented underneath Properties in your BootstrapFunction resource:
BootstrapFunction:
Type: AWS::Serverless::Function
Properties:
PackageType: Zip
FunctionName: !Sub '${appName}-${env}-${sourceCodeName}-bootstrap'
CodeUri:
Bucket: !Ref sourceCodeBucketName
Key: !Sub '${sourceCodeName}/${sourceCodeTag}.zip'
Description: Bootstrap the Project State Machine
Handler: build/src/bootstrapHandler.bootstrap
Policies:
- AWSLambdaExecute
Runtime: nodejs14.x
MemorySize: 1024
Timeout: 30
Environment:
Variables:
LOG_LEVEL: 'debug'
REGION: !Ref AWS::Region
VpcConfig:
SecurityGroupIds:
- !Ref clusterSecurityGroupId
SubnetIds: !Ref subnetIds
Events:
BootstrapFunctionSQSEvent:
Type: SQS
Properties:
Queue: !GetAtt TaskQueue.Arn
BatchSize: 1
Enabled: true

What is SourceArn when create lambda function through cloudformation template

I want to create a lambda function through cloudformation template, I have ConfigurationLambdaRole, ConfigurationLambdaFunction and ConfigurationLambdaInvokePermission, in ConfigurationLambdaInvokePermission section, what should be the SourceArn? And is there any incorrect thing with my template?
Resources:
ConfigurationLambdaRole:
Type: "AWS::IAM::Role"
Properties:
RoleName: 'configuration-lambda'
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- events.amazonaws.com
- s3.amazonaws.com
Action:
- sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSQSFullAccess
- arn:aws:iam::aws:policy/CloudWatchLogsFullAccess
ConfigurationLambdaFunction:
Type: AWS::Lambda::Function
Properties:
Description: 'configuration service with lambda'
FunctionName: 'configuration-lambda1'
Handler: lambda.handler.EventHandler::handleRequest
Runtime: Java 11
MemorySize: 128
Timeout: 120
Code:
S3Bucket: configurationlambda
S3Key: lambda-service-1.0.0-SNAPSHOT.jar
Role: !GetAtt ConfiguratioLambdaRole.Arn
ConfigurationLambdaInvokePermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName:
Fn::GetAtt:
- ConfigurationLambdaFunction
- Arn
Action: 'lambda:InvokeFunction'
Principal: "s3.amazonaws.com"
SourceArn: 'arn of jar file in s3(configurationlambda)'
SourceArn is an arn of a resource which is going to invoke your function. For example, if your lambda would be invoked through S3 Events Notifications, the SourceArn would be the ARN of your bucket.
In your case I don't see why would you need AWS::Lambda::Permission. So I would just remove the entire resource.

How to add S3 trigger for existing bucket to lambda function in cloudformation

I'm trying to create a template.yml for a lambda function pipeline, this is my template:
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Parameters:
ImageUri:
Type: String
LambdaName:
Type: String
RoleName:
Type: String
BucketName:
Type: String
Resources:
S3Bucket:
Type: AWS::S3::Bucket
DeletionPolicy: Retain
Properties:
BucketName: !Ref BucketName
AllowS3ToCallLambdaPermission:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !Ref LambdaFunction
Principal: s3.amazonaws.com
SourceArn: !GetAtt S3Bucket.Arn
LambdaRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Ref RoleName
AssumeRolePolicyDocument:
Statement:
- Action:
- sts:AssumeRole
Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Version: 2012-10-17
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonS3FullAccess
LambdaFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: !Ref LambdaName
PackageType: Image
MemorySize: 256
Timeout: 5
ImageUri: !Ref ImageUri
Events:
S3Bucket:
Type: S3
Properties:
Bucket: !Ref S3Bucket
Events: 's3:ObjectCreated:*'
Role:
Fn::GetAtt:
- LambdaRole
- Arn
This template contains an S3 event, with the template above it tries to create a new bucket. Is there a way to specify an existing bucket for the trigger?
No matter how much I tried to make LambdaFunction resource to use an existing S3 bucket, I failed.

Work around circular dependency in AWS CloudFormation

The following AWS CloudFormation gives a circular dependency error. My understanding is that the dependencies flow like this: rawUploads -> generatePreview -> previewPipeline -> rawUploads. Although it doesn't seem like rawUploads depends on generatePreview, I guess CF needs to know what lambda to trigger when creating the bucket, even though the trigger is defined in the lambda part of the CloudFormation template.
I've found some resources online that talk about a similar issue, but it doesn't seem to apply here. https://aws.amazon.com/premiumsupport/knowledge-center/unable-validate-circular-dependency-cloudformation/
What are my options for breaking this circular dependency chain? Scriptable solutions are viable, but multiple deployments with manual changes are not for my use case.
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Resources:
rawUploads:
Type: 'AWS::S3::Bucket'
previewAudioFiles:
Type: 'AWS::S3::Bucket'
generatePreview:
Type: AWS::Serverless::Function
Properties:
Handler: generatePreview.handler
Runtime: nodejs6.10
CodeUri: .
Environment:
Variables:
PipelineId: !Ref previewPipeline
Events:
BucketrawUploads:
Type: S3
Properties:
Bucket: !Ref rawUploads
Events: 's3:ObjectCreated:*'
previewPipeline:
Type: Custom::ElasticTranscoderPipeline
Version: '1.0'
Properties:
ServiceToken:
Fn::Join:
- ":"
- - arn:aws:lambda
- Ref: AWS::Region
- Ref: AWS::AccountId
- function
- aws-cloudformation-elastic-transcoder-pipeline-1-0-0
Name: transcoderPipeline
InputBucket:
Ref: rawUploads
OutputBucket:
Ref: previewAudioFiles
One way is to give the S3 buckets explicit names so that later, instead of relying on Ref: bucketname, you can simply use the bucket name. That's obviously problematic if you want auto-generated bucket names and in those cases it's prudent to generate the bucket name from some prefix plus the (unique) stack name, for example:
InputBucket: !Join ["-", ['rawuploads', Ref: 'AWS::StackName']]
Another option is to use a single CloudFormation template but in 2 stages - the 1st stage creates the base resources (and whatever refs are not circular) and then you add the remaining refs to the template and do a stack update. Not ideal, obviously, so I would prefer the first approach.
You can also use the first technique in cases when you need a reference to an ARN, for example:
!Join ['/', ['arn:aws:s3:::logsbucket', 'AWSLogs', Ref: 'AWS:AccountId', '*']]
When using this technique, you may want to also consider using DependsOn because you have removed an implicit dependency which can sometimes cause problems.
This post helped me out in the end: https://aws.amazon.com/premiumsupport/knowledge-center/unable-validate-destination-s3/
I ended up configuring an SNS topic in CloudFormation. The bucket would push events on this topic, and the Lambda function listens to this topic. This way the dependency graph is as follows:
S3 bucket -> SNS topic -> SNS topic policy
Lambda function -> SNS topic
Lambda function -> transcoder pipeline
Something along the lines of this (some policies omitted)
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Resources:
SNSTopic:
Type: AWS::SNS::Topic
SNSTopicPolicy:
Type: AWS::SNS::TopicPolicy
Properties:
PolicyDocument:
Id: MyTopicPolicy
Version: '2012-10-17'
Statement:
- Sid: Statement-id
Effect: Allow
Principal:
AWS: "*"
Action: sns:Publish
Resource:
Ref: SNSTopic
Condition:
ArnLike:
aws:SourceArn:
!Join ["-", ['arn:aws:s3:::rawuploads', Ref: 'AWS::StackName']]
Topics:
- Ref: SNSTopic
rawUploads:
Type: 'AWS::S3::Bucket'
DependsOn: SNSTopicPolicy
Properties:
BucketName: !Join ["-", ['rawuploads', Ref: 'AWS::StackName']]
NotificationConfiguration:
TopicConfigurations:
- Topic:
Ref: "SNSTopic"
Event: 's3:ObjectCreated:*'
previewAudioFiles:
Type: 'AWS::S3::Bucket'
generatePreview:
Type: AWS::Serverless::Function
Properties:
FunctionName: !Join ["-", ['generatepreview', Ref: 'AWS::StackName']]
Handler: generatePreview.handler
Runtime: nodejs6.10
CodeUri: .
Environment:
Variables:
PipelineId: !Ref previewPipeline
Events:
BucketrawUploads:
Type: SNS
Properties:
Topic: !Ref "SNSTopic"
previewPipeline:
Type: Custom::ElasticTranscoderPipeline
DependsOn: 'rawUploads'
Version: '1.0'
Properties:
ServiceToken:
Fn::Join:
- ":"
- - arn:aws:lambda
- Ref: AWS::Region
- Ref: AWS::AccountId
- function
- aws-cloudformation-elastic-transcoder-pipeline-1-0-0
Name: transcoderPipeline
InputBucket:
!Join ["-", ['arn:aws:s3:::rawuploads', Ref: 'AWS::StackName']]
OutputBucket:
Ref: previewAudioFiles