mirror of
https://github.com/BagelHole/DevOps-Security-Agent-Skills.git
synced 2026-08-22 12:49:53 +02:00
.
This commit is contained in:
@@ -0,0 +1,384 @@
|
||||
---
|
||||
name: hashicorp-vault
|
||||
description: Manage secrets and PKI with HashiCorp Vault. Configure secret engines, authentication methods, and policies. Use when implementing centralized secrets management, dynamic credentials, or certificate management.
|
||||
license: MIT
|
||||
metadata:
|
||||
author: devops-skills
|
||||
version: "1.0"
|
||||
---
|
||||
|
||||
# HashiCorp Vault
|
||||
|
||||
Centrally manage secrets, encryption, and access with HashiCorp Vault.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
Use this skill when:
|
||||
- Centralizing secrets management
|
||||
- Implementing dynamic credentials
|
||||
- Managing PKI and certificates
|
||||
- Encrypting sensitive data
|
||||
- Meeting compliance requirements
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Vault server (dev or production)
|
||||
- Vault CLI installed
|
||||
- Network access to Vault
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Development Server
|
||||
|
||||
```bash
|
||||
# Start dev server
|
||||
vault server -dev
|
||||
|
||||
# Set environment
|
||||
export VAULT_ADDR='http://127.0.0.1:8200'
|
||||
export VAULT_TOKEN='root'
|
||||
|
||||
# Verify connection
|
||||
vault status
|
||||
```
|
||||
|
||||
### Production Deployment
|
||||
|
||||
```hcl
|
||||
# config.hcl
|
||||
storage "raft" {
|
||||
path = "/opt/vault/data"
|
||||
node_id = "vault-1"
|
||||
}
|
||||
|
||||
listener "tcp" {
|
||||
address = "0.0.0.0:8200"
|
||||
tls_cert_file = "/opt/vault/tls/vault.crt"
|
||||
tls_key_file = "/opt/vault/tls/vault.key"
|
||||
}
|
||||
|
||||
api_addr = "https://vault.example.com:8200"
|
||||
cluster_addr = "https://vault.example.com:8201"
|
||||
|
||||
ui = true
|
||||
```
|
||||
|
||||
```bash
|
||||
# Initialize Vault
|
||||
vault operator init -key-shares=5 -key-threshold=3
|
||||
|
||||
# Unseal (run 3 times with different keys)
|
||||
vault operator unseal <key-1>
|
||||
vault operator unseal <key-2>
|
||||
vault operator unseal <key-3>
|
||||
|
||||
# Login
|
||||
vault login <root-token>
|
||||
```
|
||||
|
||||
## Secret Engines
|
||||
|
||||
### KV Secrets
|
||||
|
||||
```bash
|
||||
# Enable KV v2
|
||||
vault secrets enable -path=secret kv-v2
|
||||
|
||||
# Write secret
|
||||
vault kv put secret/myapp/config \
|
||||
username="admin" \
|
||||
password="s3cr3t"
|
||||
|
||||
# Read secret
|
||||
vault kv get secret/myapp/config
|
||||
vault kv get -field=password secret/myapp/config
|
||||
|
||||
# Update secret
|
||||
vault kv put secret/myapp/config \
|
||||
username="admin" \
|
||||
password="new-password"
|
||||
|
||||
# List secrets
|
||||
vault kv list secret/
|
||||
|
||||
# Delete secret
|
||||
vault kv delete secret/myapp/config
|
||||
|
||||
# Version history
|
||||
vault kv metadata get secret/myapp/config
|
||||
```
|
||||
|
||||
### Database Secrets
|
||||
|
||||
```bash
|
||||
# Enable database engine
|
||||
vault secrets enable database
|
||||
|
||||
# Configure PostgreSQL connection
|
||||
vault write database/config/postgresql \
|
||||
plugin_name=postgresql-database-plugin \
|
||||
connection_url="postgresql://{{username}}:{{password}}@localhost:5432/mydb" \
|
||||
allowed_roles="readonly,readwrite" \
|
||||
username="vault" \
|
||||
password="vault-password"
|
||||
|
||||
# Create role
|
||||
vault write database/roles/readonly \
|
||||
db_name=postgresql \
|
||||
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; \
|
||||
GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
|
||||
default_ttl="1h" \
|
||||
max_ttl="24h"
|
||||
|
||||
# Get credentials
|
||||
vault read database/creds/readonly
|
||||
```
|
||||
|
||||
### AWS Secrets
|
||||
|
||||
```bash
|
||||
# Enable AWS engine
|
||||
vault secrets enable aws
|
||||
|
||||
# Configure root credentials
|
||||
vault write aws/config/root \
|
||||
access_key=AKIA... \
|
||||
secret_key=secret... \
|
||||
region=us-east-1
|
||||
|
||||
# Create role
|
||||
vault write aws/roles/deploy \
|
||||
credential_type=iam_user \
|
||||
policy_document=-<<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": ["s3:*"],
|
||||
"Resource": ["arn:aws:s3:::my-bucket/*"]
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
|
||||
# Get credentials
|
||||
vault read aws/creds/deploy
|
||||
```
|
||||
|
||||
### PKI Secrets
|
||||
|
||||
```bash
|
||||
# Enable PKI engine
|
||||
vault secrets enable pki
|
||||
vault secrets tune -max-lease-ttl=87600h pki
|
||||
|
||||
# Generate root CA
|
||||
vault write -field=certificate pki/root/generate/internal \
|
||||
common_name="example.com" \
|
||||
ttl=87600h > ca_cert.crt
|
||||
|
||||
# Configure URLs
|
||||
vault write pki/config/urls \
|
||||
issuing_certificates="https://vault.example.com:8200/v1/pki/ca" \
|
||||
crl_distribution_points="https://vault.example.com:8200/v1/pki/crl"
|
||||
|
||||
# Create role
|
||||
vault write pki/roles/web-server \
|
||||
allowed_domains="example.com" \
|
||||
allow_subdomains=true \
|
||||
max_ttl="720h"
|
||||
|
||||
# Issue certificate
|
||||
vault write pki/issue/web-server \
|
||||
common_name="web.example.com" \
|
||||
ttl="24h"
|
||||
```
|
||||
|
||||
## Authentication Methods
|
||||
|
||||
### AppRole
|
||||
|
||||
```bash
|
||||
# Enable AppRole
|
||||
vault auth enable approle
|
||||
|
||||
# Create role
|
||||
vault write auth/approle/role/myapp \
|
||||
token_policies="myapp-policy" \
|
||||
token_ttl=1h \
|
||||
token_max_ttl=4h \
|
||||
secret_id_ttl=10m
|
||||
|
||||
# Get role ID
|
||||
vault read auth/approle/role/myapp/role-id
|
||||
|
||||
# Generate secret ID
|
||||
vault write -f auth/approle/role/myapp/secret-id
|
||||
|
||||
# Login
|
||||
vault write auth/approle/login \
|
||||
role_id=<role-id> \
|
||||
secret_id=<secret-id>
|
||||
```
|
||||
|
||||
### Kubernetes
|
||||
|
||||
```bash
|
||||
# Enable Kubernetes auth
|
||||
vault auth enable kubernetes
|
||||
|
||||
# Configure
|
||||
vault write auth/kubernetes/config \
|
||||
kubernetes_host="https://kubernetes.default.svc" \
|
||||
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
||||
|
||||
# Create role
|
||||
vault write auth/kubernetes/role/myapp \
|
||||
bound_service_account_names=myapp \
|
||||
bound_service_account_namespaces=default \
|
||||
policies=myapp-policy \
|
||||
ttl=1h
|
||||
```
|
||||
|
||||
### OIDC
|
||||
|
||||
```bash
|
||||
# Enable OIDC auth
|
||||
vault auth enable oidc
|
||||
|
||||
# Configure
|
||||
vault write auth/oidc/config \
|
||||
oidc_discovery_url="https://accounts.google.com" \
|
||||
oidc_client_id="your-client-id" \
|
||||
oidc_client_secret="your-client-secret" \
|
||||
default_role="default"
|
||||
|
||||
# Create role
|
||||
vault write auth/oidc/role/default \
|
||||
bound_audiences="your-client-id" \
|
||||
allowed_redirect_uris="http://localhost:8250/oidc/callback" \
|
||||
user_claim="sub" \
|
||||
policies="default"
|
||||
```
|
||||
|
||||
## Policies
|
||||
|
||||
### Policy Definition
|
||||
|
||||
```hcl
|
||||
# myapp-policy.hcl
|
||||
# Read secrets
|
||||
path "secret/data/myapp/*" {
|
||||
capabilities = ["read", "list"]
|
||||
}
|
||||
|
||||
# Database credentials
|
||||
path "database/creds/myapp-db" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
|
||||
# PKI certificates
|
||||
path "pki/issue/web-server" {
|
||||
capabilities = ["create", "update"]
|
||||
}
|
||||
|
||||
# Deny access to other secrets
|
||||
path "secret/data/other/*" {
|
||||
capabilities = ["deny"]
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
# Create policy
|
||||
vault policy write myapp myapp-policy.hcl
|
||||
|
||||
# List policies
|
||||
vault policy list
|
||||
|
||||
# Read policy
|
||||
vault policy read myapp
|
||||
```
|
||||
|
||||
## Application Integration
|
||||
|
||||
### Python
|
||||
|
||||
```python
|
||||
import hvac
|
||||
|
||||
# Initialize client
|
||||
client = hvac.Client(url='http://localhost:8200')
|
||||
|
||||
# AppRole authentication
|
||||
client.auth.approle.login(
|
||||
role_id='role-id',
|
||||
secret_id='secret-id'
|
||||
)
|
||||
|
||||
# Read secret
|
||||
secret = client.secrets.kv.v2.read_secret_version(
|
||||
path='myapp/config',
|
||||
mount_point='secret'
|
||||
)
|
||||
password = secret['data']['data']['password']
|
||||
|
||||
# Get database credentials
|
||||
db_creds = client.secrets.database.generate_credentials(
|
||||
name='myapp-db'
|
||||
)
|
||||
```
|
||||
|
||||
### Kubernetes Sidecar
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: myapp
|
||||
annotations:
|
||||
vault.hashicorp.com/agent-inject: "true"
|
||||
vault.hashicorp.com/role: "myapp"
|
||||
vault.hashicorp.com/agent-inject-secret-config: "secret/data/myapp/config"
|
||||
vault.hashicorp.com/agent-inject-template-config: |
|
||||
{{- with secret "secret/data/myapp/config" -}}
|
||||
export DB_PASSWORD="{{ .Data.data.password }}"
|
||||
{{- end }}
|
||||
spec:
|
||||
serviceAccountName: myapp
|
||||
containers:
|
||||
- name: myapp
|
||||
image: myapp:latest
|
||||
command: ["/bin/sh", "-c", "source /vault/secrets/config && ./start.sh"]
|
||||
```
|
||||
|
||||
## Common Issues
|
||||
|
||||
### Issue: Sealed Vault
|
||||
**Problem**: Vault is sealed after restart
|
||||
**Solution**: Implement auto-unseal with cloud KMS or HSM
|
||||
|
||||
### Issue: Token Expired
|
||||
**Problem**: Application token has expired
|
||||
**Solution**: Implement token renewal, use shorter-lived tokens
|
||||
|
||||
### Issue: Permission Denied
|
||||
**Problem**: Cannot access secrets
|
||||
**Solution**: Review policies, check token capabilities
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Use short-lived tokens
|
||||
- Implement auto-unseal
|
||||
- Enable audit logging
|
||||
- Use namespaces for isolation
|
||||
- Rotate root tokens regularly
|
||||
- Implement least-privilege policies
|
||||
- Use dynamic secrets where possible
|
||||
- Regular backup and DR testing
|
||||
|
||||
## Related Skills
|
||||
|
||||
- [aws-secrets-manager](../aws-secrets-manager/) - AWS native secrets
|
||||
- [sops-encryption](../sops-encryption/) - File encryption
|
||||
- [kubernetes-hardening](../../hardening/kubernetes-hardening/) - K8s security
|
||||
@@ -0,0 +1,81 @@
|
||||
# Kubernetes Authentication for Vault
|
||||
# Enables pods to authenticate with Vault using service accounts
|
||||
|
||||
---
|
||||
# ServiceAccount for Vault auth
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: vault-auth
|
||||
namespace: vault
|
||||
|
||||
---
|
||||
# ClusterRoleBinding for token review
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: vault-tokenreview-binding
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: system:auth-delegator
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: vault-auth
|
||||
namespace: vault
|
||||
|
||||
---
|
||||
# Secret for SA token (K8s 1.24+)
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: vault-auth-token
|
||||
namespace: vault
|
||||
annotations:
|
||||
kubernetes.io/service-account.name: vault-auth
|
||||
type: kubernetes.io/service-account-token
|
||||
|
||||
---
|
||||
# Example: Application ServiceAccount
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: myapp
|
||||
namespace: myapp
|
||||
|
||||
---
|
||||
# Example: Pod using Vault Agent Injector
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: myapp
|
||||
namespace: myapp
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: myapp
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: myapp
|
||||
annotations:
|
||||
# Vault Agent Injector annotations
|
||||
vault.hashicorp.com/agent-inject: "true"
|
||||
vault.hashicorp.com/role: "myapp"
|
||||
vault.hashicorp.com/agent-inject-secret-config: "secret/data/myapp/config"
|
||||
vault.hashicorp.com/agent-inject-template-config: |
|
||||
{{- with secret "secret/data/myapp/config" -}}
|
||||
DATABASE_URL={{ .Data.data.database_url }}
|
||||
API_KEY={{ .Data.data.api_key }}
|
||||
{{- end }}
|
||||
spec:
|
||||
serviceAccountName: myapp
|
||||
containers:
|
||||
- name: myapp
|
||||
image: myapp:latest
|
||||
# Secrets available at /vault/secrets/config
|
||||
volumeMounts:
|
||||
- name: secrets
|
||||
mountPath: /vault/secrets
|
||||
readOnly: true
|
||||
@@ -0,0 +1,62 @@
|
||||
# Vault Server Configuration
|
||||
# /etc/vault.d/vault.hcl
|
||||
|
||||
# Cluster name
|
||||
cluster_name = "production"
|
||||
|
||||
# Storage backend (Raft for HA)
|
||||
storage "raft" {
|
||||
path = "/opt/vault/data"
|
||||
node_id = "vault-1"
|
||||
|
||||
retry_join {
|
||||
leader_api_addr = "https://vault-2.example.com:8200"
|
||||
}
|
||||
retry_join {
|
||||
leader_api_addr = "https://vault-3.example.com:8200"
|
||||
}
|
||||
}
|
||||
|
||||
# Listener configuration
|
||||
listener "tcp" {
|
||||
address = "0.0.0.0:8200"
|
||||
cluster_address = "0.0.0.0:8201"
|
||||
tls_cert_file = "/opt/vault/tls/vault.crt"
|
||||
tls_key_file = "/opt/vault/tls/vault.key"
|
||||
|
||||
# TLS settings
|
||||
tls_min_version = "tls12"
|
||||
tls_cipher_suites = "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
|
||||
}
|
||||
|
||||
# API address
|
||||
api_addr = "https://vault.example.com:8200"
|
||||
cluster_addr = "https://vault-1.example.com:8201"
|
||||
|
||||
# UI
|
||||
ui = true
|
||||
|
||||
# Telemetry
|
||||
telemetry {
|
||||
prometheus_retention_time = "30s"
|
||||
disable_hostname = true
|
||||
}
|
||||
|
||||
# Audit logging
|
||||
# Enable via API after init:
|
||||
# vault audit enable file file_path=/var/log/vault/audit.log
|
||||
|
||||
# Seal configuration (Auto-unseal with AWS KMS)
|
||||
# seal "awskms" {
|
||||
# region = "us-east-1"
|
||||
# kms_key_id = "alias/vault-unseal-key"
|
||||
# }
|
||||
|
||||
# Performance settings
|
||||
max_lease_ttl = "768h"
|
||||
default_lease_ttl = "768h"
|
||||
disable_mlock = false
|
||||
disable_cache = false
|
||||
|
||||
# Plugin directory
|
||||
plugin_directory = "/opt/vault/plugins"
|
||||
@@ -0,0 +1,136 @@
|
||||
# Vault Secrets Engines Guide
|
||||
|
||||
## KV Secrets Engine (v2)
|
||||
|
||||
### Enable and Configure
|
||||
```bash
|
||||
# Enable KV v2
|
||||
vault secrets enable -path=secret kv-v2
|
||||
|
||||
# Write secret
|
||||
vault kv put secret/myapp/config \
|
||||
db_host="postgres.example.com" \
|
||||
db_user="myapp" \
|
||||
db_password="secret123"
|
||||
|
||||
# Read secret
|
||||
vault kv get secret/myapp/config
|
||||
vault kv get -field=db_password secret/myapp/config
|
||||
|
||||
# List secrets
|
||||
vault kv list secret/myapp/
|
||||
|
||||
# Delete secret
|
||||
vault kv delete secret/myapp/config
|
||||
|
||||
# Versioning
|
||||
vault kv get -version=1 secret/myapp/config
|
||||
vault kv rollback -version=1 secret/myapp/config
|
||||
```
|
||||
|
||||
## Database Secrets Engine
|
||||
|
||||
### Setup Dynamic Credentials
|
||||
```bash
|
||||
# Enable database engine
|
||||
vault secrets enable database
|
||||
|
||||
# Configure PostgreSQL
|
||||
vault write database/config/myapp-db \
|
||||
plugin_name=postgresql-database-plugin \
|
||||
allowed_roles="myapp-role" \
|
||||
connection_url="postgresql://{{username}}:{{password}}@postgres:5432/myapp?sslmode=disable" \
|
||||
username="vault_admin" \
|
||||
password="admin_password"
|
||||
|
||||
# Create role
|
||||
vault write database/roles/myapp-role \
|
||||
db_name=myapp-db \
|
||||
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; \
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
|
||||
default_ttl="1h" \
|
||||
max_ttl="24h"
|
||||
|
||||
# Generate credentials
|
||||
vault read database/creds/myapp-role
|
||||
```
|
||||
|
||||
## AWS Secrets Engine
|
||||
|
||||
### Setup Dynamic AWS Credentials
|
||||
```bash
|
||||
# Enable AWS engine
|
||||
vault secrets enable aws
|
||||
|
||||
# Configure root credentials
|
||||
vault write aws/config/root \
|
||||
access_key=AKIAXXXXXXXX \
|
||||
secret_key=xxxxxxxx \
|
||||
region=us-east-1
|
||||
|
||||
# Create role
|
||||
vault write aws/roles/deploy-role \
|
||||
credential_type=iam_user \
|
||||
policy_document=-<<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": ["s3:*"],
|
||||
"Resource": ["arn:aws:s3:::my-bucket/*"]
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
|
||||
# Generate credentials
|
||||
vault read aws/creds/deploy-role
|
||||
```
|
||||
|
||||
## PKI Secrets Engine
|
||||
|
||||
### Certificate Authority
|
||||
```bash
|
||||
# Enable PKI
|
||||
vault secrets enable pki
|
||||
vault secrets tune -max-lease-ttl=87600h pki
|
||||
|
||||
# Generate root CA
|
||||
vault write pki/root/generate/internal \
|
||||
common_name="Example Root CA" \
|
||||
ttl=87600h
|
||||
|
||||
# Create role
|
||||
vault write pki/roles/server-cert \
|
||||
allowed_domains="example.com" \
|
||||
allow_subdomains=true \
|
||||
max_ttl="720h"
|
||||
|
||||
# Issue certificate
|
||||
vault write pki/issue/server-cert \
|
||||
common_name="api.example.com" \
|
||||
ttl="24h"
|
||||
```
|
||||
|
||||
## Transit Secrets Engine
|
||||
|
||||
### Encryption as a Service
|
||||
```bash
|
||||
# Enable transit
|
||||
vault secrets enable transit
|
||||
|
||||
# Create encryption key
|
||||
vault write -f transit/keys/myapp-key
|
||||
|
||||
# Encrypt data
|
||||
vault write transit/encrypt/myapp-key \
|
||||
plaintext=$(echo "secret data" | base64)
|
||||
|
||||
# Decrypt data
|
||||
vault write transit/decrypt/myapp-key \
|
||||
ciphertext="vault:v1:xxxxx"
|
||||
|
||||
# Rotate key
|
||||
vault write -f transit/keys/myapp-key/rotate
|
||||
```
|
||||
@@ -0,0 +1,130 @@
|
||||
# Vault Policy Guide
|
||||
|
||||
## Policy Syntax
|
||||
|
||||
```hcl
|
||||
# Basic policy structure
|
||||
path "secret/data/myapp/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list"]
|
||||
}
|
||||
```
|
||||
|
||||
## Capabilities
|
||||
|
||||
| Capability | HTTP Verb | Description |
|
||||
|------------|-----------|-------------|
|
||||
| `create` | POST/PUT | Create new data |
|
||||
| `read` | GET | Read data |
|
||||
| `update` | POST/PUT | Update existing data |
|
||||
| `delete` | DELETE | Delete data |
|
||||
| `list` | LIST | List keys |
|
||||
| `sudo` | - | Root-protected paths |
|
||||
| `deny` | - | Explicitly deny access |
|
||||
|
||||
## Common Policies
|
||||
|
||||
### Application Read-Only
|
||||
```hcl
|
||||
# app-readonly.hcl
|
||||
path "secret/data/myapp/*" {
|
||||
capabilities = ["read", "list"]
|
||||
}
|
||||
|
||||
path "secret/metadata/myapp/*" {
|
||||
capabilities = ["read", "list"]
|
||||
}
|
||||
```
|
||||
|
||||
### Developer Policy
|
||||
```hcl
|
||||
# developer.hcl
|
||||
path "secret/data/dev/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list"]
|
||||
}
|
||||
|
||||
path "secret/data/staging/*" {
|
||||
capabilities = ["read", "list"]
|
||||
}
|
||||
|
||||
# Deny production access
|
||||
path "secret/data/prod/*" {
|
||||
capabilities = ["deny"]
|
||||
}
|
||||
```
|
||||
|
||||
### CI/CD Pipeline
|
||||
```hcl
|
||||
# cicd.hcl
|
||||
# Read deployment secrets
|
||||
path "secret/data/deploy/*" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
|
||||
# Generate dynamic database credentials
|
||||
path "database/creds/myapp-role" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
|
||||
# Sign SSH keys
|
||||
path "ssh-client-signer/sign/deploy-role" {
|
||||
capabilities = ["create", "update"]
|
||||
}
|
||||
```
|
||||
|
||||
### Admin Policy
|
||||
```hcl
|
||||
# admin.hcl
|
||||
# Manage secrets engines
|
||||
path "sys/mounts/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list"]
|
||||
}
|
||||
|
||||
# Manage policies
|
||||
path "sys/policies/acl/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list"]
|
||||
}
|
||||
|
||||
# Manage auth methods
|
||||
path "sys/auth/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
|
||||
}
|
||||
|
||||
# View audit logs
|
||||
path "sys/audit" {
|
||||
capabilities = ["read", "list"]
|
||||
}
|
||||
```
|
||||
|
||||
## Policy Templates
|
||||
|
||||
### Using Templating
|
||||
```hcl
|
||||
# Per-user secrets path
|
||||
path "secret/data/users/{{identity.entity.name}}/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list"]
|
||||
}
|
||||
|
||||
# Team-based access
|
||||
path "secret/data/teams/{{identity.groups.names}}/*" {
|
||||
capabilities = ["read", "list"]
|
||||
}
|
||||
```
|
||||
|
||||
## Policy Management
|
||||
|
||||
```bash
|
||||
# Write policy
|
||||
vault policy write myapp-policy myapp-policy.hcl
|
||||
|
||||
# List policies
|
||||
vault policy list
|
||||
|
||||
# Read policy
|
||||
vault policy read myapp-policy
|
||||
|
||||
# Delete policy
|
||||
vault policy delete myapp-policy
|
||||
|
||||
# Test policy (requires root)
|
||||
vault token create -policy=myapp-policy
|
||||
```
|
||||
@@ -0,0 +1,55 @@
|
||||
#!/bin/bash
|
||||
# Vault Backup Script (Raft Storage)
|
||||
# Usage: ./vault-backup.sh [output-dir]
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
OUTPUT_DIR="${1:-./vault-backups}"
|
||||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||
BACKUP_FILE="$OUTPUT_DIR/vault-snapshot-$TIMESTAMP.snap"
|
||||
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
echo "========================================="
|
||||
echo "Vault Raft Snapshot Backup"
|
||||
echo "Output: $BACKUP_FILE"
|
||||
echo "========================================="
|
||||
echo ""
|
||||
|
||||
# Check Vault status
|
||||
if ! vault status &>/dev/null; then
|
||||
echo "Error: Cannot connect to Vault or Vault is sealed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Take snapshot
|
||||
echo "Creating snapshot..."
|
||||
vault operator raft snapshot save "$BACKUP_FILE"
|
||||
|
||||
if [ -f "$BACKUP_FILE" ]; then
|
||||
SIZE=$(du -h "$BACKUP_FILE" | cut -f1)
|
||||
echo "Snapshot created successfully!"
|
||||
echo "File: $BACKUP_FILE"
|
||||
echo "Size: $SIZE"
|
||||
else
|
||||
echo "Error: Snapshot creation failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify snapshot
|
||||
echo ""
|
||||
echo "Verifying snapshot..."
|
||||
vault operator raft snapshot inspect "$BACKUP_FILE" | head -20
|
||||
|
||||
# Cleanup old backups (keep last 7)
|
||||
echo ""
|
||||
echo "Cleaning up old backups (keeping last 7)..."
|
||||
ls -t "$OUTPUT_DIR"/vault-snapshot-*.snap 2>/dev/null | tail -n +8 | xargs -r rm -v
|
||||
|
||||
echo ""
|
||||
echo "========================================="
|
||||
echo "Backup complete"
|
||||
echo ""
|
||||
echo "To restore:"
|
||||
echo " vault operator raft snapshot restore $BACKUP_FILE"
|
||||
echo "========================================="
|
||||
@@ -0,0 +1,78 @@
|
||||
#!/bin/bash
|
||||
# Vault Initialization and Unseal Script
|
||||
# Usage: ./vault-init.sh [vault-addr]
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
export VAULT_ADDR="${1:-http://127.0.0.1:8200}"
|
||||
|
||||
echo "========================================="
|
||||
echo "Vault Initialization"
|
||||
echo "Address: $VAULT_ADDR"
|
||||
echo "========================================="
|
||||
echo ""
|
||||
|
||||
# Check if Vault is already initialized
|
||||
INIT_STATUS=$(vault status -format=json 2>/dev/null | jq -r '.initialized' || echo "error")
|
||||
|
||||
if [ "$INIT_STATUS" == "true" ]; then
|
||||
echo "Vault is already initialized"
|
||||
SEALED=$(vault status -format=json | jq -r '.sealed')
|
||||
if [ "$SEALED" == "true" ]; then
|
||||
echo "Vault is sealed. Use unseal keys to unseal."
|
||||
else
|
||||
echo "Vault is unsealed and ready."
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$INIT_STATUS" == "error" ]; then
|
||||
echo "Error: Cannot connect to Vault at $VAULT_ADDR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Initialize Vault
|
||||
echo "Initializing Vault..."
|
||||
echo ""
|
||||
|
||||
# Initialize with 5 key shares, 3 required to unseal
|
||||
INIT_OUTPUT=$(vault operator init \
|
||||
-key-shares=5 \
|
||||
-key-threshold=3 \
|
||||
-format=json)
|
||||
|
||||
# Save keys securely
|
||||
echo "$INIT_OUTPUT" > vault-init-keys.json
|
||||
chmod 600 vault-init-keys.json
|
||||
|
||||
echo "Vault initialized successfully!"
|
||||
echo ""
|
||||
echo "IMPORTANT: vault-init-keys.json contains your unseal keys and root token"
|
||||
echo "Store these securely and distribute unseal keys to different people"
|
||||
echo ""
|
||||
|
||||
# Extract keys
|
||||
UNSEAL_KEY_1=$(echo "$INIT_OUTPUT" | jq -r '.unseal_keys_b64[0]')
|
||||
UNSEAL_KEY_2=$(echo "$INIT_OUTPUT" | jq -r '.unseal_keys_b64[1]')
|
||||
UNSEAL_KEY_3=$(echo "$INIT_OUTPUT" | jq -r '.unseal_keys_b64[2]')
|
||||
ROOT_TOKEN=$(echo "$INIT_OUTPUT" | jq -r '.root_token')
|
||||
|
||||
# Unseal Vault
|
||||
echo "Unsealing Vault..."
|
||||
vault operator unseal "$UNSEAL_KEY_1" >/dev/null
|
||||
vault operator unseal "$UNSEAL_KEY_2" >/dev/null
|
||||
vault operator unseal "$UNSEAL_KEY_3" >/dev/null
|
||||
|
||||
echo "Vault unsealed successfully!"
|
||||
echo ""
|
||||
echo "Root Token: $ROOT_TOKEN"
|
||||
echo ""
|
||||
echo "Login with: vault login $ROOT_TOKEN"
|
||||
echo ""
|
||||
echo "========================================="
|
||||
echo "Next steps:"
|
||||
echo "1. Store unseal keys securely (different locations)"
|
||||
echo "2. Create AppRole or other auth methods"
|
||||
echo "3. Enable audit logging"
|
||||
echo "4. Configure secrets engines"
|
||||
echo "========================================="
|
||||
Reference in New Issue
Block a user