I wanted to use the ARN as parameter input to cloudformation stack resources EventRuleRegion1 - Target as well as EventBridgeIAMrole , but it is not working. when i call with Ref function
Original ARN
arn:aws:events:ap-southeast-2:123456789123:event-bus/central-eventbus-sydney
When i give the arn directly in code its working fine.
Code
AWSTemplateFormatVersion: 2010-09-09
Parameters:
EventBridgeName:
Description: Enter the Event Bridge Name
Type: String
Default: ec2-lifecycle-events
EventBusName:
Description: Enter the Central Event Bus Name
Type: String
Default: central-eventbus-sydney
EventBusArn:
Description: Enter the ARN of Central Event Bus
Type: String
Default: arn:aws:events:ap-southeast-2:123456789123:event-bus/central-eventbus-sydney
Monitoringaccount:
Description: Enter the Monitoring AWS account number
Type: String
Default: 123456789123
Resources:
EventRuleRegion1:
Type: AWS::Events::Rule
Properties:
Description: Event rule to send events to monitoring account event bus
EventBusName: default
EventPattern:
source:
- aws.ec2
detail-type:
- "EC2 Instance State-change Notification"
detail:
state:
- "running"
- "stopped"
- "terminated"
Name: !Ref EventBridgeName
State: ENABLED
Targets:
- Arn: >-
- !Join [ "", [ !Sub "arn:aws:events:${AWS::Region}:123456789123:event-bus/",!Ref EventBusName ] ]
Id: !Ref EventBusName
RoleArn: !GetAtt
- EventBridgeIAMrole
- Arn
EventBridgeIAMrole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: !Sub events.amazonaws.com
Action: 'sts:AssumeRole'
Path: /
Policies:
- PolicyName: PutEventsDestinationBus
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- 'events:PutEvents'
Resource:
- >-
- !Join [ "", [ !Sub "arn:aws:events:${AWS::Region}:123456789123:event-bus/",!Ref EventBusName ] ]
Error
Parameter - !Join [ "", [ !Sub "arn:aws:events:${AWS::Region}:123456789123:event-bus/",!Ref EventBusName ] ] is not valid. Reason: Provided Arn is not in correct format. (Service: AmazonCloudWatchEvents; Status Code: 400; Error Code: ValidationException; Request ID: 0d52a1d6-095e-44f7-9455-b7481dc4fb8d; Proxy: null)
The use of >- will result in literal strings, not evaluation of your CFN functions (join, ref). It should be:
Targets:
- Arn: !Join [ "", [ !Sub "arn:aws:events:${AWS::Region}:123456789123:event-bus/",!Ref EventBusName ] ]
Related
Cloudformation Stack 1:
AWSTemplateFormatVersion: 2010-09-09
Metadata:
'AWS::CloudFormation::Designer':
c311c237-d7a4-4fac-a838-8a5a37a4b083:
size:
width: 60
height: 60
position:
x: 127
'y': 160
z: 0
Resources:
ECSRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: [ecs.amazonaws.com]
Action: ['sts:AssumeRole']
Path: /
Policies:
- PolicyName: ecs-service
PolicyDocument:
Statement:
- Effect: Allow
Action:
- 'ec2:AttachNetworkInterface'
- 'ec2:CreateNetworkInterface'
- 'ec2:CreateNetworkInterfacePermission'
- 'ec2:DeleteNetworkInterface'
- 'ec2:DeleteNetworkInterfacePermission'
- 'ec2:Describe*'
- 'ec2:DetachNetworkInterface'
- 'elasticloadbalancing:DeregisterInstancesFromLoadBalancer'
- 'elasticloadbalancing:DeregisterTargets'
- 'elasticloadbalancing:Describe*'
- 'elasticloadbalancing:RegisterInstancesWithLoadBalancer'
- 'elasticloadbalancing:RegisterTargets'
Resource: '*'
Outputs:
ECSTaskRoleId:
Description: ECSRoleId
Value: !GetAtt
- ECSRole
- RoleId
Export:
Name: !Join [ ':', [ !Ref 'AWS::StackName', ECSTaskRoleId ] ]
ECSTaskRoleIdECSRole:
Description: The ARN of the ECS role
Value: !GetAtt 'ECSRole.Arn'
Export:
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ECSRole' ] ]
**
Stack 2:**
Resources:
SNSRWPolicy:
Type: 'AWS::IAM::Policy'
Properties:
Role :
- Fn::ImportValue: 'testk2:ECSTaskRoleId'
PolicyName: test-snspolicy
PolicyDocument:
Statement:
- Effect: Allow
Action:
- 'sns:Publish'
- 'kms:Decrypt'
- 'kms:GenerateDataKey'
Metadata:
'AWS::CloudFormation::Designer':
id: c5c7c890-30c7-470d-9233-57b8bd630856
I am getting below error
The role with name AROA3RRAFXNEDPVQKOLIW cannot be found. (Service: AmazonIdentityManagement; Status Code: 404; Error Code: NoSuchEntity; Request ID: d5ad937f-94c3-458e-a803-0c37258e05f1; Proxy: null)
How can I import IAM::Role to attach a policy in another stack?
Beginner in CloudFormation :(
The problem is that Type: 'AWS::IAM::Policy' property Roles expects a Role name and not role ID.
CloudFormation is quite sensitive to names vs ID. So always ensure that you mention correct property.
Outputs:
ECSTaskRole:
Description: The ECSRole name
Value: !Ref ECSRole
So while exporting it will export the name and importValue will take the name properly.
AWS::IAM::Policy Roles
I am pretty new to CloudFormation and playing around with it. I am trying to create a ConfigRule that checks if an EC2 instance does not have monitoring enabled. If it is compliant or non-compliant it will then notify the user via email (SNS). It creates the resources with no errors and even sends a subscription email which I then subscribe to. However, if I change the monitoring of the ec2 to enabled or disabled, no email notification comes to my email. I tried this same scenario manually through the console and had no issues getting email notifications.
CF Designer
Here is my code:
AWSTemplateFormatVersion: "2010-09-09"
Description: ""
Parameters:
TopicName:
Type: String
Description: Topic Name
Default: my-topic
Resources:
snsTopic:
Type: AWS::SNS::Topic
Properties:
DisplayName: SNS EC2 Topic
Subscription:
- Endpoint: "test#gmail.com"
Protocol: email
TopicName: my-topic2
snsSubscription:
Type: AWS::SNS::Subscription
Properties:
TopicArn: !Ref snsTopic
Protocol: email
Endpoint: test#gmail.com
ConfigRule:
Type: "AWS::Config::ConfigRule"
DependsOn: ConfigurationRecorder
Properties:
ConfigRuleName: "ec2-monitoring-check"
Description: "A Config rule that checks if an instance has monitoring enabled"
Scope:
ComplianceResourceTypes:
- "AWS::EC2::Instance"
Source:
Owner: "AWS"
SourceIdentifier: "EC2_INSTANCE_DETAILED_MONITORING_ENABLED"
ConfigurationRecorder:
Type: "AWS::Config::ConfigurationRecorder"
Properties:
RoleARN:
Fn::GetAtt:
- "IamRoleForAwsConfig"
- "Arn"
RecordingGroup:
AllSupported: true
IncludeGlobalResourceTypes: true
DeliveryChannel:
Type: "AWS::Config::DeliveryChannel"
Properties:
S3BucketName:
Ref: "S3BucketForAwsConfig"
SnsTopicARN: !Ref snsTopic
S3BucketForAwsConfig:
Type: "AWS::S3::Bucket"
Properties: {}
IamRoleForAwsConfig:
Type: "AWS::IAM::Role"
Properties:
ManagedPolicyArns:
- "arn:aws:iam::aws:policy/service-role/AWSConfigRole"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Sid: ""
Effect: "Allow"
Principal:
Service: "config.amazonaws.com"
Action: "sts:AssumeRole"
Policies:
- PolicyName: "allow-access-to-config-s3-bucket"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- "s3:PutObject"
Resource:
- Fn::Join:
- ""
-
- Fn::GetAtt:
- "S3BucketForAwsConfig"
- "Arn"
- "/*"
Condition:
StringLike:
s3:x-amz-acl: "bucket-owner-full-control"
- Effect: "Allow"
Action:
- "s3:GetBucketAcl"
Resource:
Fn::GetAtt:
- "S3BucketForAwsConfig"
- "Arn"
myEC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-0cff7528ff583bf9a
InstanceType: t2.micro
Monitoring: false
UserData: !Base64 |
#!/bin/bash -ex
# put your script here
Tags:
- Key: Name
Value: TestEC2Instance
Metadata: {}
Conditions: {}
Outputs: {}
I tried a similar thing with CloudWatch events and the same thing occurs. I can subscribe to it but when the rule detects something, I never get the subsequent email notifications.
Anyone run into this issue or know how they can help? Thank you.
I'm getting the error below from my cloud formation template. It happens when using json and pure yaml.
error
Resource handler returned message: "Invalid request provided: JSON not well-formed. at Line: 13, Column: 10 (Service: Ssm, Status Code: 400,
template with json
AWSTemplateFormatVersion: "2010-09-09"
Description: "AWS CloudFormation Template for Response Plans"
Parameters:
Environment:
Type: String
Domain:
Type: String
Team:
Type: String
NotificationARN:
Type: AWS::SSM::Parameter::Value<String>
Default: /sandbox06/Topics/PolicyData/arn
Resources:
UpdateAliasResponsePlan:
Type: AWS::SSMIncidents::ResponsePlan
Properties:
Actions:
- SsmAutomation:
RoleArn: !Ref Role
DocumentName: UpdateAliasDocument
# ActionType: UpdateAlias
DisplayName: "UpdateLambdaAlias"
# Engagements:
# Engagements
IncidentTemplate:
Impact: 3
NotificationTargets:
- SnsTopicArn:
Ref: NotificationARN
Summary: "String"
Title: "String"
Name: "UpdateLambdaAlias"
Tags:
- Key: "Team"
Value: !Ref Team
- Key: "Domain"
Value: !Ref Domain
- Key: "Environment"
Value: !Ref Environment
UpdateAliasDocument:
Type: AWS::SSM::Document
Properties:
Content: |
{
"schemaVersion": "2.2",
"parameters": {
"Environment": { "type": "string"},
"Domain": { "type": "string"},
"Team": { "type": "string"},
"NotificationARN": { "type": "string", "default": "/sandbox06/Topics/PolicyData/arn"}
},
"mainSteps": [
{ "action": "aws:runShellScript",
"name": "runCommands",
"inputs": {
"runCommand": ["aws lambda update-functionconfiguration --function-name $FunctionArn --version $FunctionVersion"]
}
]
}
Role:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action: sts:AssumeRole
Path: /
Policies:
- PolicyName: UpdateAliasPolicy
PolicyDocument:
Statement:
- Effect: Allow
Action:
- lambda:UpdateFunctionConfiguration
Resource:
- !Sub arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${Environment}-*
template with yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: "AWS CloudFormation Template for Response Plans"
Parameters:
Environment:
Type: String
Domain:
Type: String
Team:
Type: String
NotificationARN:
Type: AWS::SSM::Parameter::Value<String>
Default: /sandbox06/Topics/PolicyData/arn
Resources:
UpdateAliasResponsePlan:
Type: AWS::SSMIncidents::ResponsePlan
Properties:
Actions:
- SsmAutomation:
RoleArn: !Ref Role
DocumentName: UpdateAliasDocument
# ActionType: UpdateAlias
DisplayName: "UpdateLambdaAlias"
# Engagements:
# Engagements
IncidentTemplate:
Impact: 3
NotificationTargets:
- SnsTopicArn:
Ref: NotificationARN
Summary: "String"
Title: "String"
Name: "UpdateLambdaAlias"
Tags:
- Key: "Team"
Value: !Ref Team
- Key: "Domain"
Value: !Ref Domain
- Key: "Environment"
Value: !Ref Environment
UpdateAliasDocument:
Type: AWS::SSM::Document
Properties:
Content:
schemaVersion: "2.2"
parameters:
- name: FunctionVersion
type: "String"
defaultValue: "1"
- name: FunctionArn
type: "String"
mainSteps:
- action: aws:runShellScript
name: "runCommand"
inputs:
runCommand: "aws lambda update-function-configuration --function-name $FunctionArn --version $FunctionVersion"
Role:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action: sts:AssumeRole
Path: /
Policies:
- PolicyName: UpdateAliasPolicy
PolicyDocument:
Statement:
- Effect: Allow
Action:
- lambda:UpdateFunctionConfiguration
Resource:
- !Sub arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${Environment}-*
Another YAML Version
AWSTemplateFormatVersion: "2010-09-09"
Description: "AWS CloudFormation Template for Response Plans"
Parameters:
Environment:
Type: String
Domain:
Type: String
Team:
Type: String
NotificationARN:
Type: AWS::SSM::Parameter::Value<String>
Default: /sandbox06/Topics/PolicyData/arn
Resources:
UpdateAliasResponsePlan:
Type: AWS::SSMIncidents::ResponsePlan
Properties:
Actions:
- SsmAutomation:
RoleArn: !Ref Role
DocumentName: UpdateAliasDocument
# ActionType: UpdateAlias
DisplayName: "UpdateLambdaAlias"
# Engagements:
# Engagements
IncidentTemplate:
Impact: 3
NotificationTargets:
- SnsTopicArn:
Ref: NotificationARN
Summary: "String"
Title: "String"
Name: "UpdateLambdaAlias"
Tags:
- Key: "Team"
Value: !Ref Team
- Key: "Domain"
Value: !Ref Domain
- Key: "Environment"
Value: !Ref Environment
UpdateAliasDocument:
Type: AWS::SSM::Document
Properties:
Content:
schemaVersion: "2.2"
parameters:
- name: FunctionVersion
type: "String"
defaultValue: "1"
- name: FunctionName
type: "String"
mainSteps:
- name: UpdateLambdaAlias
action: aws:executeAWSApi
inputs:
Service: "lambda"
Api: UpdateFunctionConfiguration
FunctionName: $FunctionName
FunctionVersion: $FunctionVersion
Role:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action: sts:AssumeRole
Path: /
Policies:
- PolicyName: UpdateAliasPolicy
PolicyDocument:
Statement:
- Effect: Allow
Action:
- lambda:UpdateFunctionConfiguration
Resource:
- !Sub arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${Environment}-*
You're getting the error when it tries to resolve the SSM parameters. It is a 400 error, so it may be that you don't have permission to retrieve the parameter from SSM. In this case it is looking for /sandbox06/Topics/PolicyData/arn so verify that the account you are using to create the stack has permission to retrieve that parameter. This article shows the permissions needed.
If so, also verify that the value of that parameter in SSM would result in a valid template if you pasted it into your template. Verify that the SSM parameter is of type String, as AWS::SSM::Parameter::Value<String> is
A Systems Manager parameter whose value is a string. This corresponds
to the String parameter type in Parameter Store.
That link also mentions the following and gives an alternative if you are want to fetch a secure string:
AWS CloudFormation does not support defining template parameters as
SecureString Systems Manager parameter types.
Also, it may be that you need to format the default to not start with a slash. This page shows an example that does not start with a slash, or for hierarchical parameters that do begin with a slash, it may need to be in single quotes (Example 2 shows it that way)
The problem was with the way I was defining the parameters. I needed to remove the name key.
replace
UpdateAliasDocument:
Type: AWS::SSM::Document
Properties:
Content:
schemaVersion: "2.2"
parameters:
- name: FunctionVersion
type: "String"
defaultValue: "1"
- name: FunctionName
type: "String"
mainSteps:
- name: UpdateLambdaAlias
action: aws:executeAWSApi
inputs:
Service: "lambda"
Api: UpdateFunctionConfiguration
FunctionName: $FunctionName
FunctionVersion: $FunctionVersion
with
UpdateAliasDocument:
Type: AWS::SSM::Document
Properties:
Content:
schemaVersion: "2.2"
parameters:
FunctionVersion
type: "String"
defaultValue: "1"
FunctionName
type: "String"
mainSteps:
- name: UpdateLambdaAlias
action: aws:executeAWSApi
inputs:
Service: "lambda"
Api: UpdateFunctionConfiguration
FunctionName: $FunctionName
FunctionVersion: $FunctionVersion
Below is my Cloudformation template I want add multiple resources getting below error
Template contains errors.: Template format error: YAML not well-formed. (line 61, column 1)
AWSTemplateFormatVersion: 2010-09-09
Description: >-
This template creates IoT policy - attaches to a device certificate, IoT Topic
Rule- used to forward messages to sns based on service key, and creates
required IAM roles for these.
Parameters:
vpcname:
Type: String
Description: Enter vpcname
vpcnamefirstletterupper:
Type: String
Description: Enter vpcname with camelcase, ex- "Usdevms"
taaccountid:
Type: String
Description: Enter TA AccountID"
Resources:
IoTDaasDeviceRole:
Type: 'AWS::IAM::Role'
Properties:
RoleName: !Join ["",[IoTDaasDeviceRole.,!Ref vpcname]]
MaxSessionDuration : 43200
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
AWS: !Join ["",[!Sub 'arn:aws:iam::${AWS::AccountId}:role/Daas',!Ref vpcnamefirstletterupper,'IotCredentialLambda']]
Service: lambda.amazonaws.com
Action:
- 'sts:AssumeRole'
IoTDaasDevicePolicy:
Type: 'AWS::IAM::ManagedPolicy'
Properties:
Description: >-
This Policy will be attached to the device role and lists the
permissions given to device certificates
ManagedPolicyName: !Join
- ''
- - 'IoTDaasDeviceConnectPolicy.'
- !Ref vpcname
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: 'iot:Connect'
Resource: !Join
- ''
- - !Sub 'arn:aws:iot:${AWS::Region}:${AWS::AccountId}:client/'
- '*'
- Effect: Allow
Action: 'iot:Publish'
Resource: !Join
- ''
- - !Sub 'arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topic/$aws/rules/daas_device_events_rule_'
- !Ref vpcname
- '/*'
- Effect: Allow
Action: 'iot:StartNextPendingJobExecution'
Resource: {
!Join ["",[!Sub 'arn:aws:iot:${AWS::Region}:${AWS::AccountId}:things/','*']],
!Join ["",[!Sub 'arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topic/$aws/things/thingName/jobs/start-next/']],
!Join ["",[!Sub 'arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topicfilter/$aws/things/thingName/jobs/start-next/accepted']],
!Join ["",[!Sub 'arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topicfilter/$aws/things/thingName/jobs/start-next/rejected']]
}
- Effect: Allow
Action: 'iot:UpdateJobExecution'
Resource: !Join ["",[!Sub 'arn:aws:iot:${AWS::Region}:${AWS::AccountId}:things/','*']]
- Effect: Allow
Action: 'execute-api:Invoke'
Resource: !Join ['', [!Sub 'arn:aws:execute-api:${AWS::Region}:',!Ref taaccountid,':hpe5n6k1v8/Test/GET']]
Roles:
- Ref: IoTDaasDeviceRole
The following is incorrect:
Resource: {
!Join ["",[!Sub 'arn:aws:iot:${AWS::Region}:${AWS::AccountId}:things/','*']],
!Join ["",[!Sub 'arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topic/$aws/things/thingName/jobs/start-next/']],
!Join ["",[!Sub 'arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topicfilter/$aws/things/thingName/jobs/start-next/accepted']],
!Join ["",[!Sub 'arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topicfilter/$aws/things/thingName/jobs/start-next/rejected']] }
as it creates a map, but you need a list:
Resource:
- !Join ["",[!Sub 'arn:aws:iot:${AWS::Region}:${AWS::AccountId}:things/','*']]
- !Join ["",[!Sub 'arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topic/$aws/things/thingName/jobs/start-next/']]
- !Join ["",[!Sub 'arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topicfilter/$aws/things/thingName/jobs/start-next/accepted']]
- !Join ["",[!Sub 'arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topicfilter/$aws/things/thingName/jobs/start-next/rejected']]
Please note that there still can be issues in your template, which are not apparent yet.
You can use the aws cloudformation command line to validate your template, here's the output when running it on the file you provided:
$ aws cloudformation validate-template --template-body file://test.template
An error occurred (ValidationError) when calling the ValidateTemplate operation: Template format error: [/Resources/IoTDaasDevicePolicy/Type/PolicyDocument/Statement/2/Resource] map keys must be strings; received a map instead
The validation succeeded when I corrected the faulty bloc using Marcin's answer:
{
"Parameters": [
{
"ParameterKey": "vpcname",
"NoEcho": false,
"Description": "Enter vpcname"
},
{
"ParameterKey": "taaccountid",
"NoEcho": false,
"Description": "Enter TA AccountID\""
},
{
"ParameterKey": "vpcnamefirstletterupper",
"NoEcho": false,
"Description": "Enter vpcname with camelcase, ex- \"Usdevms\""
}
],
"Description": "This template creates IoT policy - attaches to a device certificate, IoT Topic Rule- used to forward messages to sns based on service key, and creates required IAM roles for these.",
"Capabilities": [
"CAPABILITY_NAMED_IAM"
],
"CapabilitiesReason": "The following resource(s) require capabilities: [AWS::IAM::Role]"
}
I'm creating an ASG group which has a lifecyclehook for termination:
LifecycleHook:
Type: AWS::AutoScaling::LifecycleHook
Properties:
AutoScalingGroupName: !Ref NodeGroup
DefaultResult: CONTINUE
HeartbeatTimeout: 60
LifecycleHookName: !Sub "${AWS::StackName}-lifecycle-hook"
LifecycleTransition: autoscaling:EC2_INSTANCE_TERMINATING
Now I create a lambda function as well:
LambdaCreation:
Type: "AWS::Lambda::Function"
Properties:
Handler: "lambda_function.lambda_handler"
Environment:
Variables:
aws_region : !Ref AWSRegion
Role: !GetAtt LambdaExecutionRole.Arn
Code:
S3Bucket: !Ref LambdaCodeBucket
S3Key: "lambda-functions/function.zip"
Runtime: "python3.6"
Timeout: 60
On cloudwatch events, i created a rule for said event:
CloudwatchEvent:
Type: AWS::Events::Rule
Properties:
Description: ASG scale-in event to lambda
EventPattern: {
"source": [
"aws.autoscaling"
],
"detail-type": [
"EC2 Instance-terminate Lifecycle Action"
],
"detail": {
"AutoScalingGroupName":
[
{
"Fn::ImportValue" :
{
"Fn::Sub" : "${RootStackName}-nodes-asg-name"
}
}
]
}
}
State: ENABLED
Targets:
-
Arn:
!GetAtt LambdaCreation.Arn
Id:
!Ref LambdaCreation
But the lambda is never triggered.
Now, on AWS console I don't see a trigger on the designer. But if i add manually a cloudwatch trigger for the created rule, it starts working...
Why is the trigger on the lambda side not created? What am I missing?
Thanks all!
I faced the exact same frustration. Only difference is that I was using terraform but that's irrelavant.
You are missing this:
{
"Type" : "AWS::Lambda::Permission",
"Properties" : {
"Action" : String,
"EventSourceToken" : String,
"FunctionName" : String,
"Principal" : String,
"SourceAccount" : String,
"SourceArn" : String
}
}
The reason the "manual way" works because it creates the trigger AND the permission. When you provision stuff using IaC tools like Cloudformation/terraform, you need to explicitly specify this Lambda permission object.
The below code snippet creates a lambda function and creates a cloudwatch event to trigger the lambda function with necessary privileges.
LambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Path: "/"
Policies:
- PolicyName: root
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- logs:*
Resource: arn:aws:logs:*:*:*
- Effect: Allow
Action:
- s3:ListBucket
Resource: !Join [ '', [ 'arn:aws:s3:::', !Ref LambdaS3Bucket ] ]
- Effect: Allow
Action:
- s3:GetObject
Resource: !Join [ '', [ 'arn:aws:s3:::', !Ref LambdaS3Bucket, '/*' ] ]
- Effect: Allow
Action:
- sts:GetCallerIdentity
Resource: '*'
LambdaFunction:
Type: "AWS::Lambda::Function"
Properties:
Description: "Lambda function"
FunctionName: !Ref LambdaFunctionName
Handler: !Ref LambdaHandler
Runtime: !Ref LambdaRuntime
Timeout: !Ref LambdaTimeout
MemorySize: !Ref LambdaMemorysize
Role: !GetAtt LambdaExecutionRole.Arn
Code:
S3Bucket: !Ref LambdaS3Bucket
S3Key: !Ref LambdaS3BucketKey
Environment:
Variables:
time_interval_in_hours: !Ref TimeIntervalInHours
DependsOn: LambdaExecutionRole
CleanupEventRule:
Type: AWS::Events::Rule
Properties:
Description: "Cloudwatch Rule"
ScheduleExpression: !Ref CloudwatchScheduleExpression
State: !Ref CloudWatchEventState
Targets:
- Arn: !Sub ${LambdaFunction.Arn}
Id: "CleanupEventRule"
DependsOn: LambdaFunction
LambdaSchedulePermission:
Type: AWS::Lambda::Permission
Properties:
Action: 'lambda:InvokeFunction'
FunctionName: !Sub ${LambdaFunction.Arn}
Principal: 'events.amazonaws.com'
SourceArn: !Sub ${CleanupEventRule.Arn}
DependsOn: LambdaFunction