AWS SAM and the changes in resource ARNs with each deployment - amazon-web-services

I see that one SAM deployment over another, that the previous resources are deleted, and new resources are created. Now, the new resources that are created are actually not the same resources, and have a different ARN than before.
This causes some problems that I am facing right now. Say that we have non SAM resources which require set for for the SAM resources.
Like for example, we have an SNS which is subscribed by our API gateway. Now after the deployment the ARN of the API gateway changes, and we'd require to subscribe again.
There are more problems like this that I am facing, but this is the gist of it.
Any help appreciated!

The ARN of the resource can remain same if the name of the resource is specified in the template. Since the name now remains the same, the ARN too will remain the same, even after multiple deployments.

Related

Using CDK, prevent resource in stack from being updated

I have a lambda deployed in a stack, that is referenced via ARN by resources that I do not manage. It is problematic that certain updates to other resources can trigger this lambda to be redeployed. So therefore I would like to put a stack policy in place like what is described here, but from within the CDK project itself. I've looked through the stack construct's docs but don't see any API's exposed. I've also looked here at the actual Stack CFN resource, and don't see it as a property you can supply.
Any help or advice would be appreciated!

AWS SAM/CloudFormation Template Lambda Delete Protection

We are migrating REST API service from EC2 to Lambda/API Gateway (to lower billing) using the AWS - SAM feature. This service is consumed only by internal application(INTRANET). We don't have VPN connectivity between on-premise and AWS. Each function is housed in a separate folder which includes a YAML file template. When deployed using the same stack name it deletes the previous function. We tried to use,
DeletionPolicy: Retain
which errored out ,
'property DeletionPolicy not defined for resource of type
AWS::Serverless::Function'
Our requirement is, to have a common base URL without using R53 (if possible).
Is there a better way to do this?
CloudFormation attributes, such as DeletionPolicy, are not defined inside the Properties section. You may need to un-indent DeletionPolicy so it is not defined within the Properties section
I believe you don't need to retain the old lambda, it's fine to delete the old as you deploy new changes.
What needed is to tied the Lambda with API gateway.
In other words, your cloudformation template should have Lambda resources and for API Gateway point to the like
Uri: !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${LambdaFunction.Arn}/invocations'
within AWS::ApiGateway::Method resources
I quoted my code block from AWS Samples on github
In case you have different cloud formation templates you might consider to Output section in cloudformation templates to export resources

How to upload contents into S3 bucket via CloudFormation template using custom resource?

Fairly new to cloudformation templating but all I am looking to create a template where I create a S3 bucket and import contents into that bucket from another S3 bucket from a different account (that is also mine). I realize CloudFormation does not natively supports importing contents into S3 bucket, and I have to utilize custom resource. I could not find any reference/resources that does such tasks. Hoping someone could point out some examples or maybe even some guidance as to how to tackle this.
Thank you very much!
Can't provide full code, but can provide some guidance. There are few ways of doing this, but I will list one:
Create a bucket policy for the bucket in the second account. The policy should allow the first account (one with cfn) to read it. There are many resources on doing this. One from AWS is here.
Create a standalone lambda function in the first account with execution role allowing it to the read bucket from the second account. This is not a custom resource yet. The purpose of this lambda function is to test the cross-account permissions, and your code which reads objects from it. This is like a test function to sort out all the permissions and polish object copying code from one bucket to other.
Once your lambda function works as intended, you modify it (or create new one) as a custom resource in CFN. As a custom resource, it will need to take your newly created bucket in cfn as one of its arguments. For easier creation of custom resources this aws helper can be used.
Note, that the lambda execution timeout is 15 minutes. Depending on how many objects you have, it may be not enough.
Hope this helps.
If Custom Resources scare you, then a simpler way is to launch an Amazon EC2 instance with a startup script specified via User Data.
The CloudFormation template can 'insert' the name of the new bucket into the script by referencing the bucket resource that was created. The script could then run an AWS CLI command to copy the files across.
Plus, it's not expensive. A t3.micro instance is about 1c/hour and it is charged per second, so it's pretty darn close to free.

How do I add a Lambda Function with an S3 Trigger in CloudFormation?

I've been working with CloudFormation YAML for awhile and have found it to be comprehensive - until now. I'm struggling in trying to use SAM/CloudFormation to create a Lambda function that is triggered whenever an object is added to an existing S3 bucket.
All of the examples I've seen thus far seem to require that you create the bucket in the same CloudFormation script as you create the Lambda function. This doesn't work for me, because we have a design goal to be able to use CloudFormation redeploy our entire stack to different regions or AWS accounts and quickly stand up our application. S3 bucket names must be globally unique, so if I create the bucket in CloudFormation, the script will break when I try to deploy it to a different region/account. I could probably get around this by creating buckets with the account name/region in the name, but that's just not desirable from a bucket sprawl perspective.
So, does anyone have a solution for creating a Lambda function in CloudFormation that is triggered by objects being written to an existing S3 bucket?
Thanks!
This is impossible, according to the SAM team. This is something which the underlying CloudFormation service can't do.
There is a possible workaround, if you implement a Custom resource which would trigger a separate Lambda function to modify the existing bucket and link it to the Lambda function that you want to deploy.
As "implement a Custom Resource" isn't very specific: Here is an AWS github repo with scaffold code to help write it, and then you declare something like the following in your template (where LambdaToBucket) is the custom function you wrote. I've found that you need to configure two things in that function: one is a bucket notification configuration on the bucket (saying tell Lambda about changes), the other is a Lambda Permission on the function (saying allow invocations from S3).
Resources:
JoinLambdaToBucket:
Type: Custom::JoinLambdaToExistingBucket
Properties:
ServiceToken: !GetAtt LambdaToBucket.Arn

My cloud formation template fails to create resource without producing any error

I have a large template for CloudFormation that has hundreds of resources. All are successfully updated, during an update, except one: an SNS alarm topic.
When deploying the stack, I get no errors, but even if the topic is non-existent the topic is never created.
I'm not expecting anyone to be able to provide me with a solution, but I would simply like to know how to troubleshoot the problem. It would be helpful to get output from the deployment, but the events are so few and really don't reflect the amount of resources being updated/created that they rarely help finding out what goes wrong.
Validation of the template is also successful, but that's almost a given since deploying also succeeds.
Regarding troubleshooting live CloudFormation stacks in general, CloudFormation just recently added support for Change Sets, which should help you preview changes and troubleshoot potential issues with updates before you attempt to apply them to your running stack.
Regarding SNS topics specifically, creating an SNS topic from scratch using the AWS::SNS::Topic resource works correctly. However, if you are using a TopicName property in your SNS resource, make sure that the name is unique across your entire AWS Account, as noted in the documentation:
Resource names must be unique across all of your active stacks. If you reuse templates to create multiple stacks, you must change or remove custom names from your template.
So reusing a constant TopicName in a stack deployed multiple times could cause the issue you're describing.
Also, if you're attempting to update existing CloudFormation-created topics with added/removed subscriptions, note the following important notice in the documentation:
Important
After you create an Amazon SNS topic, you cannot update its properties by using AWS CloudFormation. You can modify an Amazon SNS topic by using the AWS Management Console.
As a potential workaround for adding/removing subscriptions to existing SNS topics via CloudFormation, there is a cloudformation-helpers library containing a Custom::SnsSubscription resource (example) that might help.