CloudFormation Parameter Dynamic Regex - regex

I have a a CloudFormation template with 2 parameters. I want to set an AllowedPattern value for the 2nd parameter such that its regex is dynamically generated based on the value for the first parameter. Something like this:
CloudFormation Parameters
WebsiteDomain:
Type: String
EmailAddress:
Type: String
AllowedPattern: !Sub '.*#${WebsiteDomain}'
Allowed Input
WebsiteDomain: google.com
EmailAddress: test#google.com
Disallowed Input
WebsiteDomain: google.com
EmailAddress: test#yahoo.com
Is there any way to accomplish this?

You would have to use CloudFormation macro for pre-processing of your template, before actuall deployment. Ohterwise, you can't do what you wan't.

Cloudformation templates are not so dynamic, but you could write a script using the AWS CDK which would allow you to write logic to check this yourself and then either immediately deploy it to the AWS environment or synthesize a CloudFormation template from the defined resources in your CDK app.

Unfortunately, No. CF Templates are not that dynamic.

Related

Can use environment variables with the sub intrinsic function?

I am using the sub function to define a resource within an aws IAM service.
Resource:
- !Sub 'arn:aws:s3:::example-${TEST1}-${AWS::REGION}-test'
${TEST1}: it is an environment variable that I have in my java project.
${AWS::REGION}: pseudo parameter
I want to know if !sub is able to read the environment variable and if it can't, is there any way I can do it even if it's not with this function
No, you cannot reference environment variables within cloudformation.
You'll have to wrap the cloudformation deployment with a script that parses the environment variables and feeds them in as parameters, which can then be referenced in the template.
Make the environment variable a CloudFormation Parameter and set the value. Then !Sub will work as expected. You can create a parameter file if you need to massage the values with sed or jq.

CloudFormation create change set fails with 'Template parameters modified by transform'

I'm trying to create a change set for my stack, but it keeps failing with status reason Template parameters modified by transform.
I have a CodeBuild project which runs the below and then passes the template on if it's valid:
aws cloudformation validate-template --template-body file://<TEMPLATE_FILE>
I am using the CodeDeployBlueGreen transform to allow Blue/Green deployments with ECS, as per this documentation.
Transform:
- 'AWS::CodeDeployBlueGreen'
My template does not contain any input parameters, and I removed any references to resolve::ssm....
I'm at a bit of a loss as to what's causing this issue, and I cannot find any documentation which points me in the right direction.
The template is as follows:
Template removed after answer posted for security.
I hope this saves someone some headaches one day.
This is currently a known issue with CloudFormation in which you need to provide the VPC and Subnets as parameters to the stack when using AWS::CodeDeployBlueGreen Transform.
Parameters:
VPC:
Type: AWS::EC2::VPC::Id
Subnet1:
Type: AWS::EC2::Subnet::Id
Subnet2:
Type: AWS::EC2::Subnet::Id
Probably unrelated, but CloudFormation Linter in VSCode calls out a missing required property:
[cfn-lint] E3003: Property GroupDescription missing at Resources/NeptuneSG/Properties
AWS::EC2::SecurityGroup.GroupDescription

Create CloudFormation stack without resources

I am using Terraform for most of my infrastructure, but at the same time I'm using the serverless framework to define some Lambda functions. Serverless uses CloudFormation under the hood where I need access to some ARNs for resources created by Terraform.
My idea was to create a CloudFormation stack in Terraform and export all of the value that I need, but it complains that it cannot create a stack without any resources. I don't want to define any resources in CloudFormation, only the outputs, so I though maybe there is a way to define some dummy resource, but I couldn't find any.
Is there a way to work around this issue? If not, I'm also open to other suggestions for getting parameters passed from Terraform to CloudFormation.
You can use AWS::CloudFormation::WaitConditionHandle for this. Example:
Resources:
NullResource:
Type: AWS::CloudFormation::WaitConditionHandle
The Resource section is required, but you can create non-resource type of resource.
For example, minimalist template with only a non-resource would be:
Conditions:
Never:
!Equals [ "A", "B" ]
Resources:
NonResource:
Type: Custom::NonResource
Condition: Never
Outputs:
MyOutput:
Value: some-value
You can use create AWS SSM parameter using Terraform and reference them in your serverless framework. That would do the job easily.
https://www.serverless.com/blog/definitive-guide-terraform-serverless/

Can you have an optional parameter in CloudFormation for AWS Specific Parameters?

How do you include an optional list of AWS specific resources in a CloudFormation template?
For example, an optional list of existing EBS volumes to attach to an EC2 instance?
The parameter would be defined as usual:
AdditionalExistingVolumes:
Type: List<AWS::EC2::Volume::Id>
Description: Existing AWS volumes to attach to the instance.
However when it comes to use it, you only want to include the list if the user provided some values.
With a string parameter you would use a Condition along with the function !If to optional include AWS::NoValue.
How do you do this with a list of AWS types?

Access AWS auto-generated URL for deployed resources

Is there a way to access auto-generated URLs for deployed resources before the deployment is finished? (like db host, lambda function URL, etc.)
I can access them after the deployment is finished, but sometimes I need to access them while building my stack. (E.g. use them in other resources).
What is a good solution to handle this use-case? I was thinking about outputting them into the SSM parameter store from CloudFormation template, but I'm not sure if this is even possible.
Thanks for any suggestion or guidance!
If "use them in other resources" means another serverless service or another CloudFormation stack, then use CloudFormation Outputs to export the values you are interested in. Then use CloudFormation ImportValue function to reference that value in another stack.
See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html and https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html
Within Serverless Framework, you can access a CloudFormation Output value using https://serverless.com/framework/docs/providers/aws/guide/variables/#reference-cloudformation-outputs
If you want to use the autogenerated value within the same stack, then just use CloudFormation GetAtt function. See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html.
For example, I have a CloudFormation stack that outputs the URL for an ElasticSearch cluster.
Resources:
Search:
Type: AWS::Elasticsearch::Domain
Properties: <redacted>
Outputs:
SearchUrl:
Value: !GetAtt Search.DomainEndpoint
Export:
Name: myapp:search-url
Assuming that the CloudFormation stack name is "mystack", then in my Serverless service, I can reference the SearchUrl by:
custom:
searchUrl: ${cf:mystack.SearchUrl}
To add to bwinant's answer, ${cf:<stack name>.<output name>} does not work if you want to reference a variable in another stack which is located in another region. There is a plugin to achieve this called serverless-plugin-cloudformation-cross-region-variables. You can use it like so
plugins:
- serverless-plugin-cloudformation-cross-region-variables
custom:
myVariable: ${cfcr:ca-central-1:my-other-stack:MyVariable}