

Terraform module to generate secret values and store in SSM Parameter Store
source link: https://advancedweb.hu/terraform-module-to-generate-secret-values-and-store-in-ssm-parameter-store/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Handling secrets in the cloud
The recommended way to handle secrets in AWS is to put them either into SSM Parameter Store or into Secrets Manager. Then whatever needs to use these values, give them IAM permissions to read the value.
For example, a Lambda function might need to connect to a MongoDB database. Since it is outside AWS, IAM permissions won’t work, instead, a password is needed. How should the Lambda get this password? Put it into Parameter Store, then use IAM permissions to give the Lambda’s execution role access to the parameter.
This is a security best practice as the value is stored in a place that is protected by IAM permissions. Anybody (or anything) who needs access can be granted via an explicit permission and since every part of the system only references the value it won’t show up accidentally in state files or environment variables.
Generated secrets
The above approach is good for secrets that are generated outside the deployed stack, such as a token to access a third-party system, a database password, or an encryption key that needs to be usable by other systems.
But what about secrets that are used only in this stack?
For example, IVS private channels require a public-private key pair to work. The public part is added to IVS while the private needs to be accessible to the backend to be able to sign tokens for authorized viewers.
Another example is CloudFront Signed URLs. The public key is added to the distribution while the private key is used by the backend for the signature.
Notice that these secrets are different than the MongoDB password we discussed earlier. The exact value of the IVS key pair does not matter, it is only needed to be usable inside the stack. It does not matter if it changes as long as both the IVS and the backend part is changed as well. There is no need for these keys to be stable or usable outside the stack.
Because of this, manually generating these keys and adding them to SSM Parameter Store before deploying the stack and delete them after seems like an overkill. After all, how an IVS private channel where the backend can control who can view the video different than let’s say a DynamoDB table that the backend can read data from? The only difference is that for IVS a secret must be generated while DynamoDB access is controlled by IAM. An IVS key pair should be part of the stack, generated when all the other resources are deployed and destroyed when the stack is cleaned up.
Solution
The solution is to generate these values dynamically but fully in the cloud. For this, we need a Lambda function that can add a parameter to the SSM Parameter Store and will be called during the deployment process.
Deploying and calling a Lambda during deployment is supported by both CloudFormation and Terraform. In CloudFormation it is based on custom resources which is wrapped with a nicer resource type in the CDK called AwsCustomResource. In Terraform, there is an aws_lambda_invocation resource type. In this article, we’ll focus on a solution based on Terraform.
Creating the function is no different than creating any other functions: it needs the code in an archive file, an execution role with the required permissions attached, and then the function itself:
resource "aws_lambda_function" "generate_value" {
function_name = "ssm-generated-value-module-${random_id.id.hex}"
filename = data.archive_file.generate_value.output_path
source_code_hash = data.archive_file.generate_value.output_base64sha256
timeout = 30
handler = "index.handler"
runtime = "nodejs18.x"
environment {
variables = {
SSM_PARAMETER: var.parameter_name,
}
}
role = aws_iam_role.generate_value_exec.arn
}
To make Terraform call this function during the different stages of the deployment, the aws_lambda_invocation
resource is used:
resource "aws_lambda_invocation" "generate_value" {
function_name = aws_lambda_function.generate_value.function_name
input = "{}"
lifecycle_scope = "CRUD"
}
The CRUD
lifecycle scope means it will be called when the resource is created, updated, and deleted, allowing it to reliably handle the lifecycle of the SSM parameter.
We write articles like this regularly. Join our mailing list and let's keep in touch.
Terraform module
What we discussed above is the resources that are needed to manage a generated secret in SSM Parameter Store with a custom Lambda function. But this also yields a reusable structure: a value is generated and stored as a parameter then it is deleted when the stack is deleted. The only configurable parts are:
- how to generate the value
- how to delete the value
Abstracting out all the other parts yields a nice structure and it is available as a Terraform module: ssm-generated-value.
We’ll see how to use the module to generate key pair for CloudFront and to generate IAM user credentials.
Recommend
-
14
Parse parameter default values using PowerShell – Part 3 In part 1 and
-
7
Parse parameter default values using PowerShell – Part 2 In my last post, I showed how to use TSqlParser
-
23
Optional parameters, default parameter values and method overloading yourbasic.org/golang
-
6
Parse parameter default values using PowerShell – Part 1 If you have ever tried to determine the default values for stored procedure parameters, you probably have marks on your forehead from hi...
-
27
Signed URLs in AWS Recently, AWS added a powerful and well-needed function to CloudFront: Trusted Key Groups. They allow using CloudFront sig...
-
9
Just published: "Rejecting or Accepting Parameter Values in Bayesian Estimation" Just published: "Rejecting or Accepting Parameter Values in Bayesian Estimation" in the journal, Advances in Methods and Practices in Psychologic...
-
10
In this post, I will walk you through the challenges I’ve faced when adopting the object type in my Terraform 0.12 modules and the solutions I came up with to work around the caveats. As an example, I will use the google_storage_bucket resource, a...
-
11
Code is available on GitHub Storing secrets in AWS For IAM credentials, AWS provides a secret-less way t...
-
19
Code is available on GitHub Sensitive inputs While IAM Roles provide a great way to remove secrets from the arc...
-
8
IAM identities Generally, it’s a bad idea to use IAM users in cases when roles are also an option. This is because roles provide a secret-less way for systems to gain permissions to AWS resources, while a user’s Secret...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK