Skip to main content

Secret Management Guide

Learn how to effectively manage secrets using v-secure's enterprise-grade features.

Overview

Proper secret management is critical for security. This guide covers best practices for storing, accessing, and rotating secrets.

Creating Secrets

Basic Secret Creation

vsecure secrets:create API_KEY "sk_live_..." \
--tags production,api

With Metadata

vsecure secrets:create DATABASE_URL "postgresql://..." \
--tags production,database \
--metadata owner=backend-team \
--metadata service=user-api

With Expiration

vsecure secrets:create TEMP_TOKEN "xyz123" \
--expires-in 30d

Organizing Secrets

Use Tags Effectively

Tag secrets by:

  • Environment: production, staging, development
  • Service: api, database, cache
  • Team: backend, frontend, devops
  • Type: password, apikey, certificate
vsecure secrets:create DB_PASSWORD "secure123" \
--tags production,database,backend,password

Naming Conventions

Follow a consistent naming pattern:

{SERVICE}_{ENVIRONMENT}_{TYPE}

Examples:

  • USER_API_PRODUCTION_DATABASE_URL
  • PAYMENT_SERVICE_STAGING_STRIPE_KEY
  • AUTH_SERVICE_PRODUCTION_JWT_SECRET

Secret Rotation

Manual Rotation

# Update secret (creates new version)
vsecure secrets:update API_KEY "new_key_value"

# List versions
vsecure secrets:versions API_KEY

# Rollback if needed
vsecure secrets:rollback API_KEY --version 2

Automatic Rotation

Configure rotation policy:

await client.secrets.create({
name: 'API_KEY',
value: 'initial_value',
rotationPolicy: {
enabled: true,
period: '30d',
notifyBefore: '7d'
}
});

Access Control

Role-Based Access

Define who can access secrets:

{
"secrets": {
"production/*": {
"read": ["engineers", "devops"],
"write": ["devops"],
"delete": ["admins"]
}
}
}

Time-Limited Access

Grant temporary access:

vsecure secrets:grant-access DATABASE_URL \
--user john@example.com \
--duration 1h

Version Control

Viewing History

# List all versions
vsecure secrets:versions DATABASE_URL

# Get specific version
vsecure secrets:get DATABASE_URL --version 2

# Compare versions
vsecure secrets:diff DATABASE_URL --from 1 --to 2

Rollback

# Rollback to previous version
vsecure secrets:rollback DATABASE_URL

# Rollback to specific version
vsecure secrets:rollback DATABASE_URL --version 3

Best Practices

1. Never Hardcode Secrets

Bad:

const apiKey = 'sk_live_abc123';

Good:

import { VSecureClient } from '@lanonasis/v-secure-sdk';

const client = new VSecureClient();
const apiKey = await client.secrets.get('API_KEY');

2. Use Environment-Specific Secrets

# Development
vsecure secrets:create API_KEY "dev_key" --tags development

# Production
vsecure secrets:create API_KEY "prod_key" --tags production

3. Implement Rotation

# Set expiration on all sensitive secrets
vsecure secrets:update STRIPE_KEY --expires-in 90d

4. Monitor Access

# Review who accessed secrets
vsecure audit:logs --resource secrets --action accessed

5. Use Metadata

vsecure secrets:create API_KEY "..." \
--metadata owner=john@example.com \
--metadata purpose="Payment processing" \
--metadata documentation=https://wiki.company.com/api

Integration Patterns

Application Startup

import { VSecureClient } from '@lanonasis/v-secure-sdk';

async function loadSecrets() {
const client = new VSecureClient();

const secrets = await client.secrets.batchGet([
'DATABASE_URL',
'REDIS_URL',
'API_KEY'
]);

process.env.DATABASE_URL = secrets.DATABASE_URL;
process.env.REDIS_URL = secrets.REDIS_URL;
process.env.API_KEY = secrets.API_KEY;
}

await loadSecrets();

Dynamic Secret Loading

class SecretManager {
private cache = new Map();
private ttl = 300000; // 5 minutes

async getSecret(name: string): Promise<string> {
const cached = this.cache.get(name);

if (cached && Date.now() - cached.timestamp < this.ttl) {
return cached.value;
}

const secret = await client.secrets.get(name);
this.cache.set(name, {
value: secret.value,
timestamp: Date.now()
});

return secret.value;
}
}

Next Steps