# SecretumVault How-To Guide Step-by-step instructions for common tasks with SecretumVault. ## Table of Contents 1. [Getting Started](#getting-started) 2. [Initialize Vault](#initialize-vault) 3. [Unseal Vault](#unseal-vault) 4. [Manage Secrets](#manage-secrets) 5. [Configure Engines](#configure-engines) 6. [Setup Authorization](#setup-authorization) 7. [Configure TLS](#configure-tls) 8. [Integrate with Kubernetes](#integrate-with-kubernetes) 9. [Backup & Restore](#backup--restore) 10. [Monitor & Troubleshoot](#monitor--troubleshoot) --- ## Getting Started ### 1. Start Vault Locally **Using Docker Compose** (recommended for development): ```bash # Navigate to project cd secretumvault # Build image docker build -t secretumvault:latest . # Start all services docker-compose up -d # Verify vault is running curl http://localhost:8200/v1/sys/health ``` **Using Cargo**: ```bash # Create configuration cat > svault.toml <<'EOF' [vault] crypto_backend = "openssl" [server] address = "0.0.0.0" port = 8200 [storage] backend = "etcd" [storage.etcd] endpoints = ["http://localhost:2379"] [seal] seal_type = "shamir" threshold = 2 shares = 3 [engines.kv] path = "secret/" versioned = true [logging] level = "info" format = "json" EOF # Start vault (requires etcd running) cargo run --release -- server --config svault.toml ``` ### 2. Verify Health ```bash curl http://localhost:8200/v1/sys/health ``` Response: ```json { "initialized": false, "sealed": true, "standby": false, "performance_standby": false, "replication_performance_mode": "disabled", "replication_dr_mode": "disabled", "server_time_utc": 1703142600, "version": "0.1.0" } ``` Key fields: - `initialized: false` - Vault not initialized yet - `sealed: true` - Master key is sealed (expected before initialization) --- ## Initialize Vault ### 1. Generate Unseal Keys Create a request to initialize vault with Shamir Secret Sharing: ```bash curl -X POST http://localhost:8200/v1/sys/init \ -H "Content-Type: application/json" \ -d '{ "shares": 5, "threshold": 3 }' ``` Parameters: - `shares: 5` - Total unseal keys generated (5 people get 1 key each) - `threshold: 3` - Need 3 keys to unseal (quorum) Response: ```json { "keys": [ "key_1_base64_encoded", "key_2_base64_encoded", "key_3_base64_encoded", "key_4_base64_encoded", "key_5_base64_encoded" ], "root_token": "root_token_abc123def456" } ``` ### 2. Store Keys Securely **CRITICAL: Store unseal keys immediately in a secure location!** Save in password manager (Bitwarden, 1Password, LastPass): - Each unseal key separately (don't store all together) - Distribute keys to different people/locations - Test that stored keys are retrievable Save root token separately: - Store in same password manager - Label clearly: "Root Token - SecretumVault" - Keep temporary access only ### 3. Verify Initialization ```bash curl http://localhost:8200/v1/sys/health ``` Response should now show `initialized: true` and `sealed: true` --- ## Unseal Vault Vault must be unsealed before it can serve requests. ### 1. Unseal with Keys You need `threshold` keys (e.g., 3 of 5) to unseal. **Unseal with first key:** ```bash curl -X POST http://localhost:8200/v1/sys/unseal \ -H "Content-Type: application/json" \ -d '{ "key": "first_unseal_key_from_storage" }' ``` Response: ```json { "sealed": true, "t": 3, "n": 5, "progress": 1 } ``` Progress shows 1/3 keys provided. **Unseal with second key:** ```bash curl -X POST http://localhost:8200/v1/sys/unseal \ -H "Content-Type: application/json" \ -d '{ "key": "second_unseal_key_from_storage" }' ``` Response shows `progress: 2/3` **Unseal with third key (final):** ```bash curl -X POST http://localhost:8200/v1/sys/unseal \ -H "Content-Type: application/json" \ -d '{ "key": "third_unseal_key_from_storage" }' ``` Response: ```json { "sealed": false, "t": 3, "n": 5, "progress": 0 } ``` `sealed: false` means vault is now unsealed! ### 2. Verify Unsealed State ```bash curl http://localhost:8200/v1/sys/health ``` Should show `sealed: false` ### 3. Auto-Unseal (Future) For production, configure auto-unseal via AWS KMS or GCP Cloud KMS (planned): ```toml [seal] seal_type = "aws-kms" [seal.aws-kms] key_id = "arn:aws:kms:us-east-1:account:key/id" region = "us-east-1" ``` --- ## Manage Secrets ### 1. Store a Secret **HTTP Request:** ```bash curl -X POST http://localhost:8200/v1/secret/data/myapp \ -H "X-Vault-Token: $VAULT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "data": { "username": "admin", "password": "supersecret123", "api_key": "sk_live_abc123" } }' ``` Environment variable setup: ```bash # From initialization response export VAULT_TOKEN="root_token_abc123" ``` Response: ```json { "request_id": "req_123", "lease_id": "", "renewable": false, "lease_duration": 0, "data": null, "wrap_info": null, "warnings": null, "auth": null } ``` Status `201 Created` indicates success. ### 2. Read a Secret **HTTP Request:** ```bash curl -X GET http://localhost:8200/v1/secret/data/myapp \ -H "X-Vault-Token: $VAULT_TOKEN" ``` Response: ```json { "request_id": "req_124", "lease_id": "", "renewable": false, "lease_duration": 0, "data": { "data": { "username": "admin", "password": "supersecret123", "api_key": "sk_live_abc123" }, "metadata": { "created_time": "2025-12-21T10:30:00Z", "deletion_time": "", "destroyed": false, "version": 1 } } } ``` Extract secret data: ```bash # Get password field curl -s http://localhost:8200/v1/secret/data/myapp \ -H "X-Vault-Token: $VAULT_TOKEN" | jq '.data.data.password' ``` Output: `"supersecret123"` ### 3. Update a Secret ```bash curl -X POST http://localhost:8200/v1/secret/data/myapp \ -H "X-Vault-Token: $VAULT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "data": { "username": "admin", "password": "newsecret456", "api_key": "sk_live_abc123" } }' ``` New version created (version 2). Previous versions retained. ### 4. Delete a Secret ```bash curl -X DELETE http://localhost:8200/v1/secret/data/myapp \ -H "X-Vault-Token: $VAULT_TOKEN" ``` Soft delete: metadata retained, data destroyed. ### 5. List Secrets ```bash curl -X LIST http://localhost:8200/v1/secret/metadata \ -H "X-Vault-Token: $VAULT_TOKEN" ``` Response: ```json { "data": { "keys": [ "myapp", "database-prod", "aws-credentials" ] } } ``` ### 6. Restore from Version View available versions: ```bash curl -X GET http://localhost:8200/v1/secret/metadata/myapp \ -H "X-Vault-Token: $VAULT_TOKEN" ``` Response shows all versions with timestamps. Get specific version: ```bash curl -X GET http://localhost:8200/v1/secret/data/myapp?version=1 \ -H "X-Vault-Token: $VAULT_TOKEN" ``` --- ## Configure Engines ### 1. Enable Additional Engines Edit `svault.toml`: ```toml [engines.kv] path = "secret/" versioned = true [engines.transit] path = "transit/" versioned = true [engines.pki] path = "pki/" versioned = false [engines.database] path = "database/" versioned = false ``` Restart vault: ```bash # Docker Compose docker-compose restart vault # Or Cargo # Kill running process (Ctrl+C) and restart cargo run --release -- server --config svault.toml ``` ### 2. Use Transit Engine (Encryption) Create encryption key: ```bash curl -X POST http://localhost:8200/v1/transit/keys/my-key \ -H "X-Vault-Token: $VAULT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "exportable": false, "key_size": 256, "type": "aes-gcm" }' ``` Encrypt data: ```bash # Plaintext must be base64 encoded PLAINTEXT=$(echo -n "sensitive data" | base64) curl -X POST http://localhost:8200/v1/transit/encrypt/my-key \ -H "X-Vault-Token: $VAULT_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"plaintext\": \"$PLAINTEXT\"}" ``` Response: ```json { "data": { "ciphertext": "vault:v1:abc123def456..." } } ``` Decrypt data: ```bash CIPHERTEXT="vault:v1:abc123def456..." curl -X POST http://localhost:8200/v1/transit/decrypt/my-key \ -H "X-Vault-Token: $VAULT_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"ciphertext\": \"$CIPHERTEXT\"}" ``` Response: ```json { "data": { "plaintext": "c2Vuc2l0aXZlIGRhdGE=" } } ``` Decode plaintext: ```bash echo "c2Vuc2l0aXZlIGRhdGE=" | base64 -d # Output: sensitive data ``` ### 3. Mount at Custom Path Change mount path in config: ```toml [engines.kv] path = "app-secrets/" # Instead of "secret/" versioned = true ``` Then access at: ```bash curl http://localhost:8200/v1/app-secrets/data/myapp \ -H "X-Vault-Token: $VAULT_TOKEN" ``` --- ## Setup Authorization ### 1. Create Cedar Policies Create policy directory: ```bash mkdir -p /etc/secretumvault/policies ``` Create policy file: ```bash cat > /etc/secretumvault/policies/default.cedar <<'EOF' permit ( principal, action, resource ) when { principal has policies && principal.policies.contains("admin") }; deny ( principal, action == Action::"write", resource ) unless { context.time_of_day < 20:00 }; EOF ``` Update config: ```toml [auth] cedar_policies_dir = "/etc/secretumvault/policies" ``` ### 2. Create Auth Token ```bash curl -X POST http://localhost:8200/v1/auth/token/create \ -H "X-Vault-Token: $VAULT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "policies": ["default", "app-reader"], "ttl": "24h", "renewable": true }' ``` Response: ```json { "auth": { "client_token": "s.abc123def456", "policies": ["default", "app-reader"], "metadata": { "created_time": "2025-12-21T10:30:00Z", "ttl": "24h" } } } ``` Use token: ```bash export APP_TOKEN="s.abc123def456" curl http://localhost:8200/v1/secret/data/myapp \ -H "X-Vault-Token: $APP_TOKEN" ``` ### 3. Renew Token ```bash curl -X POST http://localhost:8200/v1/auth/token/renew \ -H "X-Vault-Token: $APP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "increment": "24h" }' ``` ### 4. Revoke Token ```bash curl -X POST http://localhost:8200/v1/auth/token/revoke \ -H "X-Vault-Token: $VAULT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "token": "s.abc123def456" }' ``` --- ## Configure TLS ### 1. Generate Self-Signed Certificate For development: ```bash openssl req -x509 -newkey rsa:4096 -keyout tls.key -out tls.crt \ -days 365 -nodes \ -subj "/CN=localhost/O=SecretumVault/C=US" ``` ### 2. Configure Vault Update `svault.toml`: ```toml [server] address = "0.0.0.0" port = 8200 tls_cert = "/path/to/tls.crt" tls_key = "/path/to/tls.key" ``` ### 3. Access via HTTPS ```bash # Allow self-signed certificate curl --insecure https://localhost:8200/v1/sys/health \ -H "X-Vault-Token: $VAULT_TOKEN" # Or with CA certificate curl --cacert tls.crt https://localhost:8200/v1/sys/health \ -H "X-Vault-Token: $VAULT_TOKEN" ``` ### 4. Production Certificate (Let's Encrypt) For Kubernetes with cert-manager, use the Helm installation which handles automatic certificate renewal. --- ## Integrate with Kubernetes ### 1. Deploy Vault ```bash # Apply manifests kubectl apply -f k8s/01-namespace.yaml kubectl apply -f k8s/02-configmap.yaml kubectl apply -f k8s/03-deployment.yaml kubectl apply -f k8s/04-service.yaml kubectl apply -f k8s/05-etcd.yaml # Wait for pods kubectl -n secretumvault wait --for=condition=ready pod -l app=vault --timeout=300s ``` ### 2. Initialize and Unseal Port-forward vault: ```bash kubectl -n secretumvault port-forward svc/vault 8200:8200 & ``` Initialize (from earlier steps): ```bash curl -X POST http://localhost:8200/v1/sys/init \ -H "Content-Type: application/json" \ -d '{"shares": 3, "threshold": 2}' ``` Save keys, then unseal (from earlier steps). ### 3. Create Kubernetes ServiceAccount ```bash cat > /tmp/app-sa.yaml <<'EOF' apiVersion: v1 kind: ServiceAccount metadata: name: myapp namespace: default EOF kubectl apply -f /tmp/app-sa.yaml ``` ### 4. Pod Secret Injection Create ClusterRoleBinding to allow reading vault-config: ```bash cat > /tmp/vault-reader.yaml <<'EOF' apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: vault-reader rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get"] - apiGroups: [""] resources: ["configmaps"] verbs: ["get"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: vault-reader roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: vault-reader subjects: - kind: ServiceAccount name: myapp namespace: default EOF kubectl apply -f /tmp/vault-reader.yaml ``` ### 5. Deploy Application Pod ```bash cat > /tmp/myapp-pod.yaml <<'EOF' apiVersion: v1 kind: Pod metadata: name: myapp namespace: default spec: serviceAccountName: myapp containers: - name: app image: myapp:latest env: - name: VAULT_ADDR value: "http://vault.secretumvault.svc.cluster.local:8200" - name: VAULT_TOKEN valueFrom: secretKeyRef: name: vault-token key: token volumeMounts: - name: vault-config mountPath: /etc/vault readOnly: true volumes: - name: vault-config configMap: name: vault-config namespace: secretumvault EOF kubectl apply -f /tmp/myapp-pod.yaml ``` --- ## Backup & Restore ### 1. Backup Secrets Export all secrets: ```bash # List all secrets SECRETS=$(curl -s http://localhost:8200/v1/secret/metadata \ -H "X-Vault-Token: $VAULT_TOKEN" | jq -r '.data.keys[]') # Backup each secret for secret in $SECRETS; do curl -s http://localhost:8200/v1/secret/data/$secret \ -H "X-Vault-Token: $VAULT_TOKEN" > $secret-backup.json done ``` ### 2. Export with Encryption Encrypt backup before storing: ```bash # Create transit key for backups curl -X POST http://localhost:8200/v1/transit/keys/backup-key \ -H "X-Vault-Token: $VAULT_TOKEN" \ -H "Content-Type: application/json" \ -d '{"type": "aes-gcm"}' # Backup and encrypt for secret in $SECRETS; do CONTENT=$(curl -s http://localhost:8200/v1/secret/data/$secret \ -H "X-Vault-Token: $VAULT_TOKEN" | base64) ENCRYPTED=$(curl -s -X POST http://localhost:8200/v1/transit/encrypt/backup-key \ -H "X-Vault-Token: $VAULT_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"plaintext\": \"$CONTENT\"}" | jq -r '.data.ciphertext') echo "$ENCRYPTED" > $secret-backup.enc done ``` ### 3. Restore Secrets ```bash # List backup files for backup in *-backup.json; do secret=${backup%-backup.json} # Read backup curl -X POST http://localhost:8200/v1/secret/data/$secret \ -H "X-Vault-Token: $VAULT_TOKEN" \ -H "Content-Type: application/json" \ -d @$backup done ``` --- ## Monitor & Troubleshoot ### 1. Check Vault Health ```bash curl http://localhost:8200/v1/sys/health | jq . ``` Key fields to check: - `sealed`: Should be `false` - `initialized`: Should be `true` - `standby`: Should be `false` (or expected leader state) ### 2. View Metrics Prometheus metrics endpoint: ```bash curl http://localhost:9090/metrics | grep vault ``` Common metrics: - `vault_secrets_stored_total` - Total secrets stored - `vault_secrets_read_total` - Total secrets read - `vault_operations_encrypt` - Encryption operations - `vault_tokens_created` - Tokens created ### 3. Check Logs Docker Compose: ```bash docker-compose logs -f vault ``` Kubernetes: ```bash kubectl -n secretumvault logs -f deployment/vault ``` Look for: - `ERROR` entries with details - `WARN` for unexpected but recoverable conditions - `INFO` for normal operations ### 4. Verify Storage Connectivity Check etcd from vault pod: ```bash kubectl -n secretumvault exec deployment/vault -- \ curl http://vault-etcd-client:2379/health ``` ### 5. Test Token Access Validate token is working: ```bash curl -X GET http://localhost:8200/v1/auth/token/self \ -H "X-Vault-Token: $VAULT_TOKEN" | jq '.auth' ``` Response shows token metadata and policies. ### 6. Common Issues **Issue: "sealed: true" after restart** - Solution: Run unseal procedure with stored keys **Issue: "permission denied" on secret read** - Solution: Check Cedar policies, verify token has correct policies **Issue: Storage connection error** - Solution: Verify backend endpoint in config (etcd DNS/IP) **Issue: High memory usage** - Solution: Check number of active leases, revoke old tokens **Issue: Slow operations** - Solution: Check storage backend performance, review metrics --- **For more details**, see: - [Architecture Guide](ARCHITECTURE.md) - [Configuration Reference](CONFIGURATION.md) - [Deployment Guide](../DEPLOYMENT.md)