forked from tangled.org/core
this repo has no description

docs/spindle: describe openbao proxy dev and prod setups

Signed-off-by: Anirudh Oppiliappan <anirudh@tangled.sh>

authored by anirudh.fi and committed by Tangled ee1083d6 cccf0b0b

Changed files
+193 -38
docs
spindle
+193 -38
docs/spindle/openbao.md
··· 1 1 # spindle secrets with openbao 2 2 3 3 This document covers setting up Spindle to use OpenBao for secrets 4 - management instead of the default SQLite backend. 4 + management via OpenBao Proxy instead of the default SQLite backend. 5 + 6 + ## overview 7 + 8 + Spindle now uses OpenBao Proxy for secrets management. The proxy handles 9 + authentication automatically using AppRole credentials, while Spindle 10 + connects to the local proxy instead of directly to the OpenBao server. 11 + 12 + This approach provides better security, automatic token renewal, and 13 + simplified application code. 5 14 6 15 ## installation 7 16 8 17 Install OpenBao from nixpkgs: 9 18 10 19 ```bash 11 - nix-env -iA nixpkgs.openbao 20 + nix shell nixpkgs#openbao # for a local server 12 21 ``` 13 22 14 - ## local development setup 23 + ## setup 24 + 25 + The setup process can is documented for both local development and production. 26 + 27 + ### local development 15 28 16 29 Start OpenBao in dev mode: 17 30 18 31 ```bash 19 - bao server -dev 32 + bao server -dev -dev-root-token-id="root" -dev-listen-address=127.0.0.1:8201 20 33 ``` 21 34 22 - This starts OpenBao on `http://localhost:8200` with a root token. Save 23 - the root token from the output -- you'll need it. 35 + This starts OpenBao on `http://localhost:8201` with a root token. 24 36 25 37 Set up environment for bao CLI: 26 38 27 39 ```bash 28 40 export BAO_ADDR=http://localhost:8200 29 - export BAO_TOKEN=hvs.your-root-token-here 41 + export BAO_TOKEN=root 30 42 ``` 31 43 44 + ### production 45 + 46 + You would typically use a systemd service with a configuration file. Refer to 47 + [@tangled.sh/infra](https://tangled.sh/@tangled.sh/infra) for how this can be 48 + achieved using Nix. 49 + 50 + Then, initialize the bao server: 51 + ```bash 52 + bao operator init -key-shares=1 -key-threshold=1 53 + ``` 54 + 55 + This will print out an unseal key and a root key. Save them somewhere (like a password manager). Then unseal the vault to begin setting it up: 56 + ```bash 57 + bao operator unseal <unseal_key> 58 + ``` 59 + 60 + All steps below remain the same across both dev and production setups. 61 + 62 + ### configure openbao server 63 + 32 64 Create the spindle KV mount: 33 65 34 66 ```bash 35 67 bao secrets enable -path=spindle -version=2 kv 36 68 ``` 37 69 38 - Set up AppRole authentication: 70 + Set up AppRole authentication and policy: 39 71 40 72 Create a policy file `spindle-policy.hcl`: 41 73 42 74 ```hcl 75 + # Full access to spindle KV v2 data 43 76 path "spindle/data/*" { 44 - capabilities = ["create", "read", "update", "delete", "list"] 77 + capabilities = ["create", "read", "update", "delete"] 45 78 } 46 79 80 + # Access to metadata for listing and management 47 81 path "spindle/metadata/*" { 48 - capabilities = ["list", "read", "delete"] 82 + capabilities = ["list", "read", "delete", "update"] 49 83 } 50 84 51 - path "spindle/*" { 85 + # Allow listing at root level 86 + path "spindle/" { 52 87 capabilities = ["list"] 53 88 } 89 + 90 + # Required for connection testing and health checks 91 + path "auth/token/lookup-self" { 92 + capabilities = ["read"] 93 + } 54 94 ``` 55 95 56 96 Apply the policy and create an AppRole: ··· 61 101 bao write auth/approle/role/spindle \ 62 102 token_policies="spindle-policy" \ 63 103 token_ttl=1h \ 64 - token_max_ttl=4h 104 + token_max_ttl=4h \ 105 + bind_secret_id=true \ 106 + secret_id_ttl=0 \ 107 + secret_id_num_uses=0 65 108 ``` 66 109 67 110 Get the credentials: 68 111 69 112 ```bash 70 - bao read auth/approle/role/spindle/role-id 71 - bao write -f auth/approle/role/spindle/secret-id 113 + # Get role ID (static) 114 + ROLE_ID=$(bao read -field=role_id auth/approle/role/spindle/role-id) 115 + 116 + # Generate secret ID 117 + SECRET_ID=$(bao write -field=secret_id auth/approle/role/spindle/secret-id) 118 + 119 + echo "Role ID: $ROLE_ID" 120 + echo "Secret ID: $SECRET_ID" 121 + ``` 122 + 123 + ### create proxy configuration 124 + 125 + Create the credential files: 126 + 127 + ```bash 128 + # Create directory for OpenBao files 129 + mkdir -p /tmp/openbao 130 + 131 + # Save credentials 132 + echo "$ROLE_ID" > /tmp/openbao/role-id 133 + echo "$SECRET_ID" > /tmp/openbao/secret-id 134 + chmod 600 /tmp/openbao/role-id /tmp/openbao/secret-id 135 + ``` 136 + 137 + Create a proxy configuration file `/tmp/openbao/proxy.hcl`: 138 + 139 + ```hcl 140 + # OpenBao server connection 141 + vault { 142 + address = "http://localhost:8200" 143 + } 144 + 145 + # Auto-Auth using AppRole 146 + auto_auth { 147 + method "approle" { 148 + mount_path = "auth/approle" 149 + config = { 150 + role_id_file_path = "/tmp/openbao/role-id" 151 + secret_id_file_path = "/tmp/openbao/secret-id" 152 + } 153 + } 154 + 155 + # Optional: write token to file for debugging 156 + sink "file" { 157 + config = { 158 + path = "/tmp/openbao/token" 159 + mode = 0640 160 + } 161 + } 162 + } 163 + 164 + # Proxy listener for Spindle 165 + listener "tcp" { 166 + address = "127.0.0.1:8201" 167 + tls_disable = true 168 + } 169 + 170 + # Enable API proxy with auto-auth token 171 + api_proxy { 172 + use_auto_auth_token = true 173 + } 174 + 175 + # Enable response caching 176 + cache { 177 + use_auto_auth_token = true 178 + } 179 + 180 + # Logging 181 + log_level = "info" 72 182 ``` 73 183 74 - Configure Spindle: 184 + ### start the proxy 185 + 186 + Start OpenBao Proxy: 187 + 188 + ```bash 189 + bao proxy -config=/tmp/openbao/proxy.hcl 190 + ``` 191 + 192 + The proxy will authenticate with OpenBao and start listening on 193 + `127.0.0.1:8201`. 194 + 195 + ### configure spindle 75 196 76 197 Set these environment variables for Spindle: 77 198 78 199 ```bash 79 200 export SPINDLE_SERVER_SECRETS_PROVIDER=openbao 80 - export SPINDLE_SERVER_SECRETS_OPENBAO_ADDR=http://localhost:8200 81 - export SPINDLE_SERVER_SECRETS_OPENBAO_ROLE_ID=your-role-id-from-above 82 - export SPINDLE_SERVER_SECRETS_OPENBAO_SECRET_ID=your-secret-id-from-above 201 + export SPINDLE_SERVER_SECRETS_OPENBAO_PROXY_ADDR=http://127.0.0.1:8201 83 202 export SPINDLE_SERVER_SECRETS_OPENBAO_MOUNT=spindle 84 203 ``` 85 204 86 205 Start Spindle: 87 206 88 - Spindle will now use OpenBao for secrets storage with automatic token 89 - renewal. 207 + Spindle will now connect to the local proxy, which handles all 208 + authentication automatically. 209 + 210 + ## production setup for proxy 211 + 212 + For production, you'll want to run the proxy as a service: 213 + 214 + Place your production configuration in `/etc/openbao/proxy.hcl` with 215 + proper TLS settings for the vault connection. 90 216 91 217 ## verifying setup 92 218 93 - List all secrets: 219 + Test the proxy directly: 94 220 95 221 ```bash 96 - bao kv list spindle/ 222 + # Check proxy health 223 + curl -H "X-Vault-Request: true" http://127.0.0.1:8201/v1/sys/health 224 + 225 + # Test token lookup through proxy 226 + curl -H "X-Vault-Request: true" http://127.0.0.1:8201/v1/auth/token/lookup-self 97 227 ``` 98 228 99 - Add a test secret via Spindle API, then check it exists: 229 + Test OpenBao operations through the server: 100 230 101 231 ```bash 232 + # List all secrets 233 + bao kv list spindle/ 234 + 235 + # Add a test secret via Spindle API, then check it exists 102 236 bao kv list spindle/repos/ 103 - ``` 104 237 105 - Get a specific secret: 106 - 107 - ```bash 238 + # Get a specific secret 108 239 bao kv get spindle/repos/your_repo_path/SECRET_NAME 109 240 ``` 110 241 111 242 ## how it works 112 243 244 + - Spindle connects to OpenBao Proxy on localhost (typically port 8200 or 8201) 245 + - The proxy authenticates with OpenBao using AppRole credentials 246 + - All Spindle requests go through the proxy, which injects authentication tokens 113 247 - Secrets are stored at `spindle/repos/{sanitized_repo_path}/{secret_key}` 114 - - Each repository gets its own namespace 115 - - Repository paths like `at://did:plc:alice/myrepo` become 116 - `at_did_plc_alice_myrepo` 117 - - The system automatically handles token renewal using AppRole 118 - authentication 119 - - On shutdown, Spindle cleanly stops the token renewal process 248 + - Repository paths like `did:plc:alice/myrepo` become `did_plc_alice_myrepo` 249 + - The proxy handles all token renewal automatically 250 + - Spindle no longer manages tokens or authentication directly 120 251 121 252 ## troubleshooting 122 253 123 - **403 errors**: Check that your BAO_TOKEN is set and the spindle mount 124 - exists 254 + **Connection refused**: Check that the OpenBao Proxy is running and 255 + listening on the configured address. 256 + 257 + **403 errors**: Verify the AppRole credentials are correct and the policy 258 + has the necessary permissions. 125 259 126 260 **404 route errors**: The spindle KV mount probably doesn't exist - run 127 - the mount creation step again 261 + the mount creation step again. 128 262 129 - **Token expired**: The AppRole system should handle this automatically, 130 - but you can check token status with `bao token lookup` 263 + **Proxy authentication failures**: Check the proxy logs and verify the 264 + role-id and secret-id files are readable and contain valid credentials. 265 + 266 + **Secret not found after writing**: This can indicate policy permission 267 + issues. Verify the policy includes both `spindle/data/*` and 268 + `spindle/metadata/*` paths with appropriate capabilities. 269 + 270 + Check proxy logs: 271 + 272 + ```bash 273 + # If running as systemd service 274 + journalctl -u openbao-proxy -f 275 + 276 + # If running directly, check the console output 277 + ``` 278 + 279 + Test AppRole authentication manually: 280 + 281 + ```bash 282 + bao write auth/approle/login \ 283 + role_id="$(cat /tmp/openbao/role-id)" \ 284 + secret_id="$(cat /tmp/openbao/secret-id)" 285 + ```