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.
Features
Section titled “Features”- 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 configurefor local development - Auto-infer secret/parameter names from environment variable names
- JSON key extraction from secrets/parameters using
#syntax or namedkeyparameter - Name prefixing with
namePrefixoption for organized secret management - Support for named AWS profiles
- Support for explicit credentials
- Support for temporary credentials with session tokens
Installation and setup
Section titled “Installation and setup”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.
# 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)# ---Authentication options
Section titled “Authentication options”The plugin tries authentication methods in this priority order:
- Explicit credentials - If
accessKeyIdandsecretAccessKeyare provided - Named profile - If
profileis specified, uses credentials from~/.aws/credentials - Default AWS credential chain - Environment variables →
~/.aws/credentials→ IAM roles
Automatic authentication (Recommended)
Section titled “Automatic authentication (Recommended)”For most use cases, you only need to provide the AWS region:
# @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:
-
Create an IAM user with the necessary permissions (see AWS Setup section below)
-
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=awsAccessKeyAWS_ACCESS_KEY_ID=# @type=awsSecretKey @sensitiveAWS_SECRET_ACCESS_KEY= -
Set your credentials in deployed environments. Use your platform’s env var management UI to securely inject these values.
Using named profiles
Section titled “Using named profiles”Use a specific profile from your ~/.aws/credentials file:
# @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 = AKIAIOSFODNN7EXAMPLEaws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
[production]aws_access_key_id = AKIAI44QH8DHBEXAMPLEaws_secret_access_key = je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEYMultiple instances
Section titled “Multiple instances”If you need to connect to multiple regions or use different authentication, register multiple named instances:
# @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")Loading secrets and parameters
Section titled “Loading secrets and parameters”Once the plugin is installed and initialized, you can start adding config items that load values using the awsSecret() and awsParam() resolver functions.
AWS Secrets Manager
Section titled “AWS Secrets Manager”The awsSecret() function fetches secrets from AWS Secrets Manager.
# Auto-infer secret names (DATABASE_URL -> "DATABASE_URL")DATABASE_URL=awsSecret()API_KEY=awsSecret()
# Explicit secret namesSTRIPE_KEY=awsSecret("payments/stripe-secret-key")Systems Manager Parameter Store
Section titled “Systems Manager Parameter Store”The awsParam() function fetches parameters from Parameter Store.
# Parameters from Parameter StoreAPP_CONFIG=awsParam("/prod/app/config")FEATURE_FLAGS=awsParam("/prod/features")
# Auto-infer parameter names tooDATABASE_HOST=awsParam()JSON key extraction
Section titled “JSON key extraction”If your secrets or parameters contain JSON, you can extract specific keys:
# 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" parameterDB_PORT=awsSecret("database-creds", key="port")Name prefixing
Section titled “Name prefixing”Use namePrefix to automatically prefix all secret/parameter names for better organization:
# @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:
# @initAws(region=us-east-1, namePrefix="${ENV}/")# ---
# In prod: fetches "prod/DATABASE_URL"# In dev: fetches "dev/DATABASE_URL"DATABASE_URL=awsSecret()AWS Setup
Section titled “AWS Setup”Required IAM permissions
Section titled “Required IAM permissions”Your IAM user or role needs specific permissions to access secrets and parameters.
For AWS Secrets Manager
Section titled “For AWS Secrets Manager”{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["secretsmanager:GetSecretValue"], "Resource": "arn:aws:secretsmanager:*:*:secret:*" } ]}For AWS Systems Manager Parameter Store
Section titled “For AWS Systems Manager Parameter Store”{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["ssm:GetParameter"], "Resource": "arn:aws:ssm:*:*:parameter/*" } ]}IAM roles for AWS-hosted apps (Recommended)
Section titled “IAM roles for AWS-hosted apps (Recommended)”IAM roles are the AWS-native way to authenticate - no credentials needed!
-
Create an IAM role with the necessary permissions and trust policy for your service (EC2, ECS, or Lambda)
-
Attach the role to your application
- EC2: Create an instance profile and attach it to your instance
- ECS: Set the
taskRoleArnin your task definition - Lambda: Set the execution role in your function configuration
-
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.
IAM user for non-AWS environments
Section titled “IAM user for non-AWS environments”-
Create an IAM user
Terminal window aws iam create-user --user-name varlock-secrets-reader -
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 -
Create access credentials
Terminal window aws iam create-access-key --user-name varlock-secrets-readerSave the
AccessKeyIdandSecretAccessKeyfrom the output - you’ll need them for your deployments.
Configure AWS CLI for local development
Section titled “Configure AWS CLI for local development”-
Run
aws configureTerminal 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 -
Test the configuration
Terminal window aws sts get-caller-identity
Reference
Section titled “Reference”Root decorators
Section titled “Root decorators”@initAws()
Section titled “@initAws()”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 namesaccessKeyId(optional): AWS access key ID for explicit authenticationsecretAccessKey(optional): AWS secret access key for explicit authenticationsessionToken(optional): AWS session token for temporary credentialsprofile(optional): Named profile from~/.aws/credentialsid(optional): Instance identifier for multiple instances
# @initAws(region=us-east-1, namePrefix="prod/api/")# ---Data types
Section titled “Data types”awsAccessKey
Section titled “awsAccessKey”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=awsAccessKeyAWS_ACCESS_KEY_ID=awsSecretKey
Section titled “awsSecretKey”Represents an AWS secret access key (40-character string). This type is marked as @sensitive.
# @type=awsSecretKeyAWS_SECRET_ACCESS_KEY=Resolver functions
Section titled “Resolver functions”awsSecret()
Section titled “awsSecret()”Fetch a secret from AWS Secrets Manager.
Array args:
instanceId(optional): instance identifier to use when multiple plugin instances are initializedsecretId(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 nameDATABASE_URL=awsSecret()
# Explicit secret nameSTRIPE_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 IDUS_SECRET=awsSecret(us, "my-secret")awsParam()
Section titled “awsParam()”Fetch a parameter from AWS Systems Manager Parameter Store.
Array args:
instanceId(optional): instance identifier to use when multiple plugin instances are initializedparameterName(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 nameDATABASE_HOST=awsParam()
# Explicit parameter pathAPP_CONFIG=awsParam("/prod/app/config")
# Extract JSON keyDB_CREDS=awsParam("/prod/db/creds#password")
# With instance IDEU_CONFIG=awsParam(eu, "/prod/config")Troubleshooting
Section titled “Troubleshooting”Secret not found
Section titled “Secret not found”- 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)
Parameter not found
Section titled “Parameter not found”- 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
Permission denied
Section titled “Permission denied”- Check your IAM permissions: Test with
aws sts get-caller-identityto 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:GetSecretValueand/orssm:GetParameter
Authentication failed
Section titled “Authentication failed”- Local dev: Run
aws configureor ensureAWS_ACCESS_KEY_IDandAWS_SECRET_ACCESS_KEYare 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
JSON parsing errors
Section titled “JSON parsing errors”- 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 .