|
| 1 | +# Auto-Unsealing OpenBao Cluster |
| 2 | + |
| 3 | +This Facets module deploys OpenBao with automatic initialization and unsealing capabilities using configurable key shares and threshold. The module uses Helm to deploy OpenBao and implements auto-unseal functionality through Terraform null resources that execute API calls against the OpenBao cluster. |
| 4 | + |
| 5 | +## Features |
| 6 | + |
| 7 | +- **Helm-based Deployment**: Uses the official Vault Helm chart (compatible with OpenBao) |
| 8 | +- **Automatic Initialization**: Initializes OpenBao with configurable key shares and threshold |
| 9 | +- **Auto-Unseal**: Automatically unseals OpenBao using stored unseal keys |
| 10 | +- **Secure Key Storage**: Stores unseal keys and root token in Kubernetes secrets |
| 11 | +- **Flexible Storage Backends**: Supports file, Raft, and Azure storage backends |
| 12 | +- **High Availability**: Configurable replicas with Raft consensus |
| 13 | +- **TLS Support**: Optional TLS configuration with multiple certificate sources |
| 14 | +- **UI Access**: Optional web UI with ingress support |
| 15 | +- **Resource Management**: Configurable CPU/memory requests and limits |
| 16 | + |
| 17 | +## Architecture |
| 18 | + |
| 19 | +``` |
| 20 | +┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ |
| 21 | +│ Helm Release │ │ Null Resource │ │ Null Resource │ |
| 22 | +│ (OpenBao) │───▶│ (Initialize) │───▶│ (Auto-Unseal) │ |
| 23 | +└─────────────────┘ └─────────────────┘ └─────────────────┘ |
| 24 | + │ │ │ |
| 25 | + ▼ ▼ ▼ |
| 26 | +┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ |
| 27 | +│ OpenBao Pods │ │ K8s Secrets │ │ Unsealed │ |
| 28 | +│ │ │ - Unseal Keys │ │ OpenBao │ |
| 29 | +│ │ │ - Root Token │ │ Ready for Use │ |
| 30 | +└─────────────────┘ └─────────────────┘ └─────────────────┘ |
| 31 | +``` |
| 32 | + |
| 33 | +## Usage |
| 34 | + |
| 35 | +### Basic Configuration |
| 36 | + |
| 37 | +```yaml |
| 38 | +kind: openbao-cluster |
| 39 | +flavor: auto-unseal |
| 40 | +version: "1.0" |
| 41 | +spec: |
| 42 | + namespace: "openbao" |
| 43 | + release_name: "my-openbao" |
| 44 | + key_shares: 5 |
| 45 | + key_threshold: 3 |
| 46 | + storage_backend: |
| 47 | + type: "raft" |
| 48 | +``` |
| 49 | +
|
| 50 | +### Advanced Configuration |
| 51 | +
|
| 52 | +```yaml |
| 53 | +kind: openbao-cluster |
| 54 | +flavor: auto-unseal |
| 55 | +version: "1.0" |
| 56 | +spec: |
| 57 | + namespace: "openbao-prod" |
| 58 | + release_name: "openbao-ha" |
| 59 | + key_shares: 7 |
| 60 | + key_threshold: 4 |
| 61 | + |
| 62 | + # High availability setup |
| 63 | + server_replicas: 3 |
| 64 | + storage_backend: |
| 65 | + type: "raft" |
| 66 | + config: |
| 67 | + retry_join: |
| 68 | + - "openbao-ha-0.openbao-ha-internal:8201" |
| 69 | + - "openbao-ha-1.openbao-ha-internal:8201" |
| 70 | + - "openbao-ha-2.openbao-ha-internal:8201" |
| 71 | + |
| 72 | + # Resource configuration |
| 73 | + server_resources: |
| 74 | + requests: |
| 75 | + cpu: "1000m" |
| 76 | + memory: "512Mi" |
| 77 | + limits: |
| 78 | + cpu: "2000m" |
| 79 | + memory: "1Gi" |
| 80 | + |
| 81 | + # TLS and UI |
| 82 | + tls_config: |
| 83 | + enabled: true |
| 84 | + cert_source: "cert-manager" |
| 85 | + ui_enabled: true |
| 86 | + ingress_enabled: true |
| 87 | + |
| 88 | + # Custom timeout |
| 89 | + init_timeout: "600s" |
| 90 | +``` |
| 91 | +
|
| 92 | +## Configuration Reference |
| 93 | +
|
| 94 | +### Required Parameters |
| 95 | +
|
| 96 | +| Parameter | Type | Description | |
| 97 | +|-----------|------|-------------| |
| 98 | +| `key_shares` | integer | Number of key shares to generate (1-255) | |
| 99 | +| `key_threshold` | integer | Number of shares required to unseal (1-255, ≤ key_shares) | |
| 100 | +| `namespace` | string | Kubernetes namespace (created automatically) | |
| 101 | +| `release_name` | string | Helm release name | |
| 102 | +| `storage_backend` | object | Storage backend configuration | |
| 103 | + |
| 104 | +### Optional Parameters |
| 105 | + |
| 106 | +| Parameter | Type | Default | Description | |
| 107 | +|-----------|------|---------|-------------| |
| 108 | +| `helm_chart_version` | string | "0.28.1" | Vault Helm chart version | |
| 109 | +| `helm_repository` | string | "https://helm.releases.hashicorp.com" | Helm repository URL | |
| 110 | +| `secret_name_prefix` | string | "openbao" | Prefix for secrets | |
| 111 | +| `server_replicas` | integer | 1 | Number of OpenBao replicas | |
| 112 | +| `server_resources` | object | See defaults | CPU/memory requests and limits | |
| 113 | +| `ui_enabled` | boolean | true | Enable OpenBao web UI | |
| 114 | +| `ingress_enabled` | boolean | false | Create ingress for UI | |
| 115 | +| `tls_config` | object | See TLS section | TLS configuration | |
| 116 | +| `init_timeout` | string | "300s" | Initialization timeout | |
| 117 | + |
| 118 | +### Storage Backend Options |
| 119 | + |
| 120 | +#### Raft (Recommended for HA) |
| 121 | +```yaml |
| 122 | +storage_backend: |
| 123 | + type: "raft" |
| 124 | + config: |
| 125 | + retry_join: |
| 126 | + - "pod-0.service:8201" |
| 127 | + - "pod-1.service:8201" |
| 128 | +``` |
| 129 | + |
| 130 | +#### File (Single Instance) |
| 131 | +```yaml |
| 132 | +storage_backend: |
| 133 | + type: "file" |
| 134 | + config: |
| 135 | + path: "/openbao/data" |
| 136 | +``` |
| 137 | + |
| 138 | +#### Azure Key Vault |
| 139 | +```yaml |
| 140 | +storage_backend: |
| 141 | + type: "azure" |
| 142 | + config: |
| 143 | + tenant_id: "your-tenant-id" |
| 144 | + client_id: "your-client-id" |
| 145 | + client_secret: "your-secret" |
| 146 | + vault_name: "your-keyvault" |
| 147 | +``` |
| 148 | + |
| 149 | +### TLS Configuration |
| 150 | + |
| 151 | +```yaml |
| 152 | +tls_config: |
| 153 | + enabled: true |
| 154 | + cert_source: "self-signed" # or "cert-manager" or "manual" |
| 155 | +``` |
| 156 | + |
| 157 | +## Outputs |
| 158 | + |
| 159 | +The module provides the following outputs: |
| 160 | + |
| 161 | +### Default Output |
| 162 | +- **Connection details**: Service URLs, namespace, release name |
| 163 | +- **UI access**: UI URL if enabled |
| 164 | +- **Ingress details**: Ingress host if enabled |
| 165 | +- **Secrets**: Names of Kubernetes secrets containing keys and tokens |
| 166 | +- **Configuration**: Deployment configuration details |
| 167 | +- **Health check**: Health check endpoint URL |
| 168 | + |
| 169 | +### Additional Outputs |
| 170 | +- `root_token_secret_name`: Name of secret containing root token |
| 171 | +- `unseal_keys_secret_name`: Name of secret containing unseal keys |
| 172 | +- `namespace`: Deployment namespace |
| 173 | +- `service_details`: Service connection details for other apps |
| 174 | +- `helm_release`: Helm release information |
| 175 | + |
| 176 | +## Security Considerations |
| 177 | + |
| 178 | +### Unseal Keys Storage |
| 179 | +- Unseal keys are stored in Kubernetes secrets with base64 encoding |
| 180 | +- Secrets are labeled for easy identification and management |
| 181 | +- Consider implementing additional encryption for secrets at rest |
| 182 | + |
| 183 | +### Root Token Protection |
| 184 | +- Root token is stored in a separate Kubernetes secret |
| 185 | +- Rotate the root token regularly using OpenBao's token rotation features |
| 186 | +- Limit access to the root token secret using RBAC |
| 187 | + |
| 188 | +### Network Security |
| 189 | +- Use TLS for all communications when possible |
| 190 | +- Configure network policies to restrict pod-to-pod communication |
| 191 | +- Use ingress with proper authentication for UI access |
| 192 | + |
| 193 | +## Operations |
| 194 | + |
| 195 | +### Accessing OpenBao |
| 196 | +```bash |
| 197 | +# Get the root token |
| 198 | +kubectl get secret openbao-root-token -n openbao -o jsonpath='{.data.root-token}' | base64 -d |
| 199 | +
|
| 200 | +# Port forward to access UI |
| 201 | +kubectl port-forward svc/openbao-vault -n openbao 8200:8200 |
| 202 | +
|
| 203 | +# Access via browser |
| 204 | +open http://localhost:8200/ui |
| 205 | +``` |
| 206 | + |
| 207 | +### Manual Unseal (if needed) |
| 208 | +```bash |
| 209 | +# Get unseal keys |
| 210 | +kubectl get secret openbao-init-keys -n openbao -o jsonpath='{.data.unseal-keys}' | base64 -d | base64 -d |
| 211 | +
|
| 212 | +# Unseal manually (if auto-unseal fails) |
| 213 | +kubectl exec -n openbao openbao-vault-0 -- openbao operator unseal <key> |
| 214 | +``` |
| 215 | + |
| 216 | +### Backup and Recovery |
| 217 | +- Regularly backup the Kubernetes secrets containing unseal keys |
| 218 | +- Consider using Velero or similar tools for cluster-level backups |
| 219 | +- Test recovery procedures in non-production environments |
| 220 | + |
| 221 | +## Troubleshooting |
| 222 | + |
| 223 | +### Common Issues |
| 224 | + |
| 225 | +1. **Initialization Timeout** |
| 226 | + - Increase `init_timeout` value |
| 227 | + - Check pod logs: `kubectl logs -n <namespace> <pod-name>` |
| 228 | + - Verify network connectivity |
| 229 | + |
| 230 | +2. **Unseal Failures** |
| 231 | + - Check if secrets exist and contain valid keys |
| 232 | + - Verify key threshold is not greater than available keys |
| 233 | + - Check OpenBao pod status and logs |
| 234 | + |
| 235 | +3. **Helm Deployment Issues** |
| 236 | + - Verify Helm repository is accessible |
| 237 | + - Check chart version compatibility |
| 238 | + - Review Helm release status: `helm status <release-name> -n <namespace>` |
| 239 | + |
| 240 | +### Debugging Commands |
| 241 | +```bash |
| 242 | +# Check OpenBao status |
| 243 | +kubectl exec -n <namespace> <pod-name> -- openbao status |
| 244 | +
|
| 245 | +# View initialization logs |
| 246 | +kubectl logs -n <namespace> <pod-name> | grep init |
| 247 | +
|
| 248 | +# Check secrets |
| 249 | +kubectl get secrets -n <namespace> | grep openbao |
| 250 | +
|
| 251 | +# Describe Helm release |
| 252 | +helm get values <release-name> -n <namespace> |
| 253 | +``` |
| 254 | + |
| 255 | +## Prerequisites |
| 256 | + |
| 257 | +- Kubernetes cluster with RBAC enabled |
| 258 | +- Helm 3.x installed and configured |
| 259 | +- `kubectl` access to the target cluster |
| 260 | +- `jq` utility for JSON processing (required for auto-unseal scripts) |
| 261 | + |
| 262 | +## Limitations |
| 263 | + |
| 264 | +- Currently supports single-cluster deployments only |
| 265 | +- Auto-unseal requires `kubectl` and `jq` to be available in Terraform execution environment |
| 266 | +- Raft storage backend requires persistent volumes |
| 267 | +- TLS certificate management is basic (consider cert-manager for production) |
| 268 | + |
| 269 | +## Contributing |
| 270 | + |
| 271 | +This module follows Facets module development standards. When contributing: |
| 272 | + |
| 273 | +1. Maintain backward compatibility |
| 274 | +2. Update documentation for any new features |
| 275 | +3. Add appropriate validation rules |
| 276 | +4. Test with different storage backends |
| 277 | +5. Follow Terraform best practices |
| 278 | + |
| 279 | +## License |
| 280 | + |
| 281 | +This module is part of the Facets platform and follows the same licensing terms. |
0 commit comments