Skip to content

AWS Secrets Manager Plugin

Our AWS plugin enables secure loading of secrets from AWS Secrets Manager (SM) and from AWS Systems Manager Parameter Store (SSM) using declarative instructions within your .env files.

The plugin automatically integrates with AWS authentication, including IAM roles for AWS-hosted applications, AWS CLI credentials for local development, and explicit credentials for non-AWS environments.

  • Zero-config authentication - Automatically uses AWS credentials from your environment
  • IAM role support - No credentials needed for AWS-hosted apps (EC2, ECS, Lambda, etc.)
  • AWS CLI authentication - Works seamlessly with aws configure for local development
  • Auto-infer secret/parameter names from environment variable names
  • JSON key extraction from secrets/parameters using # syntax or named key parameter
  • Name prefixing with namePrefix option for organized secret management
  • Support for named AWS profiles
  • Support for explicit credentials
  • Support for temporary credentials with session tokens

In a JS/TS project, you may install the @varlock/aws-secrets-plugin package as a normal dependency. Otherwise you can just load it directly from your .env.schema file, as long as you add a version specifier. See the plugins guide for more instructions on installing plugins.

.env.schema
# 1. Load the plugin
# @plugin(@varlock/aws-secrets-plugin)
#
# 2. Initialize the plugin - see below for more details on options
# @initAws(region=us-east-1)
# ---

The plugin tries authentication methods in this priority order:

  1. Explicit credentials - If accessKeyId and secretAccessKey are provided
  2. Named profile - If profile is specified, uses credentials from ~/.aws/credentials
  3. Default AWS credential chain - Environment variables → ~/.aws/credentials → IAM roles

For most use cases, you only need to provide the AWS region:

.env.schema
# @plugin(@varlock/aws-secrets-plugin)
# @initAws(region=us-east-1)
# ---

How this works:

  • Local development: Run aws configure → automatically uses AWS CLI credentials
  • AWS-hosted apps (EC2, ECS, Lambda, Fargate): Attach an IAM role → automatically authenticates (no secrets needed!)
  • Works everywhere with zero configuration beyond the region!

Explicit credentials (For non-AWS environments)

Section titled “Explicit credentials (For non-AWS environments)”

If you’re deploying outside of AWS (e.g., Azure, GCP, on-premises), wire up IAM credentials:

  1. Create an IAM user with the necessary permissions (see AWS Setup section below)

  2. Wire up the credentials in your config. Add config items for the access key and secret key, and reference them when initializing the plugin.

    .env.schema
    # @plugin(@varlock/aws-secrets-plugin)
    # @initAws(
    # region=us-east-1,
    # accessKeyId=$AWS_ACCESS_KEY_ID,
    # secretAccessKey=$AWS_SECRET_ACCESS_KEY
    # )
    # ---
    # @type=awsAccessKey
    AWS_ACCESS_KEY_ID=
    # @type=awsSecretKey @sensitive
    AWS_SECRET_ACCESS_KEY=
  3. Set your credentials in deployed environments. Use your platform’s env var management UI to securely inject these values.

Use a specific profile from your ~/.aws/credentials file:

.env.schema
# @plugin(@varlock/aws-secrets-plugin)
# @initAws(region=us-east-1, profile=production)
# ---

You can run aws configure --profile production to create additional profiles, or manually edit ~/.aws/credentials:

[default]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
[production]
aws_access_key_id = AKIAI44QH8DHBEXAMPLE
aws_secret_access_key = je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY

If you need to connect to multiple regions or use different authentication, register multiple named instances:

.env.schema
# @initAws(id=us, region=us-east-1)
# @initAws(id=eu, region=eu-west-1, profile=eu-prod)
# ---
US_DATABASE_URL=awsSecret(us, "db-connection")
EU_DATABASE_URL=awsSecret(eu, "db-connection")

Once the plugin is installed and initialized, you can start adding config items that load values using the awsSecret() and awsParam() resolver functions.

The awsSecret() function fetches secrets from AWS Secrets Manager.

.env.schema
# Auto-infer secret names (DATABASE_URL -> "DATABASE_URL")
DATABASE_URL=awsSecret()
API_KEY=awsSecret()
# Explicit secret names
STRIPE_KEY=awsSecret("payments/stripe-secret-key")

The awsParam() function fetches parameters from Parameter Store.

.env.schema
# Parameters from Parameter Store
APP_CONFIG=awsParam("/prod/app/config")
FEATURE_FLAGS=awsParam("/prod/features")
# Auto-infer parameter names too
DATABASE_HOST=awsParam()

If your secrets or parameters contain JSON, you can extract specific keys:

.env.schema
# If "database-creds" contains: {"host": "db.example.com", "password": "secret"}
# Using # syntax (shorthand)
DB_HOST=awsSecret("database-creds#host")
DB_PASSWORD=awsSecret("database-creds#password")
# Or use named "key" parameter
DB_PORT=awsSecret("database-creds", key="port")

Use namePrefix to automatically prefix all secret/parameter names for better organization:

.env.schema
# @initAws(region=us-east-1, namePrefix="prod/api/")
# ---
# Fetches "prod/api/DATABASE_URL"
DATABASE_URL=awsSecret()
# Fetches "prod/api/stripe-key"
STRIPE_KEY=awsSecret("stripe-key")

You can even use dynamic prefixes:

.env.schema
# @initAws(region=us-east-1, namePrefix="${ENV}/")
# ---
# In prod: fetches "prod/DATABASE_URL"
# In dev: fetches "dev/DATABASE_URL"
DATABASE_URL=awsSecret()

Your IAM user or role needs specific permissions to access secrets and parameters.

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["secretsmanager:GetSecretValue"],
"Resource": "arn:aws:secretsmanager:*:*:secret:*"
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["ssm:GetParameter"],
"Resource": "arn:aws:ssm:*:*:parameter/*"
}
]
}
Section titled “IAM roles for AWS-hosted apps (Recommended)”

IAM roles are the AWS-native way to authenticate - no credentials needed!

  1. Create an IAM role with the necessary permissions and trust policy for your service (EC2, ECS, or Lambda)

  2. Attach the role to your application

    • EC2: Create an instance profile and attach it to your instance
    • ECS: Set the taskRoleArn in your task definition
    • Lambda: Set the execution role in your function configuration
  3. That’s it! Your app will automatically authenticate using the IAM role.

See the AWS documentation for detailed instructions on creating and attaching IAM roles.

  1. Create an IAM user

    Terminal window
    aws iam create-user --user-name varlock-secrets-reader
  2. Attach the permissions policy

    Terminal window
    aws iam put-user-policy \
    --user-name varlock-secrets-reader \
    --policy-name secrets-access \
    --policy-document file://policy.json
  3. Create access credentials

    Terminal window
    aws iam create-access-key --user-name varlock-secrets-reader

    Save the AccessKeyId and SecretAccessKey from the output - you’ll need them for your deployments.

  1. Run aws configure

    Terminal window
    aws configure
    # AWS Access Key ID: [your key]
    # AWS Secret Access Key: [your secret]
    # Default region name: us-east-1
    # Default output format: json
  2. Test the configuration

    Terminal window
    aws sts get-caller-identity

Initialize an AWS plugin instance for accessing Secrets Manager and Parameter Store.

Key/value args:

  • region (required): AWS region (e.g., us-east-1, eu-west-1)
  • namePrefix (optional): Prefix automatically prepended to all secret/parameter names
  • accessKeyId (optional): AWS access key ID for explicit authentication
  • secretAccessKey (optional): AWS secret access key for explicit authentication
  • sessionToken (optional): AWS session token for temporary credentials
  • profile (optional): Named profile from ~/.aws/credentials
  • id (optional): Instance identifier for multiple instances
# @initAws(region=us-east-1, namePrefix="prod/api/")
# ---

Represents an AWS access key ID (20-character alphanumeric string). Note that the type itself is marked as @sensitive, so adding an explicit @sensitive decorator is optional.

# @type=awsAccessKey
AWS_ACCESS_KEY_ID=

Represents an AWS secret access key (40-character string). This type is marked as @sensitive.

# @type=awsSecretKey
AWS_SECRET_ACCESS_KEY=

Fetch a secret from AWS Secrets Manager.

Array args:

  • instanceId (optional): instance identifier to use when multiple plugin instances are initialized
  • secretId (optional): secret name, ARN, or name with JSON key using # syntax. If omitted, uses the variable name.
  • key (optional, named parameter): JSON key to extract from the secret value
# Auto-infer secret name
DATABASE_URL=awsSecret()
# Explicit secret name
STRIPE_KEY=awsSecret("payments/stripe-key")
# Extract JSON key (shorthand)
DB_HOST=awsSecret("database-creds#host")
# Extract JSON key (named parameter)
DB_PORT=awsSecret("database-creds", key="port")
# With instance ID
US_SECRET=awsSecret(us, "my-secret")

Fetch a parameter from AWS Systems Manager Parameter Store.

Array args:

  • instanceId (optional): instance identifier to use when multiple plugin instances are initialized
  • parameterName (optional): parameter name/path or name with JSON key using # syntax. If omitted, uses the variable name.
  • key (optional, named parameter): JSON key to extract from the parameter value
# Auto-infer parameter name
DATABASE_HOST=awsParam()
# Explicit parameter path
APP_CONFIG=awsParam("/prod/app/config")
# Extract JSON key
DB_CREDS=awsParam("/prod/db/creds#password")
# With instance ID
EU_CONFIG=awsParam(eu, "/prod/config")

  • Verify the secret exists: aws secretsmanager list-secrets --query 'SecretList[?Name==\my-secret`]’`
  • Check you’re using the correct region
  • Ensure the secret name matches exactly (including any prefix)
  • Verify the parameter exists: aws ssm describe-parameters --parameter-filters "Key=Name,Values=/my/param"
  • Check you’re using the correct region
  • Parameter Store paths are case-sensitive
  • Check your IAM permissions: Test with aws sts get-caller-identity to see which identity you’re using
  • For IAM roles on EC2/ECS/Lambda: Verify the role is attached and has the required permissions
  • Ensure the IAM policy includes secretsmanager:GetSecretValue and/or ssm:GetParameter
  • Local dev: Run aws configure or ensure AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are set
  • AWS-hosted apps: Verify IAM role is attached
  • Other environments: Verify credentials are correct and properly injected
  • Test credentials: aws sts get-caller-identity
  • Verify your secret/parameter contains valid JSON
  • Check that the key you’re extracting exists in the JSON
  • Test manually: aws secretsmanager get-secret-value --secret-id my-secret --query SecretString --output text | jq .