zoobzio January 23, 2026 Edit this page

AWS Secrets Manager

The awssm package provides a fig.SecretProvider backed by AWS Secrets Manager.

Installation

go get github.com/zoobzio/fig/awssm

Quick Start

import (
    "context"
    "log"

    "github.com/zoobzio/fig"
    "github.com/zoobzio/fig/awssm"
)

type Config struct {
    DBPassword string `secret:"prod/database:password"`
    APIKey     string `secret:"prod/api-key"`
}

func main() {
    ctx := context.Background()

    provider, err := awssm.New(ctx)
    if err != nil {
        log.Fatal(err)
    }

    var cfg Config
    if err := fig.LoadContext(ctx, &cfg, provider); err != nil {
        log.Fatal(err)
    }
}

Configuration

Credentials

The provider uses the standard AWS SDK credential chain:

  1. Environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
  2. Shared credentials file (~/.aws/credentials)
  3. IAM role (EC2, ECS, Lambda)

Region

Set via environment or shared config:

export AWS_REGION=us-east-1

Or in ~/.aws/config:

[default]
region = us-east-1

Key Format

Keys follow the format secret-name or secret-name:json-field:

Plain Text Secrets

// AWS secret name: prod/api-key
// Value: sk_live_12345
APIKey string `secret:"prod/api-key"`

JSON Secrets

// AWS secret name: prod/database
// Value: {"username": "admin", "password": "secret"}
DBUser     string `secret:"prod/database:username"`
DBPassword string `secret:"prod/database:password"`

Creating Secrets

# Plain text
aws secretsmanager create-secret \
    --name prod/api-key \
    --secret-string "sk_live_12345"

# JSON
aws secretsmanager create-secret \
    --name prod/database \
    --secret-string '{"username":"admin","password":"secret"}'

API Reference

New

func New(ctx context.Context, opts ...Option) (*Provider, error)

Creates a provider using the default AWS configuration.

Parameters:

  • ctx — context for loading AWS config
  • opts — optional configuration

Returns: (*Provider, error) — error if AWS config loading fails.

NewWithClient

func NewWithClient(client *secretsmanager.Client, opts ...Option) *Provider

Creates a provider with a pre-configured Secrets Manager client.

Example:

import (
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/secretsmanager"
)

cfg, _ := config.LoadDefaultConfig(ctx,
    config.WithRegion("eu-west-1"),
)

client := secretsmanager.NewFromConfig(cfg)
provider := awssm.NewWithClient(client)

IAM Permissions

Required IAM policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "secretsmanager:GetSecretValue"
            ],
            "Resource": [
                "arn:aws:secretsmanager:*:*:secret:prod/*"
            ]
        }
    ]
}

Restrict Resource to specific secret ARNs in production.

Cross-Account Access

For secrets in another AWS account:

import (
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/credentials/stscreds"
    "github.com/aws/aws-sdk-go-v2/service/secretsmanager"
    "github.com/aws/aws-sdk-go-v2/service/sts"
)

cfg, _ := config.LoadDefaultConfig(ctx)
stsClient := sts.NewFromConfig(cfg)

assumeRoleCfg, _ := config.LoadDefaultConfig(ctx,
    config.WithCredentialsProvider(
        stscreds.NewAssumeRoleProvider(stsClient, "arn:aws:iam::123456789012:role/SecretsReader"),
    ),
)

client := secretsmanager.NewFromConfig(assumeRoleCfg)
provider := awssm.NewWithClient(client)

Error Handling

The provider returns fig.ErrSecretNotFound when:

  • The secret doesn't exist
  • The secret value is nil
  • The requested JSON field doesn't exist
  • The JSON field is not a string

Other errors (network, permissions) are returned as-is.

Binary Secrets

AWS Secrets Manager supports binary secrets, but fig only handles string values. For binary secrets, store them as base64-encoded strings and decode after loading:

type Config struct {
    CertBase64 string `secret:"tls/certificate"`
}

cfg := Config{}
fig.Load(&cfg, provider)

cert, _ := base64.StdEncoding.DecodeString(cfg.CertBase64)

Next Steps