Skip to main content

Environment Configuration & Secrets

Most Rails applications require over a dozen environment variables to configure itself along with other popular gems used. Most notable is ActiveRecord's DATABASE_URL. There are numerous ways to configure environment variables ranging from "quick and dirty" by adding secrets to your git repo (⚠️) all the way to a strict "separation of config" from code using countless methods to achieve a proper Twelve-Factor application. We want to cover a few topics that may help you pick and choose what works best for you.

Configuration

You can add simple configurations to your all of your function's environment using SAM's global section. Configurations like these are ones that you feel safe comitting to your git repo.

template.yaml
Globals:
Environment:
Variables:
SOME_SERVICE_URL: https://prod.some-service.com/api

If you deploy to multiple environments, you can even have these be dynamic by leveraging CloudFormation's mappings. Here is an example that builds on our RailsEnv parameter.

template.yaml
Mappings:
SomeService:
staging:
Url: https://straging.some-service.com/api
production:
Url: https://prod.some-service.com/api
# ...
Globals:
Environment:
Variables:
SOME_SERVICE_URL: !FindInMap [SomeService, !Ref RailsEnv, Url]

Secrets with Crypteia

The Crypteia package is Rust Lambda Extension for any Runtime/Container to preload SSM Parameters as secure environment variables. It takes advantages of LD_PRELOAD to seamlessly fetch values from SSM when a process starts and then injects them as natively accesible Ruby ENV variables. Our Quick Start guide's cookiecutter includes Crypteia already for you via a Docker COPY command into the Lambda Extension /opt directory.

Dockerfile
FROM ruby:3.1-bullseye
COPY --from=ghcr.io/customink/crypteia-extension-debian:latest /opt /opt

Usage is simply done by adding variables to your SAM template and accessing the values fetched from SSM like any other environment variable. Please read the Crypteia's documentation for full details.

Globals:
Environment:
Variables:
SECRET: x-crypteia-ssm:/myapp/SECRET
ENV['SECRET'] # 1A2B3C4D5E6F

About SECRET_KEY_BASE

Our cookiecutter project disabled Rails encrypted credentials in favor of a more simple SECRET_KEY_BASE setting. The starter project places a temporary value for this environment variable in the config/initializers/secret_key_base.rb file. Please remove the ENV['SECRET_KEY_BASE'] = '0123...' line and use Crypteia as described above.

Modern IAM Role Usage

If your application uses other AWS resources like EventBridge or S3, you may be using environment variables like AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. Avoid this pattern. Instead, please add explicit IAM policies within your template.yaml file. They will be attached to your Lambda's Execution Role and inherently give your Lambda the needed permissions. AWS is constantly making IAM permissions more approachable. There are two high level interfaces within SAM to connect your application to cloud resources. Newest first:

  • AWS SAM Connectors: Are an AWS SAM abstract resource type, identified as AWS::Serverless::Connector, that can be defined in your AWS SAM templates to grant Read and Write access of data and events from a supported AWS resource to another.
  • AWS SAM Policy Templates: Are pre-defined sets of permissions that you can add to your AWS SAM templates to manage access and permissions between your AWS Lambda functions, AWS Step Functions state machines and the resources they interact with.

If needed, you can use the lower level Policies property of your AWS::Serverless::Function resource to attach any inline policies to your application's IAM Role.