Hey.
I'm a bit confused on how to configure environment variables in Lambda. My attempt was basically to deploy my stack using dotnet lambda deploy-serverless
, which worked great. Then I went to the Lambda function within the AWS Management Console, and I manually configured my secrets, such as the DB password, which again worked great.
Now, the next time I deployed my Lambda using dotnet lambda deploy-serverless
it removed those environment variables, so then I tried dotnet lambda deploy-function ...
and the same thing happened.
What is the correct way to set secret environment variables? I would rather not store any secrets in my git repo, but then how would I deploy them, if the above doesn't work?
Thanks.
Hi, I have done using template parameters and reference in environment variables in template, i.e.
{
"AWSTemplateFormatVersion": "2010-09-09",
"Transform": "AWS::Serverless-2016-10-31",
"Parameters": {
"CustomersDB": {
"Description": "CustomersDB",
"Type": "String"
}
},
"Resources": {
"Function": {
"Type": "AWS::Serverless::Function",
"Properties": {
"Handler": "LambdaEntryPoint::FunctionHandlerAsync",
"Runtime": "dotnetcore1.0",
"CodeUri": "",
"MemorySize": 256,
"Timeout": 20,
"Role": null,
"Policies": [
"AWSLambdaFullAccess"
],
"Environment": {
"Variables": {
"CUSTOMER_DB": {
"Ref": "CustomersDB"
}
}
},
"Events": {
"PutResource": {
"Type": "Api",
"Properties": {
"Path": "/{proxy+}",
"Method": "ANY"
}
}
}
}
}
}
}
@christianavila do you specify the CustomersDB in the CI? Or can you do that once in the Management Console?
When deploy the function, you can pass the parameters as arguments
$ dotnet lambda help deploy-serverless
Command to deploy an AWS Serverless application
dotnet lambda deploy-serverless [arguments] [options]
-tp | --template-parameters CloudFormation template parameters. Format is <key1>=<value1>;<key2>=<value2>
Or after deploy, can management in console
@ChristianAvila I'm afraid this solution doesn't help me, because the next time I deploy, the deployment will override the environment variables with whatever is in the CloudFormation template (assuming I change the environment variables in the Management Console).
I don't want to store secrets in my template. However I could probably pass the parameters like you explained with a CI.
Is CodeBuild good enough for the job? Any alternative solutions? Anyone? :)
@raRaRa I recommend you use EC2 SSM Parameter Store to securely manage your key/value pair configurations. It supports value encryption with AWS KMS Key, defined as type SecureString
. KMS and parameter store key/value (except SecureString which can be created via AWS console) objects can be provisioned via CloudFormation and then referenced within your C# lambda code.
CodeBuild also supports EC2 SSM Paramater Store (including SecureString) natively allowing you to refer to a parameter in a project buildspec.yml
file under the parameter-store
section. The variable can then be used in the buildspec.yml
to override the dotnet lambda
--template-parameters key1=value1
or other build time scripts.
We use a combination of the lambda environment variables and SSM Parameter variables. Instead of passing in the defined value in the environment variable, we pass in a reference to the SSM parameter name e.g. \dev\ConnectionString
.
This way we can:
1) change the value in a centralized location via SSM parameter store;
2) during an emergency/testing/debugging change the environment value in the AWS Lambda console to reference a different SSM key all together (e.g. \temp1\ConnectionString
) ; and
3) programatically inject parameter store names as environment variables during CICD deployment. For instance use CodeBuild to refer to a parameter store that includes an environment name. Inject variables as \staging\ConnectionString
or \testing\ConnectionString
depending on if we are building for Staging or Testing.
References for you to consider:
BurningMonk: You should use SSM Parameter Store over Lambda env variables
https://hackernoon.com/you-should-use-ssm-parameter-store-over-lambda-env-variables-5197fc6ea45b
Organize Parameters by Hierarchy, Tags, or Amazon CloudWatch Events with Amazon EC2 Systems Manager Parameter Store
https://aws.amazon.com/blogs/mt/organize-parameters-by-hierarchy-tags-or-amazon-cloudwatch-events-with-amazon-ec2-systems-manager-parameter-store/
AWS SDK For .NET REFERENCE: check out the GetParameterAsync
and PutParameterSync
https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/SSM/TSSMClient.html
Cheers!
Panod
Thank you for the quick and detailed answer @panodk. Much appreciated! 鉂わ笍
No problem - happy to save you and others some time. :)
I ended up using what @panodk described above. But here's a bit more detail:
AWSSDK.SimpleSystemsManagement
NuGet package in order to use AmazonSimpleSystemsManagementClient
.AWS_ACCESS_KEY_ID
, AWS_SECRET_ACCESS_KEY
and AWS_SESSION_TOKEN
environment variables within your Lambda to authenticate the AmazonSimpleSystemsManagementClient
client. Just make sure that the role for the Lambda has the proper access to read from Amazon SSM. I simply gave my Lambda access to AmazonSSMReadOnlyAccess
.GetParametersAsync
to get many parameters at once.Closing as it looks like the question was answered. You can pass environment variables as part of the serverless template and also parameterize the template to pass them in as part of deployment. Using SSM is also a great option to use.
Most helpful comment
@raRaRa I recommend you use EC2 SSM Parameter Store to securely manage your key/value pair configurations. It supports value encryption with AWS KMS Key, defined as type
SecureString
. KMS and parameter store key/value (except SecureString which can be created via AWS console) objects can be provisioned via CloudFormation and then referenced within your C# lambda code.CodeBuild also supports EC2 SSM Paramater Store (including SecureString) natively allowing you to refer to a parameter in a project
buildspec.yml
file under theparameter-store
section. The variable can then be used in thebuildspec.yml
to override thedotnet lambda
--template-parameters key1=value1
or other build time scripts.We use a combination of the lambda environment variables and SSM Parameter variables. Instead of passing in the defined value in the environment variable, we pass in a reference to the SSM parameter name e.g.
\dev\ConnectionString
.This way we can:
1) change the value in a centralized location via SSM parameter store;
2) during an emergency/testing/debugging change the environment value in the AWS Lambda console to reference a different SSM key all together (e.g.
\temp1\ConnectionString
) ; and3) programatically inject parameter store names as environment variables during CICD deployment. For instance use CodeBuild to refer to a parameter store that includes an environment name. Inject variables as
\staging\ConnectionString
or\testing\ConnectionString
depending on if we are building for Staging or Testing.References for you to consider:
BurningMonk: You should use SSM Parameter Store over Lambda env variables
https://hackernoon.com/you-should-use-ssm-parameter-store-over-lambda-env-variables-5197fc6ea45b
Organize Parameters by Hierarchy, Tags, or Amazon CloudWatch Events with Amazon EC2 Systems Manager Parameter Store
https://aws.amazon.com/blogs/mt/organize-parameters-by-hierarchy-tags-or-amazon-cloudwatch-events-with-amazon-ec2-systems-manager-parameter-store/
AWS SDK For .NET REFERENCE: check out the
GetParameterAsync
andPutParameterSync
https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/SSM/TSSMClient.html
Cheers!
Panod