Sensitive Information Disclosure in AWS
All stages of the AWS lifecycle can expose sensitive information. This can be from the initial planning stage to the deployment stage to the running of the application.
Vulnerable Example
An unfortunate common mistake is to hardcode credentials into IaC files. This is a bad idea as it means that anyone accessing the code can access the AWS account.
A vulnerable example is the following Terraform configuration that stores the clear-text credentials within the file.
environment {
variables = {
# Set the secrets from variables
username = "ResourceAdmin"
password = "PaXXword00"
}
}
There are many workarounds to this, such as using environment variables, but the best way to avoid this is to use a secrets manager such as AWS Secrets Manager.
Prevention
IaC technologies allow storing credentials more securely by passing variables at runtime or leveraging dedicated AWS services. Read below some examples using Terraform.
Environment Variables
In Terraform, we can use undefined variables, which allows us to pass values to the deployment at the time of running:
environment {
variables = {
# Set the secrets from variables
username = var.username
password = var.password
}
}
Then when we run the Terraform code, we can pass the values in as variables from the command line; that way, the credentials are not stored in the Terraform code.
AWS KMS Secrets
If we want to store the credentials locally more securely, we can use AWS KMS to encrypt the credentials. This allows us to store the credentials securely but still have them available to Terraform.
We encrypt the credentials using the AWS CLI:
aws kms encrypt \
--key-id $(aws kms create-key --description "KMS key for the credentials of the lambda" --query 'KeyMetadata.KeyId' --output text) \
--plaintext fileb://.credentials.hidden \
--output text \
--query CiphertextBlob \
> credentials.encrypted
Then we can use the encrypted credentials in the Terraform code:
environment {
variables = {
# Set the secrets from variables
username = local.credentials.username
password = local.credentials.password
}
}
AWS Secrets Manager
We can add secrets such as usernames and passwords to AWS Secrets Manager and then use the secrets in the Terraform code:
data "aws_secretsmanager_secret_version" "credentials" {
secret_id = "secret_name"
}
Once again, we can then load this into locals and use it in the Terraform code:
environment {
variables = {
# Set the secrets from variables
username = local.credentials.username
password = local.credentials.password
}
}