In general, accessing & decrypting AWS SSM parameter store values requires these 3 permissions:
ssm:DescribeParameters
ssm:GetParameters
kms:Decrypt
-
Here's a real world example that only allows access to SSM parameters relating to my lambda functions (distinguished by following a common naming convention/pattern) - it works under the following circumstances:
- SecureString values are encrypted with the default AWS SSM encryption key.
All parameters use the following naming convention
a. /${app-name-or-app-namespace}/serverless/${lambda-function-name/then/whatever/else/you/want
b.${lambda-function-name}
must begin with sls-
So let's say I have an app called myCoolApp
, and a Lambda function called sls-myCoolLambdaFunction
. Perhaps I want to save database config values such as username and password.
I would have two SSM parameters created:
/myCoolApp/serverless/sls-myCoolLambdaFunction/dev/database/username
(plaintext)
/myCoolApp/serverless/sls-myCoolLambdaFunction/dev/database/password
(SecureString)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:DescribeParameters"
],
"Resource": [
"arn:aws:ssm:${region-or-wildcard}:${aws-account-id-or-wildcard}:*"
]
},
{
"Effect": "Allow",
"Action": [
"ssm:GetParameter"
],
"Resource": [
"arn:aws:ssm:${region-or-wildcard}:${aws-account-id-or-wildcard}:parameter/myCoolApp/serverless/sls-*"
]
},
{
"Effect": "Allow",
"Action": [
"kms:Decrypt"
],
"Resource": [
"arn:aws:kms:*:${aws-account-id}:key/alias/aws/ssm"
]
}
]
}
Then in my serverless.yml file, I might reference these two SSM values as function level environment variables like so
environment:
DATABASE_USERNAME: ${ssm:/myCoolApp/serverless/sls-myCoolLambdaFunction/dev/database/username}
DATABASE_PASSWORD: ${ssm:/myCoolApp/serverless/sls-myCoolLambdaFunction/dev/database/password~true}
Or, even better, if I want to be super dynamic for situations where I have different config values depending on the stage, I can set the environment variables like so
environment:
DATABASE_USERNAME: ${ssm:/myCoolApp/serverless/sls-myCoolLambdaFunction/${self:provider.stage}/database/username}
DATABASE_PASSWORD: ${ssm:/myCoolApp/serverless/sls-myCoolLambdaFunction/${self:provider.stage}/database/password~true}
With this above example, if I had two stages - dev
& prod
, perhaps I would create the following SSM parameters:
/myCoolApp/serverless/sls-myCoolLambdaFunction/dev/database/username
(plaintext)
/myCoolApp/serverless/sls-myCoolLambdaFunction/dev/database/password
(SecureString)
/myCoolApp/serverless/sls-myCoolLambdaFunction/prod/database/username
(plaintext)
/myCoolApp/serverless/sls-myCoolLambdaFunction/prod/database/password
(SecureString)