Query external resources from CloudFormation (Like terraform's data) - amazon-web-services

I'm working with a CloudFormation template which is defining a lot of parameters for static values out of the scope of the template.
For example, the template is creating some EC2, and it has parameters for each VPC subnet. If this was Terraform, I would just remove all of these parameters and use data to fetch the information.
Is it possible to do that with CloudFormation?
Notice that I'm not talking about referencing another resource created within the same template, but about a resource that already exists in the account that could have been created by different means (manual, Terraform, CloudFormation, whatever...)

No, CloudFormation does not have any native ability to look up existing resources. You can, however, achieve this using a Cloudformation macro.
A CloudFormation macro leverages a lambda function, which you can implement with whatever logic you need (e.g. using boto3) so that it returns the value you're after. You can even pass parameters to it.
Once the macro has been created, you can then consume it in your existing template.
You can find a full example on how to implement a macro, and on how to consume it, here: https://stackoverflow.com/a/70475459/3390419

Related

How to create AWS Cloudformation Stack from existing API-Gateway?

We have a very complex api-gateway api that has been constructed manually through the console. I would like to create a cloudformation template from this existing api, so it can be managed instead in code.
The "create stack from existing resources" seems to require all of the resources to be pre-defined in a template. However this is exactly the bit I'm trying to avoid. Due to the complexity of the existing api, it would take a very long time to manually work through all of the api resources to create all the definitions in a template.
Is there some way I can have CloudFormation automatically scan through the existing api resources and create the template definitions from it?
There is popular open-source tool called former2 which can generated CFN templates from existing resources.
Other then former2 there is nothing (CloudFormer is not maintained nor supported by AWS anymore). You would have to manually per-populate entire template before importing resources to CloudFormation.

CloudWatch Alarm for multiple Lambda functions in a CloudFormation stack

I am using SAM and CloudFormation to deploy multiple Lambda functions and other resources. The function names are generated by CloudFormation and have the following format:
stack-name-function-name-8H2609XXXXX with the suffix automatically generated by CloudFormation
The CloudWatch log groups automatically created for all individual Lambda functions have therefore following name format:
/aws/lambda/stack-name-function-name-8H2609XXXXX
I am trying to find a way to trigger CloudWatch Alarm for the Lambda functions in a stack. When creating a MetricFilter in CloudFormation I have to specify CloudWatch LogGroupName. With 100s of Lambdas with names generated by CloudFormation, following the basic pattern would mean creating 100s of filters that would somehow have to know the names of all functions (outputs and imports maybe but that would be really inflexible when function names change, would require constant redeploying of the "alarm" stack that I was hoping to keep filters in)
Is there a way to maybe trigger alarm for a group of log groups? I imagined using wildcard would be easy on a filter for log group name like /aws/lambda/stack-name-*. Or any other nicer approach than having to manage all the filters?

Create Resource in Bulk from Single CloudFormation Template with CodePipeline

I have to create multiple IAM users from a single cloudformation stack at once.
Since, Cloudformation doesn't support Loop. I have Created a Code Pipeline which deploys cloudformation template stored in AWS CodeCommit.
Can I use Parameter Override Feature of Code Pipeline to Create Multiple Users like giving parameter in list as:
{
"Username":["Bob","Alice","John"]
}
You're going to need an action between the CodeCommit and CloudFormation actions to generate a template that includes each IAM user resource (unless you plan to commit the expanded CloudFormation template). CodeBuild is probably your best bet to run some command that generates the CoudFormation template.
You might find CDK (https://github.com/awslabs/aws-cdk/) interesting for a use case like this. It will let you describe IAM users in a loop and then synthesize a CoudFormation temple. At the time of writing this answer it's in preview, so don't rely on it for production.
You should, but if you don't leave pre-existing ones in, I believe it will drop the previous ones. You could do a Custom resource tied to a Lambda Function, then your Lambda function could "not" drop the previous resources.

CodePipeline and CloudFormation paramters

I am using CodePipeline to deploy my SAM (lambda etc) application referencing https://docs.aws.amazon.com/lambda/latest/dg/build-pipeline.html.
The "issue" now is my CloudFormation has some parameters inside and CodePipeline requires that I set these. I could do so via parameter overrides
But is this the correct way? I actually only want it set once at the start. And I'd rather have users set it in CloudFormation and CodePipeline should follow those values.
This stack is already created, why isit that CodePipeline complains I need them set?
The input parameters are required by CloudFormation to update.
Template configuration is the recommended way to specify the input parameters. You could create a template file of input parameters for the customers to use.
Possible solution is to create custom Lambda functions which will be invoked from CodePipeline using Invoke action.
As a parameter to such Lambda you would specify CloudFormation stack name. Lambda then will load CloudFormation parameters from existing stack and create output from it (using appropriate AWS SDK). Such artifact will be used as an input to CloudFormation deployment.
Another solution is to create CodeBuild project which will do the same thing.
It's a bit complex but it seems that CodePipeline always needs full set of parameters unfortunately.

Programmatically utilize resources created with CloudFormation

I'm creating a bunch of application resources with AWS CloudFormation, and when the resources are created, CloudFormation adds a hash at the end of the name to make it unique.
i.e. If you wanted to create a Kinesis stream names MyStream, the actually name would be something like my-stack-MyStream-1F8ISNCLP0W4O.
I want to be able to programmatically access the resources without having to know the hash, without having to query AWS for my resources to match the names myself, and without manual steps. Does anybody know a convenient way to use AWS resources in your application programmatically and predictably?
Here are the less ideal options I can think of:
Set a tag on the resource (i.e. name -> MyStream) and query AWS to get the actual resource name.
Query AWS for a list of resources names and look for a partial match on the expected name.
After you create your resources, manually copy the actual names into your config file (probably the sanest of these options)
You can use the CloudFormation API to get a list of resources in your stack. This will give you a list of logical ids (i.e. the name in your CloudFormation template without the hash) and matching physical ids (with the stack name and hash). Using the AWS CLI, this will show a mapping between the two ids:
aws cloudformation describe-stack-resources
--query StackResources[].[LogicalResourceId,PhysicalResourceId]
--stack-name <my-stack>
CloudFormation APIs to do the same query are provided in all the various language SDKs provided by Amazon.
You can use this as an alternative to #1, by querying CloudFormation at runtime, or #3, by querying CloudFormation at buildtime and embedding the results in a config file. I don't see any advantage to using your own tags over simply querying the CF API. #2 will cause problems if you want two or more stacks from the same template to coexist.
I've used both the runtime and build time approaches. The build time approach lets you remove the dependency on or knowledge of CloudFormation, but needs stack specific information in your config file. I like the runtime approach to allow the same build to be deployed to multiple stacks and all it needs is the stack name to find all the related resources.