Search code examples
aws-lambdaserverless-framework

Serverless Framework - environment variables from file and manual


I have Serverless Framework function for AWS Lambda. I have secrets in AWS Secrets Manager (SSM) Parameter Store and other environment variables in local .yml files, for separate deployments (dev, stg, prod).

How can I use environment variables from both file and SSM?

Only secrets work:

functions:
  kinesisEvents:
    handler: kinesis_events_processing.lambda_handler
    name: kinesis-events-${self:provider.stage}
    package: {}
    maximumRetryAttempts: 2
    events:
      - stream:
          type: kinesis
          ... # omitted a few things
    environment:
      DB_PASSWORD: ${ssm:/${self:provider.stage}/db/db_password}
      API_KEY: ${ssm:/${self:provider.stage}/api/internal_api_key}

And only file also works:

functions:
  kinesisEvents:
    ... # as above
    environment:
      ${file(${self:provider.stage}.yml):}

But how can I combine those, so I have all those variables set as env vars in final deployment? I tried this, but it does not work and throws error during deploy:

functions:
  kinesisEvents:
    ... # as above
    environment:
      DB_PASSWORD: ${ssm:/${self:provider.stage}/db/db_password}
      API_KEY: ${ssm:/${self:provider.stage}/api/internal_api_key}
      ${file(${self:provider.stage}.yml):}

Solution

  • I found answers here, here and here. Basically, Serverless Framework has no particular support for this feature. However, it supports extended YAML syntax, which has anchor and dictionary merging capabilities.

    So first I unpack the env vars from YAML config file, at the top of the file, and anchor it with &env_vars (like a variable for referencing, but in YAML):

    env_vars: &env_vars
      ${file(${self:provider.stage}.yml):}
    
    functions:
      ...
    

    And then I use it, unpacking this dictionary:

        environment:
          <<: *env_vars
          DB_PASSWORD: ${ssm:/${self:provider.stage}/db/db_password}
          API_KEY: ${ssm:/${self:provider.stage}/api/internal_api_key}