sudo soul
sudo soul

Reputation: 1682

Serverless Framework - What permissions do I need to use AWS SSM Parameter Store?

I'm opening this question because there seems to be no documentation on this, so I would like to provide the answer after much time wasted in trial and error.

As background, the Serverless framework [allows loading both plaintext & SecureString values from AWS SSM Parameter Store].1

What permissions are needed to access & load these SSM Parameter Store values when performing serverless deploy?

Upvotes: 7

Views: 8538

Answers (3)

DonMehdi
DonMehdi

Reputation: 21

In the case you are using codebuild in a ci/cd pipeline, dont forget to add the ssm authorization policies to the codebuild service role. (when we are talking about ssm we have to differenciate between secretsmanager and parametstore)

Upvotes: 0

sudo soul
sudo soul

Reputation: 1682

In general, accessing & decrypting AWS SSM parameter store values requires these 3 permissions:

  1. ssm:DescribeParameters
  2. ssm:GetParameters
  3. 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:

  1. SecureString values are encrypted with the default AWS SSM encryption key.
  2. 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:

  1. /myCoolApp/serverless/sls-myCoolLambdaFunction/dev/database/username (plaintext)

  2. /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:

  1. /myCoolApp/serverless/sls-myCoolLambdaFunction/dev/database/username (plaintext)

  2. /myCoolApp/serverless/sls-myCoolLambdaFunction/dev/database/password (SecureString)

  3. /myCoolApp/serverless/sls-myCoolLambdaFunction/prod/database/username (plaintext)

  4. /myCoolApp/serverless/sls-myCoolLambdaFunction/prod/database/password (SecureString)

Upvotes: 14

Raymond
Raymond

Reputation: 115

I suggest to use AWS SDK to get SSM parameters in code instead of saving in environment file (i.e. .env). It's more secure that way. You need to assign permission to the role you use with action=ssm:GetParameter and resource point to the parameter in the SSM Parameter store. I use serverless framework for deployment. Below is what I have in serverless.yml assumming parameter names with pattern "{stage}-myproject-*" (e.g. dev-myproject-username, qa-myproject-password):

custom:
  myStage: ${opt:stage}
provider:
  name: aws
  runtime: nodejs10.x
  stage: ${self:custom.myStage}
  region: us-east-1
  myAccountId: <aws account id>
  iamRoleStatements:
    - Effect: Allow
      Action:
        - ssm:GetParameter
      Resource: "arn:aws:ssm:${self:provider.region}:${self:provider.myAccountId}:parameter/${self:provider.stage}-myproject-*"

two useful resources are listed below: where to save credentials? wireless framework IAM doc

Upvotes: 4

Related Questions