Add new environment variables to Lambda using Cloud Formation Template - amazon-web-services

I have a nested Cloud Formation Template (multiple templates within a root template )to create a complete web application.
Lambda is created in the first template and few environment variables are added to it.
The later part of the templates also produces some values that has to be added as environment variables.
Is there a way to attach these environment variables to the existing lambda function?

I don't think so, but there are a few options. If you could change the stack dependency order, you could build the stack creating the values depended upon first. If you cannot, you can store your environment variables in SSM Parameter Store as mentioned in this knowledge center article.
So you set the environment variable to a path where the value can be expected, then when creating the stack that knows the value, you store it at that path. When the lambda runs, you just do get parameter.

Related

Lambda ValueFrom Environment Variable Like in Task Definition

Is there a way to have a ValueFrom feature in Lambda's environment variable similar to what we have in Task Definition?
How it works.
We have a kv pair in parameter store /dev/db/host=localhost.
In the container definition inside the ECS task definition, we add a new environment variable DB_HOST which has a ValueFrom /dev/db/host. When a new instance of the container is run it will have the value localhost from the parameter store.
I tried on Lambda but it seems like this feature is not available. Is there another way to do this? I wonder if there is a request for this as well.
PS: I'm aware that it can be done via TerraForm or CloudFormation but that will only evaluate and copy the values from parameter store to Lambda environment variables when the infrastructure is built. The problem is some of the values are secured like DB password, thus it cannot be simply copied as it will get exposed.

I need a strategy for handling optional SSM Parameter Store parameters in CDK

In my stack definition I pull in a number of parameters from SSM Parameter Store...
const p1 = ssm.StringParameter.fromStringParameterAttributes( ... )
const p2 = ssm.StringParameter.fromStringParameterAttributes( ... )
I then pass them along to the relevant lambdas as environment vars...
environment: {
PARAM_ONE: p1.stringValue
PARAM_TWO: p2.stringValue
}
However I don't want all of those parameters to be mandatory. I would like the ones that exist to be passed in as env vars, and the ones that don't to just remain undefined as my app has defaults for them anyway. However, trying to inspect the value of p1.stringValue just gives me a Token, not a value, so I can't do any logic based on it's presence or absence: https://docs.aws.amazon.com/cdk/latest/guide/tokens.html
If I ask for the parameter and it is not defined in SSM Parameter Store I then get an error that I can't catch or ignore when it tries to build the changeset and the deployment fails...
MyApp: creating CloudFormation changeset...
❌ MyAppStack failed: Error [ValidationError]: Unable to fetch parameters [/myapp/param1,/myapp/param2] from parameter store for this account.
So how can I deal with SSM parameters which may or may not exist at deploy time?
I assume you are only grabbing the manager in your import, not the actual values inside your secrets. If this is the case, then your best bet is to leverage the SDK to do this for you - a simple call using the SDK (which will be run during the synth stage of a cdk deploy or cdk synth) to see if said SMM fields/groups exist. If they do, go ahead and import them.
I do something very similar with Layers - the from methods for layers require the version number - that may change at any time. So i have a small function that gets the latest version number of a given layer using the SDK and i can then use that to import the layer definition into my stack.
If you are trying to get the actual secret inside the secret manager parameter ... that is better suited to outside the CDK for most scenarios - done in the exact location you need the secrets so you dont end up with secret value in plain text somewhere.

Set global parameters in aws cloudformation

I'm building a complex application in AWS using Cloudformation.
My setup is the following: I'm going to use yaml files to define the stacks and corresponding json files which contain the stack parameters. Anyway there are parameters which are the same in multiple json files and I'd like to define them globally in one file/stack instead of having to update them in multiple files everytime they change.
What is the recommended way to set such global parameters using cloudformation?
Help would be highly appreciated.
You could possibly create one stack with command parameters, end export their values from this stack. Then, in other stack, the parameter values would be accessed using Fn::ImportValue.
An alternative could be to store common parameters in SSM Parameter Store, and then use dynamic references in your template to access them.

Global environment variables for AWS CloudFormation

Is there a way to have global environment variables in a AWS CloudFormation yaml file for Lambdas?
Currently we are using the SSM Parameter Store for global variables, but we don't want to use that anymore.
I looking forward to have something like this:
Environment:
Variables:
variable1: xxx // local variables
variable2: xxx
...
${file(./globalvariables.yml)} // global variables
Or even better: every lambda is including the global environment variables as default without explicitly calling it.
Is this possible? Or what approach would you suggest? Thanks in advance!
Sadly I'm unaware of having predefined defaults for environment variables to be set through CloudFormation for Lambdas however - One possible option is instead of using env variables in CloudFormation add a lambda layer with all the config and pull the values from there.
Benefits of this are that if a value changes you only have to update your layer once then update lambdas to use new layer which could be a single parameter instead of manually updating every single one.
Docs here: https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html
Another option would be to use AWS Secrets Manager Or SSM Parameter Store as ServerMonkey suggested.

Add Resources to existing CloudFormation stack

I have a CloudFormation master stack. I want to write a tool that allows me to add Lambda functions to the master stack using Boto3.
In order to add the function to the stack I need to be able to
Get Outputs from the master stack to use in the function's template.
Add the Function to the master stack.
I have only been able to get this to work with:
Build, zip, and upload the function to S3
Add the function's template to the master stack's templates. (requires editing the master stack's files)
Deploy the master stack.
I would like to be able to create the function without editing the master stack's files.
(i.e. boto3.get_stack_id -> boto3.add_resource_to_stack_by_stack_id)
Is this possible? If so, how do I do it?
No that is not possible. When updating a stack, you always have to provide a URL for the new stack template, or provide the full template body as a string, or use the previous template.
Source: https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_UpdateStack.html
There is no API call that allows you to directly add a resource to a stack.