Setup Lambda to trigger from CloudWatch using CloudFormation - amazon-web-services

I want to use CloudFormation to trigger Lambda when my CloudWatch function is called. I have the below, but it does not work.
CloudWatch rule created fine
"CloudWatchNewEc2": {
"Type": "AWS::Events::Rule",
"DependsOn": ["LambdaNewEc2"],
"Properties": {
"Description": "Triggered on new EC2 instances",
"EventPattern": {
"source": [
"aws.ec2"
],
"detail-type": [
"AWS API Call via CloudTrail"
],
"detail": {
"eventSource": [
"ec2.amazonaws.com"
],
"eventName": [
"RunInstances"
]
}
},
"Targets": [
{
"Arn": {
"Fn::GetAtt": ["LambdaNewEc2", "Arn"]
},
"Id": "NewEc2AutoTag"
}
]
}
},
Lambda created but is not triggered
"LambdaNewEc2": {
"Type": "AWS::Lambda::Function",
"DependsOn": ["S3Lambda", "IAMRoleLambda"],
"Properties": {
"Code": {
"S3Bucket": {"Ref": "LambdaBucketName"},
"S3Key": "skynet-lambda.zip"
},
"Description": "When new EC2 instances are created, auto tag them",
"FunctionName": "newEc2AutoTag",
"Handler": "index.newEc2_autoTag",
"Role": {"Fn::GetAtt": ["IAMRoleLambda", "Arn"]},
"Runtime": "nodejs6.10",
"Timeout": "30"
}
}
},
It seems like CloudWatch Target is not sufficient?
UPDATE (Full CloudFormation template)
{
"Parameters": {
"Environment": {
"Type": "String",
"Default": "Staging",
"AllowedValues": [
"Testing",
"Staging",
"Production"
],
"Description": "Environment name"
},
"BucketName": {
"Type": "String",
"Default": "skynet-staging",
"Description": "Bucket Name"
},
"LambdaBucketName": {
"Type": "String",
"Default": "skynet-lambda",
"Description": "Lambda Bucket Name"
},
"Owner": {
"Type": "String",
"Description": "Owner"
}
},
"Resources": {
"S3Web": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": {
"Ref": "BucketName"
},
"WebsiteConfiguration": {
"IndexDocument": "index.html",
"RoutingRules": [
{
"RedirectRule": {
"ReplaceKeyPrefixWith": "#"
},
"RoutingRuleCondition": {
"HttpErrorCodeReturnedEquals": "404"
}
}
]
},
"AccessControl": "PublicRead",
"Tags": [
{
"Key": "Cost Center",
"Value": "Skynet"
},
{
"Key": "Environment",
"Value": {
"Ref": "Environment"
}
},
{
"Key": "Owner",
"Value": {
"Ref": "Owner"
}
}
]
}
},
"S3Lambda": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": {
"Ref": "LambdaBucketName"
},
"VersioningConfiguration": {
"Status": "Enabled"
},
"Tags": [
{
"Key": "Cost Center",
"Value": "Skynet"
},
{
"Key": "Owner",
"Value": {
"Ref": "Owner"
}
}
]
}
},
"CloudWatchNewEc2": {
"Type": "AWS::Events::Rule",
"DependsOn": ["LambdaNewEc2"],
"Properties": {
"Description": "Triggered on new EC2 instances",
"EventPattern": {
"source": [
"aws.ec2"
],
"detail-type": [
"AWS API Call via CloudTrail"
],
"detail": {
"eventSource": [
"ec2.amazonaws.com"
],
"eventName": [
"RunInstances"
]
}
},
"Targets": [
{
"Arn": {
"Fn::GetAtt": ["LambdaNewEc2", "Arn"]
},
"Id": "NewEc2AutoTag"
}
]
}
},
"IAMRoleLambda": {
"Type": "AWS::IAM::Role",
"Properties": {
"RoleName": "skynet-lambda-role",
"AssumeRolePolicyDocument": {
"Version" : "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [ "lambda.amazonaws.com" ]
},
"Action": [ "sts:AssumeRole" ]
}
]
},
"ManagedPolicyArns": [
"arn:aws:iam::aws:policy/AmazonEC2FullAccess",
"arn:aws:iam::aws:policy/AWSLambdaFullAccess",
"arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess",
"arn:aws:iam::aws:policy/CloudWatchLogsFullAccess"
]
}
},
"LambdaNewEc2": {
"Type": "AWS::Lambda::Function",
"DependsOn": ["S3Lambda", "IAMRoleLambda"],
"Properties": {
"Code": {
"S3Bucket": {"Ref": "LambdaBucketName"},
"S3Key": "skynet-lambda.zip"
},
"Description": "When new EC2 instances are created, auto tag them",
"FunctionName": "newEc2AutoTag",
"Handler": "index.newEc2_autoTag",
"Role": {"Fn::GetAtt": ["IAMRoleLambda", "Arn"]},
"Runtime": "nodejs6.10",
"Timeout": "30"
}
}
},
"Outputs": {
"WebUrl": {
"Value": {
"Fn::GetAtt": [
"S3Web",
"WebsiteURL"
]
},
"Description": "S3 bucket for web files"
}
}
}

I managed to deploy your template into a CloudFormation stack (by removing the LambdaBucket and pointing to my own zip file). It seems to create all resource correctly.
It took about 10 minutes for the RunInstances event to appear in CloudTrail. It then successfully triggered the Rule, but the CloudWatch metrics for my rule showed a failed invocation because I faked a Lambda function for your template.
Once I edited the rule to point to a better function and re-tested, it worked fine.
Bottom line: Seems to work!

Related

Lambda RDS Proxy connection from different VPC

I have two AWS accounts with VPCs connected with peer connections. I have RDS Proxy on account 1 and Lambda in the private, isolated subnet on account 2.
I cannot figure out how to connect to RDS Proxy. I was trying all possible VPC endpoints and interfaces and whatnot.
The only way I managed to connect was through NAT Gateway, but it's expensive. And to be honest, weird, if I want to keep a private network.
Is it possible to have a PrivateLink or something?
How should I connect to RDS Proxy from Lambda?
I have attached the CF template (I hope I cleaned it from all sensitive data 😑):
{
"Resources": {
"vpcA2121C38": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "10.0.0.0/16",
"EnableDnsHostnames": true,
"EnableDnsSupport": true,
"InstanceTenancy": "default"
},
"Metadata": {
"aws:cdk:path": "Mws/vpc/Resource"
}
},
"vpcPrivateSubnet1Subnet934893E8": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "10.0.0.0/26",
"VpcId": {
"Ref": "vpcA2121C38"
},
"AvailabilityZone": {
"Fn::Select": [
0,
{
"Fn::GetAZs": ""
}
]
},
"MapPublicIpOnLaunch": false
},
"Metadata": {
"aws:cdk:path": "Mws/vpc/PrivateSubnet1/Subnet"
}
},
"vpcPrivateSubnet1RouteTableB41A48CC": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "vpcA2121C38"
}
},
"Metadata": {
"aws:cdk:path": "Mws/vpc/PrivateSubnet1/RouteTable"
}
},
"vpcPrivateSubnet1RouteTableAssociation67945127": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"RouteTableId": {
"Ref": "vpcPrivateSubnet1RouteTableB41A48CC"
},
"SubnetId": {
"Ref": "vpcPrivateSubnet1Subnet934893E8"
}
},
"Metadata": {
"aws:cdk:path": "Mws/vpc/PrivateSubnet1/RouteTableAssociation"
}
},
"vpcS3CB758969": {
"Type": "AWS::EC2::VPCEndpoint",
"Properties": {
"ServiceName": {
"Fn::Join": [
"",
[
"com.amazonaws.",
{
"Ref": "AWS::Region"
},
".s3"
]
]
},
"VpcId": {
"Ref": "vpcA2121C38"
},
"RouteTableIds": [
{
"Ref": "vpcPrivateSubnet1RouteTableB41A48CC"
}
],
"VpcEndpointType": "Gateway"
},
"Metadata": {
"aws:cdk:path": "Mws/vpc/S3/Resource"
}
},
"vpcPeertomainaccount833D3E2C": {
"Type": "AWS::EC2::VPCPeeringConnection",
"Properties": {
"PeerVpcId": "vpc-f04b939b",
"VpcId": {
"Ref": "vpcA2121C38"
},
"PeerOwnerId": "XXXX__ACCOINT_1__XXXXXX",
"PeerRoleArn": "arn:aws:iam::XXXX__ACCOINT_1__XXXXXX:role/VPCPeerConnection"
},
"Metadata": {
"aws:cdk:path": "Mws/vpc/Peer to main account"
}
},
"producerServiceRoleEBCB54D0": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
}
}
],
"Version": "2012-10-17"
},
"ManagedPolicyArns": [
{
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
]
]
},
{
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
]
]
}
]
},
"Metadata": {
"aws:cdk:path": "Mws/producer/producer/ServiceRole/Resource"
}
},
"producerServiceRoleDefaultPolicyEA5B80A1": {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyDocument": {
"Statement": [
{
"Action": [
"xray:PutTraceSegments",
"xray:PutTelemetryRecords"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Action": [
"s3:GetObject*",
"s3:GetBucket*",
"s3:List*"
],
"Effect": "Allow",
"Resource": [
{
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":s3:::",
{
"Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}"
}
]
]
},
{
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":s3:::",
{
"Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}"
},
"/*"
]
]
}
]
}
],
"Version": "2012-10-17"
},
"PolicyName": "producerServiceRoleDefaultPolicyEA5B80A1",
"Roles": [
{
"Ref": "producerServiceRoleEBCB54D0"
}
]
},
"Metadata": {
"aws:cdk:path": "Mws/producer/producer/ServiceRole/DefaultPolicy/Resource"
}
},
"producerSecurityGroup9AA1BE28": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Automatic security group for Lambda Function Mwsproducer416E938A",
"SecurityGroupEgress": [
{
"CidrIp": "0.0.0.0/0",
"Description": "Allow all outbound traffic by default",
"IpProtocol": "-1"
}
],
"VpcId": {
"Ref": "vpcA2121C38"
}
},
"Metadata": {
"aws:cdk:path": "Mws/producer/producer/SecurityGroup/Resource"
}
},
"producerAD962441": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Code": {
"S3Bucket": {
"Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}"
},
"S3Key": "dc05df325f7034421a587e7ee47aed301c7472d001152e686053dd9d5c45c164.zip"
},
"Role": {
"Fn::GetAtt": [
"producerServiceRoleEBCB54D0",
"Arn"
]
},
"Description": "Produces MWS customer orders messages",
"Environment": {
"Variables": {
"DB_HOST": "mws-rds-proxy.proxy-XXXXXXXXX.eu-central-1.rds.amazonaws.com",
"DB_NAME": "dev"
}
},
"Handler": "lambda/mws_producer.php",
"Layers": [
"arn:aws:lambda:eu-central-1:209497400698:layer:php-80:18"
],
"MemorySize": 1024,
"Runtime": "provided.al2",
"Timeout": 900,
"TracingConfig": {
"Mode": "Active"
},
"VpcConfig": {
"SecurityGroupIds": [
{
"Fn::GetAtt": [
"producerSecurityGroup9AA1BE28",
"GroupId"
]
}
],
"SubnetIds": [
{
"Ref": "vpcPrivateSubnet1Subnet934893E8"
}
]
}
},
"DependsOn": [
"producerServiceRoleDefaultPolicyEA5B80A1",
"producerServiceRoleEBCB54D0"
]
}
}
}
Devil as we know hidden in detail. In this case, it's a Route Tables.
When we create a Peering connection between VPCs we also need to give to know our subnets how to use it. Basically, just add peering connection id (pcx-XXX) as a target for peering network.
Took me several days to realize it. Happy happy happy!

Import s3 bucket from one stack to other stack

I have created S3 Bucket with deletepolicy retain using cloud formation, I Have exported the created bucket using Export in outputs in cloudformation.
Now I want to use the same s3 bucket in another stack using import
Cloud formation for s3:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Creates an S3 bucket to be used for static content/website hosting.",
"Parameters": {
"AssetInsightId": {
"Description": "Asset Insight ID",
"Type": "String",
"Default": "206153"
},
"ResourceOwner": {
"Description": "tr:resource-owner",
"Type": "String",
"Default": "####"
},
"EnvironmentType": {
"Description": "tr:environment-type",
"Default": "preprod",
"Type": "String",
"AllowedValues": ["preprod", "prod"],
"ConstraintDescription": "must specify preprod, prod."
}
},
"Resources": {
"S3Bucket": {
"Type": "AWS::S3::Bucket",
"DeletionPolicy": "Retain",
"Properties": {
"BucketName": {
"Fn::Sub": "a${AssetInsightId}-s3bucket-${EnvironmentType}"
},
"Tags": [{
"Key": "tr:application-asset-insight-id",
"Value": {
"Fn::Sub": "${AssetInsightId}"
}
}, {
"Key": "tr:environment-type",
"Value": {
"Fn::Sub": "${EnvironmentType}"
}
}
]
}
}
},
"Outputs": {
"S3Bucket": {
"Description": "Information about the value",
"Description": "Name of the S3 Resource Bucket",
"Value": "!Ref S3Bucket",
"Export": {
"Name": "ExportS3Bucket"
}
}
}
}
cloud formation to use created s3 bucket from another template with import
Second template :
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Creates an S3 apigateway to be used for static content/website hosting.",
"Parameters": {
"AssetInsightId": {
"Description": "Asset Insight ID",
"Type": "String",
"Default": "206153"
},
"ResourceOwner": {
"Description": "tr:resource-owner",
"Type": "String",
"Default": "swathi.koochi#thomsonreuters.com"
},
"EnvironmentType": {
"Description": "tr:environment-type",
"Default": "preprod",
"Type": "String",
"AllowedValues": ["preprod", "prod"],
"ConstraintDescription": "must specify preprod, prod."
},
"endpointConfiguration": {
"Description": "tr:endpoint-configuration",
"Default": "REGIONAL",
"Type": "String",
"AllowedValues": ["REGIONAL", "EDGE"],
"ConstraintDescription": "must specify REGIONAL, EDGE."
}
},
"Resources": {
"S3BucketImport": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": {"Fn::ImportValue" : "ExportS3Bucket"}
}
},
"APIGateWayRestResourceRestApi": {
"Type": "AWS::ApiGateway::RestApi",
"Properties": {
"Name": "MyAPI",
"Description": "API Gateway rest api with cloud formation",
"EndpointConfiguration": {
"Types": [{
"Ref": "endpointConfiguration"
}
]
}
}
},
"APIGateWayResource": {
"Type": "AWS::ApiGateway::Resource",
"Properties": {
"RestApiId": {
"Ref": "APIGateWayRestResourceRestApi"
},
"ParentId": {
"Fn::GetAtt": ["APIGateWayRestResourceRestApi", "RootResourceId"]
},
"PathPart": "test"
}
},
"APIGatewayPostMethod": {
"Type": "AWS::ApiGateway::Method",
"Properties": {
"AuthorizationType": "NONE",
"HttpMethod": "POST",
"Integration": {
"Type": "AWS_PROXY",
"IntegrationHttpMethod": "POST",
"Uri": {
"Fn::Sub": "arn:aws:apigateway:us-east-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-2:861756181523:function:GreetingLambda/invocations"
}
},
"MethodResponses": [{
"ResponseModels": {
"application/json": {
"Ref": "PostMethodResponse"
}
},
"StatusCode": 200
}
],
"ResourceId": {
"Ref": "APIGateWayResource"
},
"RestApiId": {
"Ref": "APIGateWayRestResourceRestApi"
}
}
},
"PostMethodResponse": {
"Type": "AWS::ApiGateway::Model",
"Properties": {
"ContentType": "application/json",
"Name": "PostMethodResponse",
"RestApiId": {
"Ref": "APIGateWayRestResourceRestApi"
},
"Schema": {
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "PostMethodResponse",
"type": "object",
"properties": {
"Email": {
"type": "string"
}
}
}
}
},
"RestApiDeployment": {
"DependsOn": "APIGatewayPostMethod",
"Type": "AWS::ApiGateway::Deployment",
"Properties": {
"RestApiId": {
"Ref": "APIGateWayRestResourceRestApi"
}
}
},
"RestAPIStage": {
"Type": "AWS::ApiGateway::Stage",
"Properties": {
"DeploymentId": {
"Ref": "RestApiDeployment"
},
"MethodSettings": [{
"DataTraceEnabled": true,
"HttpMethod": "*",
"ResourcePath": "/*"
}
],
"RestApiId": {
"Ref": "APIGateWayRestResourceRestApi"
},
"StageName": "Latest"
}
},
"APIGateWayDomainName": {
"Type": "AWS::ApiGateway::DomainName",
"Properties": {
"CertificateArn": {
"Ref": "myCertificate"
},
"DomainName": {
"Fn::Join": [".", [{
"Ref": "AssetInsightId"
}, {
"Ref": "EnvironmentType"
}, "api"]]
},
"EndpointConfiguration": {
"Types": [{
"Ref": "endpointConfiguration"
}
]
}
}
},
"myCertificate": {
"Type": "AWS::CertificateManager::Certificate",
"Properties": {
"DomainName": {
"Fn::Join": [".", [{
"Ref": "AssetInsightId"
}, {
"Ref": "EnvironmentType"
}, "api"]]
}
}
}
}
}
when I/m trying to import using Import Value, I'm getting error saying
S3BucketImport
CREATE_FAILED Bad Request (Service: Amazon S3; Status Code: 400; Error Code: 400 Bad Request; Request ID: 9387EBE0E472E559; S3 Extended Request ID: o8EbE20IOoUgEMwXc7xVjuoyQT03L/nnQ7AsC94Ff1S/PkE100Imeyclf1BxYeM0avuYjDWILxA=)
As #Jarmod correctly pointed out,
In your first template, export the s3 bucket name using { "Ref" : ",S3Bucket" }
In your second template, you don't have to create the bucket again.you can use the exported value from the first template if you want to refer the bucket name from resources. But i don't see any of the resources in the second template refer the S3 bucket name.

Configure the LoadBalancer in AWS CloudWatch Alarm

I have a web application on AWS and I am trying to configure my autoscaling based on the requests.
My AppLoadBalancer resource is as below:
"AppLoadBalancer": {
"Properties": {
"LoadBalancerAttributes": [
{
"Key": "idle_timeout.timeout_seconds",
"Value": "60"
}
],
"Name": "sample-app-v1",
"Scheme": "internet-facing",
"SecurityGroups": [
"sg-1abcd234"
],
"Subnets": {
"Fn::FindInMap": [
"LoadBalancerSubnets",
{
"Ref": "AWS::Region"
},
"Subnets"
]
},
"Tags": [
{
"Key": "Name",
"Value": "sample-app-v1"
},
{
"Key": "StackName",
"Value": "sample-app"
},
{
"Key": "StackVersion",
"Value": "v1"
}
]
},
"Type": "AWS::ElasticLoadBalancingV2::LoadBalancer"
}
I am trying to configure a CloudWatch Alarm like this:
"RequestCountTooHighAlarm": {
"Properties": {
"AlarmActions": [
{
"Ref": "ScaleUp"
}
],
"AlarmDescription": "Scale-up if request count >= 8000 for last 5 minute",
"ComparisonOperator": "GreaterThanOrEqualToThreshold",
"Dimensions": [
{
"Name": "LoadBalancer",
"Value": [
{
"Fn::GetAtt": [
"AppLoadBalancer",
"LoadBalancerFullName"
]
}
]
}
],
"EvaluationPeriods": 1,
"MetricName": "RequestCount",
"Namespace": "AWS/ApplicationELB",
"OKActions": [
{
"Ref": "ScaleDown"
}
],
"Period": 300,
"Statistic": "SampleCount",
"Threshold": 8000
},
"Type": "AWS::CloudWatch::Alarm"
}
However, my stack continues to fail and I don't know what is wrong here. Here is the error which I am getting.
ERROR: RequestCountTooHighAlarm CREATE_FAILED: Value of property Value must be of type String
ERROR: sample-app-v1 CREATE_FAILED: The following resource(s) failed to create: [RequestCountTooHighAlarm].
Can somebody suggest?
The property mentioned requires a string. You have it defined as a list:
"Value": [
{
"Fn::GetAtt": [
"AppLoadBalancer",
"LoadBalancerFullName"
]
} ]
The [] brackets defines a list in JSON. Remove the outside brackets in the Value value, and use only the Fn::GetAt portion. That call will return a string.

Cloud Formation: S3 linked to Lambda gives The ARN is not well formed

I'm trying to use CloudFormation to deploy an S3 bucket that on ObjectCreate invokes a Lambda function.
Here are my resources:
"ExampleFunction": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Handler": "index.lambda_handler",
"Code": {
"S3Bucket": "bucketname",
"S3Key": "something.zip"
},
"Runtime": "python3.6",
"Role": {
"Fn::GetAtt": [
"LambdaExecutionRole",
"Arn"
]
}
}
},
"InputDataBucket": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": "input-data",
"NotificationConfiguration": {
"LambdaConfigurations": [
{
"Function": {
"Ref": "ExampleFunction"
},
"Event": "s3:ObjectCreated:*",
"Filter": {
"S3Key": {
"Rules": [
{
"Name": "suffix",
"Value": "zip"
}
]
}
}
}
]
}
}
},
"LambdaInvokePermission": {
"Type": "AWS::Lambda::Permission",
"Properties": {
"Action": "lambda:InvokeFunction",
"FunctionName": {
"Fn::GetAtt": [
"ExampleFunction",
"Arn"
]
},
"Principal": "s3.amazonaws.com",
"SourceAccount": {
"Ref": "AWS::AccountId"
},
"SourceArn": {
"Fn::Join": [
":",
[
"arn",
"aws",
"s3",
"",
"",
{
"Ref": "InputDataBucket"
}
]
]
}
}
}
I've tried to follow the documentation of the Notification Configuration, that says that there can be a circular dependency. However, if I follow the instructions I get the same error. Reference: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-notificationconfig.html
When I try to create the stack, the S3 always breaks it with error "The ARN is not well formed"
I've tried many things, but I always receive this same error.
I can get this to work as long as I know the S3 bucket name in advance (mybucketname below). If you don't know the bucket name in advance, then you can enhance this to request the bucket name as a stack parameter and it should still work. If you need the bucket name to be auto-generated (so you can't predict the name in advance) then this will not work and you'll have to go the create/update route.
Key thing here is to manually create the S3 bucket ARN from the known bucket name, rather than relying on "Ref": "InputDataBucket" to get the bucket name for you.
Also worth reading this support article.
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "stackoverflow-48037497",
"Resources" : {
"ExampleFunction": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Handler": "index.lambda_handler",
"Code": {
"S3Bucket": "bucketname",
"S3Key": "something.zip"
},
"Runtime": "python3.6",
"Role": {
"Fn::GetAtt": [
"LambdaExecutionRole",
"Arn"
]
}
}
},
"LambdaInvokePermission": {
"Type": "AWS::Lambda::Permission",
"DependsOn": [ "ExampleFunction" ],
"Properties": {
"Action": "lambda:InvokeFunction",
"FunctionName": {
"Fn::GetAtt": [
"ExampleFunction",
"Arn"
]
},
"Principal": "s3.amazonaws.com",
"SourceAccount": {
"Ref": "AWS::AccountId"
},
"SourceArn": "arn:aws:s3:::mybucketname"
}
},
"InputDataBucket": {
"Type": "AWS::S3::Bucket",
"DependsOn": [ "ExampleFunction", "LambdaInvokePermission" ],
"Properties": {
"BucketName": "mybucketname",
"NotificationConfiguration": {
"LambdaConfigurations": [
{
"Function": { "Fn::GetAtt" : [ "ExampleFunction", "Arn" ] },
"Event": "s3:ObjectCreated:*"
}
]
}
}
}
}
}

AWS::AutoScaling::LaunchConfiguration You are not authorized to perform this operation

While cloudformation is building the stack, I get the following error:
AWS::AutoScaling::LaunchConfiguration N1ClusterServerLaunchConfig You are not authorized to perform this operation
I have admin full access user privileges. But, still this fails. Is the authorization due to the IAMs defined inside the template?
"N1ClusterServerAutoScale": {
"Type": "AWS::AutoScaling::AutoScalingGroup",
"Properties": {
"AvailabilityZones": {
"Fn::GetAZs": ""
},
"LaunchConfigurationName": {
"Ref": "N1ClusterServerLaunchConfig"
},
"MinSize": "2",
"MaxSize": "64",
"DesiredCapacity": {
"Ref": "ClusterSize"
},
"Tags": [
{
"Key": "Name",
"Value": {
"Ref": "AWS::StackName"
},
"PropagateAtLaunch": true
}
]
},
"Metadata": {
"AWS::CloudFormation::Designer": {
"id": "a715af00-ebba-4fab-a817-d5ee1986dfe7"
}
}
},
"N1ClusterServerLaunchConfig": {
"Type": "AWS::AutoScaling::LaunchConfiguration",
"Properties": {
"ImageId": {
"Fn::FindInMap": [
"RegionMap",
{
"Ref": "AWS::Region"
},
"hvm"
]
},
"InstanceType": {
"Ref": "InstanceType"
},
"KeyName": {
"Ref": "KeyPair"
},
"SecurityGroups": [
{
"Ref": "N1ClusterSecurityGroup"
},
{
"Ref": "N1NodeSecurityGroup"
}
],
"IamInstanceProfile": {
"Ref": "IamInstanceProfile"
},
IAM
"AllowComputeFrom": {
"Description": "The net block (CIDR) that N1-COMPUTE is available to.",
"Default": "0.0.0.0/0",
"Type": "String"
},
"IamInstanceProfile": {
"Description": "The name of an IAM Profile which can access required S3 buckets and instances.",
"Default": "arn:aws:iam::247256189695:instance-profile/n1-compute-instance",
"Type": "String"
},
"IamInstanceProfileShort": {
"Description": "The last part of the name of an IAM Profile which can create instances.",
"Default": "n1-compute-instance",
"Type": "String"
},
ec2:RunInstances is required to use a Launch template