Skip to content

Secrets Management

Dynamically resolve secrets from environment variables, files, Vault, AWS Secrets Manager, and 1Password.

Overview

Nefia's secrets management provides a unified interface for dynamically resolving credentials from multiple backends. During playbook or command execution, references in ${provider:path} format are automatically replaced with their actual values.

Supported Providers

ProviderTypeDescription
Environment variableenvReads from os.Getenv()
FilefileLocal JSON/YAML file
HashiCorp VaultvaultKV v2 secrets engine
AWS Secrets Manageraws-smAWS managed secrets
1Passwordop1Password CLI integration

Reference Syntax

plaintext
${provider:path}          # Retrieve the entire value
${provider:path#field}    # Retrieve a nested field

Examples:

yaml
# Environment variable
database_url: "${env:DATABASE_URL}"
 
# Vault KV v2
db_password: "${vault-prod:secret/myapp#password}"
 
# Local file
api_key: "${secrets-file:api_keys#production}"
 
# AWS Secrets Manager
rds_password: "${aws-prod:prod/db-credentials#password}"
 
# 1Password
login_password: "${1password:My Login#password}"

Configuration

yaml
secrets:
  enabled: true
  cache_ttl: "5m"
 
  providers:
    - name: "env"
      type: "env"
 
    - name: "vault-prod"
      type: "vault"
      config:
        address: "https://vault.prod.local"
        mount: "secret"
        auth_method: "approle"    # "approle" or empty (token authentication)
        role_id: "..."
        secret_id: "..."
 
    - name: "secrets-file"
      type: "file"
      config:
        path: "~/.config/nefia/secrets.json"
 
    - name: "aws-prod"
      type: "aws-sm"
      config:
        region: "us-east-1"
        profile: "prod-account"
 
    - name: "1password"
      type: "op"
      config:
        vault: "Private"
 
  inject:
    DATABASE_PASSWORD: "${vault-prod:secret/db#password}"
    API_KEY: "${env:MY_API_KEY}"

Provider Details

env — Environment Variables

No configuration required. Reads values from os.Getenv(). Returns an error if the variable is not set.

yaml
- name: "env"
  type: "env"
plaintext
${env:DATABASE_URL}
file — JSON/YAML Files

Reads a local secrets file. Automatically detects JSON and YAML formats.

yaml
- name: "secrets-file"
  type: "file"
  config:
    path: "~/.config/nefia/secrets.json"

Example secrets file:

json
{
  "database": {"host": "db.local", "password": "s3cret"},
  "api_key": "ak-12345"
}
plaintext
${secrets-file:api_key}            → "ak-12345"
${secrets-file:database#password}  → "s3cret"
vault — HashiCorp Vault

Supports the KV v2 secrets engine. Token authentication or AppRole authentication can be used.

yaml
- name: "vault-prod"
  type: "vault"
  config:
    address: "https://vault.example.com"   # Or the VAULT_ADDR environment variable
    token: "s.xxxx"                         # Or the VAULT_TOKEN environment variable
    mount: "secret"                         # Default: "secret"
    namespace: "admin"                      # Optional, or VAULT_NAMESPACE
    auth_method: "approle"                  # Optional: AppRole authentication
    role_id: "..."
    secret_id: "..."
    ca_cert: "/path/to/ca.crt"             # Optional: custom CA

The HTTP client timeout is 30 seconds.

aws-sm — AWS Secrets Manager

Uses AWS SDK v2. When a field is specified, the value is JSON-parsed and the field is extracted.

yaml
- name: "aws-prod"
  type: "aws-sm"
  config:
    region: "us-east-1"
    profile: "prod-account"           # Optional
    access_key_id: "AKIA..."          # Optional (static credentials)
    secret_access_key: "..."
    endpoint: "http://localhost:9999" # Optional (for local testing)

Authentication chain: static credentials -> profile -> default chain (IAM roles, etc.)

op — 1Password

Uses the op CLI. In CI/CD environments, non-interactive authentication is possible via the OP_SERVICE_ACCOUNT_TOKEN environment variable.

yaml
- name: "1password"
  type: "op"
  config:
    vault: "Private"    # Default vault name (optional)

Requirement: The op CLI must be available in PATH.

CLI Commands

List Providers

bash
nefia secrets list

Displays the names and types of all configured secret providers.

Test Secret Resolution

bash
nefia secrets test '${env:DATABASE_URL}'
nefia secrets test --reveal '${vault-prod:secret/db#password}'

By default, values are masked (only the first and last characters are shown). Use --reveal to display the full value.

Caching

Resolved values are cached in memory for the duration specified by cache_ttl (default: 5 minutes). When cache entries exceed 1024, expired entries are automatically purged.

Automatic Injection with inject

References defined in the secrets.inject map are resolved at application startup and injected as environment variables.

yaml
secrets:
  inject:
    DB_PASSWORD: "${vault-prod:secret/db#password}"

MCP Tools

AI agents can interact with the secrets subsystem via MCP:

ToolDescription
nefia.secrets.listList configured secret providers and their status.
nefia.secrets.testTest connectivity to a specific secret provider without revealing secret values.

Error Handling

When secret resolution fails, the ErrSecretResolveFailed sentinel error is returned. Structured error codes make debugging straightforward.