OmniVault Provider for AWS

AWS secret storage providers for OmniVault. Supports AWS Secrets Manager and AWS Systems Manager Parameter Store.
Features
- AWS Secrets Manager (
aws-sm): Designed for credentials, API keys, and rotating secrets
- AWS Parameter Store (
aws-ssm): Designed for configuration and hierarchical parameters
- IRSA Support: Automatic authentication on EKS with IAM Roles for Service Accounts
- Multi-Field Secrets: JSON parsing for complex secrets with username, password, etc.
- Versioning: Access specific versions of secrets
- Secret Rotation: Trigger rotation for Secrets Manager secrets
Installation
go get github.com/agentplexus/omnivault-aws
Quick Start
AWS Secrets Manager
package main
import (
"context"
"fmt"
"log"
"github.com/agentplexus/omnivault-aws"
)
func main() {
ctx := context.Background()
// Create Secrets Manager provider
provider, err := aws.NewSecretsManager(aws.Config{
Region: "us-east-1",
})
if err != nil {
log.Fatal(err)
}
// Get a secret
secret, err := provider.Get(ctx, "prod/database/credentials")
if err != nil {
log.Fatal(err)
}
fmt.Println("Password:", secret.Value)
fmt.Println("Username:", secret.Fields["username"])
}
AWS Parameter Store
package main
import (
"context"
"fmt"
"log"
"github.com/agentplexus/omnivault-aws"
)
func main() {
ctx := context.Background()
// Create Parameter Store provider
provider, err := aws.NewParameterStore(aws.Config{
Region: "us-east-1",
})
if err != nil {
log.Fatal(err)
}
// Get a parameter
secret, err := provider.Get(ctx, "/myapp/prod/database/password")
if err != nil {
log.Fatal(err)
}
fmt.Println("Password:", secret.Value)
}
EKS with IRSA (IAM Roles for Service Accounts)
On EKS, authentication is automatic when using IRSA. No credentials configuration needed.
1. Create IAM Policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue",
"secretsmanager:DescribeSecret"
],
"Resource": "arn:aws:secretsmanager:us-east-1:123456789:secret:myapp/*"
}
]
}
2. Create Service Account with IAM Role
eksctl create iamserviceaccount \
--name myapp-sa \
--namespace default \
--cluster my-cluster \
--attach-policy-arn arn:aws:iam::123456789:policy/MyAppSecretsPolicy \
--approve
3. Use in Pod
apiVersion: v1
kind: Pod
metadata:
name: myapp
spec:
serviceAccountName: myapp-sa # IRSA-enabled service account
containers:
- name: app
image: myapp:latest
env:
- name: AWS_REGION
value: "us-east-1"
4. Application Code
// On EKS with IRSA, credentials are automatic
provider, err := aws.NewSecretsManager(aws.Config{
Region: os.Getenv("AWS_REGION"),
})
// That's it! IRSA handles authentication
Transparent Local/Cloud Development
Use the same code locally and in the cloud by swapping providers based on environment:
package secrets
import (
"context"
"os"
"github.com/agentplexus/omnivault"
"github.com/agentplexus/omnivault-aws"
"github.com/agentplexus/omnivault-keyring"
)
func NewResolver(ctx context.Context) (*omnivault.Resolver, error) {
resolver := omnivault.NewResolver()
if os.Getenv("AWS_EXECUTION_ENV") != "" {
// Running on AWS (EKS, Lambda, EC2)
awsVault, err := aws.NewSecretsManager(aws.Config{})
if err != nil {
return nil, err
}
resolver.Register("secret", awsVault)
} else {
// Local development - use macOS Keychain
resolver.Register("secret", keyring.New(keyring.Config{
ServiceName: "myapp",
}))
}
return resolver, nil
}
// Usage - same code works everywhere
func GetDatabasePassword(ctx context.Context, resolver *omnivault.Resolver) (string, error) {
return resolver.Resolve(ctx, "secret://database/password")
}
Provider Comparison
| Feature |
Secrets Manager (aws-sm) |
Parameter Store (aws-ssm) |
| Best For |
Credentials, API keys |
Configuration, feature flags |
| Rotation |
Built-in rotation support |
Manual only |
| Pricing |
$0.40/secret/month + API calls |
Free tier: 10K params, then $0.05/10K |
| Size Limit |
64 KB |
4 KB (standard), 8 KB (advanced) |
| Versioning |
Automatic |
Automatic |
| Hierarchy |
Flat names |
Path-based (/app/env/key) |
| Cross-Account |
Resource policies |
Resource policies |
Configuration
Basic Config
type Config struct {
// Region is the AWS region (e.g., "us-east-1")
Region string
// Profile is the AWS credentials profile name
Profile string
// EndpointURL is for LocalStack or testing
EndpointURL string
// AWSConfig is an optional pre-configured AWS SDK config
AWSConfig *aws.Config
}
Secrets Manager Config
import "github.com/agentplexus/omnivault-aws/secretsmanager"
provider, err := secretsmanager.New(secretsmanager.Config{
Region: "us-east-1",
Profile: "dev", // Optional: AWS profile
JSONParse: aws.Bool(true), // Parse JSON secrets into Fields
VersionStage: "AWSCURRENT", // Version stage to retrieve
})
Parameter Store Config
import "github.com/agentplexus/omnivault-aws/parameterstore"
provider, err := parameterstore.New(parameterstore.Config{
Region: "us-east-1",
Profile: "dev",
PathPrefix: "/myapp/prod", // Prefix for all paths
WithDecryption: aws.Bool(true), // Decrypt SecureString
DefaultType: types.ParameterTypeSecureString,
KMSKeyID: "alias/myapp-key", // Custom KMS key
})
Usage Examples
Store and Retrieve Multi-Field Secrets
// Store a database credential with multiple fields
err := provider.Set(ctx, "database/prod", &vault.Secret{
Fields: map[string]string{
"username": "admin",
"password": "super-secret",
"host": "db.example.com",
"port": "5432",
},
Metadata: vault.Metadata{
Tags: map[string]string{
"environment": "production",
"team": "backend",
},
},
})
// Retrieve and access fields
secret, _ := provider.Get(ctx, "database/prod")
fmt.Printf("postgres://%s:%s@%s:%s/mydb",
secret.Fields["username"],
secret.Fields["password"],
secret.Fields["host"],
secret.Fields["port"],
)
List Secrets
// List all secrets with prefix
secrets, err := provider.List(ctx, "myapp/")
for _, name := range secrets {
fmt.Println(name)
}
Version Management
import "github.com/agentplexus/omnivault-aws/secretsmanager"
provider, _ := secretsmanager.New(config)
// List all versions
versions, _ := provider.ListVersions(ctx, "my-secret")
for _, v := range versions {
fmt.Printf("Version: %s, Current: %t\n", v.ID, v.Current)
}
// Get specific version
secret, _ := provider.GetVersion(ctx, "my-secret", "abc123-version-id")
Secret Rotation
import "github.com/agentplexus/omnivault-aws/secretsmanager"
provider, _ := secretsmanager.New(config)
// Trigger rotation (requires rotation Lambda configured in AWS)
newSecret, err := provider.Rotate(ctx, "my-secret")
if err != nil {
log.Fatal(err)
}
fmt.Println("New secret value:", newSecret.Value)
With OmniVault Client
import (
"github.com/agentplexus/omnivault"
"github.com/agentplexus/omnivault-aws"
)
provider, _ := aws.NewSecretsManager(aws.Config{Region: "us-east-1"})
client, _ := omnivault.NewClient(omnivault.Config{
CustomVault: provider,
})
defer client.Close()
// Use standard OmniVault API
password, _ := client.GetValue(ctx, "database/password")
username, _ := client.GetField(ctx, "database/credentials", "username")
Multi-Provider Resolver
resolver := omnivault.NewResolver()
resolver.Register("aws-sm", smProvider)
resolver.Register("aws-ssm", ssmProvider)
// Route to different backends via URI
dbPassword, _ := resolver.Resolve(ctx, "aws-sm://database/password")
appConfig, _ := resolver.Resolve(ctx, "aws-ssm:///myapp/config/feature-flag")
Local Development
Using AWS CLI Profiles
# Configure a profile
aws configure --profile dev
# Use in code
provider, _ := aws.NewSecretsManager(aws.Config{
Profile: "dev",
})
Using LocalStack
provider, _ := aws.NewSecretsManager(aws.Config{
EndpointURL: "http://localhost:4566",
Region: "us-east-1",
})
Using Environment Variables
export AWS_ACCESS_KEY_ID=xxx
export AWS_SECRET_ACCESS_KEY=xxx
export AWS_REGION=us-east-1
# Or use AWS SSO
aws sso login --profile dev
export AWS_PROFILE=dev
IAM Permissions
Secrets Manager
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue",
"secretsmanager:DescribeSecret",
"secretsmanager:ListSecrets"
],
"Resource": "*"
}
]
}
For write access, add:
{
"Action": [
"secretsmanager:CreateSecret",
"secretsmanager:PutSecretValue",
"secretsmanager:DeleteSecret"
]
}
Parameter Store
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:GetParameter",
"ssm:GetParameters",
"ssm:GetParametersByPath"
],
"Resource": "arn:aws:ssm:*:*:parameter/myapp/*"
}
]
}
For SecureString parameters, add KMS access:
{
"Effect": "Allow",
"Action": [
"kms:Decrypt"
],
"Resource": "arn:aws:kms:*:*:key/your-kms-key-id"
}
Error Handling
import (
"errors"
"github.com/agentplexus/omnivault/vault"
)
secret, err := provider.Get(ctx, "my-secret")
if err != nil {
switch {
case errors.Is(err, vault.ErrSecretNotFound):
log.Println("Secret not found")
case errors.Is(err, vault.ErrAccessDenied):
log.Println("Access denied - check IAM permissions")
default:
log.Printf("Error: %v", err)
}
}
URI Schemes
| Service |
Scheme |
Example |
| Secrets Manager |
aws-sm:// |
aws-sm://database/credentials |
| Parameter Store |
aws-ssm:// |
aws-ssm:///myapp/prod/config |
License
MIT License - see LICENSE for details.