docs: update auth documentation for token-only mode
- commit
- 4a0fe8feb83ed03eb6d10a2ea288aadb50b0dcfe
- author
- brice · · 2026-03-22 06:37 UTC
- committer
- brice · · 2026-03-22 17:35 UTC
- parent
- 8d39436
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
5 files · +165 -119
M docs/cli/auth.md +39 -75
| @@ -1,6 +1,6 @@ | |||
| 1 | 1 | # Authentication Commands | |
| 2 | 2 | ||
| 3 | - | Manage Gordon server authentication tokens and passwords. | |
| 3 | + | Manage Gordon server authentication tokens. | |
| 4 | 4 | ||
| 5 | 5 | ## gordon auth | |
| 6 | 6 | ||
| @@ -12,14 +12,13 @@ Manage Gordon server authentication tokens and passwords. | |||
| 12 | 12 | | `token generate` | Generate a new JWT token | | |
| 13 | 13 | | `token list` | List all stored tokens | | |
| 14 | 14 | | `token revoke` | Revoke a token by ID (use `--all` to revoke all tokens) | | |
| 15 | - | | `password hash` | Generate bcrypt password hash | | |
| 16 | 15 | | `internal` | Show internal registry credentials | | |
| 17 | 16 | ||
| 18 | 17 | --- | |
| 19 | 18 | ||
| 20 | 19 | ## gordon auth login | |
| 21 | 20 | ||
| 22 | - | Authenticate with a remote Gordon server using password authentication or a pre-generated token. | |
| 21 | + | Authenticate with a remote Gordon server using a pre-generated token. | |
| 23 | 22 | ||
| 24 | 23 | ```bash | |
| 25 | 24 | gordon auth login [options] | |
| @@ -30,34 +29,22 @@ gordon auth login [options] | |||
| 30 | 29 | | Option | Description | | |
| 31 | 30 | |--------|-------------| | |
| 32 | 31 | | `-r, --remote` | Remote to authenticate with (defaults to active remote) | | |
| 33 | - | | `-u, --username` | Username for authentication | | |
| 34 | - | | `-p, --password` | Password for authentication | | |
| 35 | 32 | | `-t, --token` | Authentication token to store for the remote | | |
| 36 | 33 | ||
| 37 | 34 | ### Description | |
| 38 | 35 | ||
| 39 | - | This command prompts for your username and password, authenticates with the remote server's `/auth/password` endpoint, and stores the returned token. When [pass](https://www.passwordstore.org/) is available, the token is stored encrypted at `gordon/remotes/<name>/token` and any plaintext token fields are cleared from `remotes.toml`. When `pass` is unavailable, the token is stored in plaintext in `remotes.toml` with a warning. | |
| 36 | + | This command stores a pre-generated token for use with a remote Gordon server. When [pass](https://www.passwordstore.org/) is available, the token is stored encrypted at `gordon/remotes/<name>/token` and any plaintext token fields are cleared from `remotes.toml`. When `pass` is unavailable, the token is stored in plaintext in `remotes.toml` with a warning. | |
| 40 | 37 | ||
| 41 | - | If you provide `--token`, the token is stored directly and verified against `/admin/status` on a best-effort basis. | |
| 42 | - | ||
| 43 | - | The token is a long-lived JWT (7 days) that's used for subsequent CLI operations against the remote. | |
| 44 | - | ||
| 45 | - | > **Note:** For token-only servers, you can pass `--token` here or use `gordon remotes set-token`. | |
| 38 | + | The token is verified against `/admin/status` on a best-effort basis. | |
| 46 | 39 | ||
| 47 | 40 | ### Examples | |
| 48 | 41 | ||
| 49 | 42 | ```bash | |
| 50 | - | # Login using active remote | |
| 51 | - | gordon auth login | |
| 52 | - | ||
| 53 | - | # Login to specific remote | |
| 54 | - | gordon auth login --remote prod | |
| 55 | - | ||
| 56 | - | # Pre-fill username | |
| 57 | - | gordon auth login --username admin | |
| 58 | - | ||
| 59 | - | # Store a pre-generated token | |
| 43 | + | # Store a token for the active remote | |
| 60 | 44 | gordon auth login --token <token> | |
| 45 | + | ||
| 46 | + | # Store a token for a specific remote | |
| 47 | + | gordon auth login --remote prod --token <token> | |
| 61 | 48 | ``` | |
| 62 | 49 | ||
| 63 | 50 | ### Output | |
| @@ -65,26 +52,14 @@ gordon auth login --token <token> | |||
| 65 | 52 | When `pass` is available: | |
| 66 | 53 | ||
| 67 | 54 | ```text | |
| 68 | - | Username: admin | |
| 69 | - | Password: ******** | |
| 70 | - | Authenticating with prod... | |
| 71 | - | ||
| 72 | - | ✓ Authentication successful! | |
| 73 | 55 | Token stored in pass for remote 'prod' | |
| 74 | - | Expires in: 604800 seconds | |
| 75 | 56 | ``` | |
| 76 | 57 | ||
| 77 | 58 | When `pass` is not available: | |
| 78 | 59 | ||
| 79 | 60 | ```text | |
| 80 | - | Username: admin | |
| 81 | - | Password: ******** | |
| 82 | - | Authenticating with prod... | |
| 83 | - | ||
| 84 | 61 | Warning: 'pass' not available. Storing token in plaintext config. Consider installing pass (https://www.passwordstore.org/) for secure token storage. | |
| 85 | - | ✓ Authentication successful! | |
| 86 | 62 | Token stored for remote 'prod' | |
| 87 | - | Expires in: 604800 seconds | |
| 88 | 63 | ``` | |
| 89 | 64 | ||
| 90 | 65 | --- | |
| @@ -121,6 +96,18 @@ Compound durations are also supported: `1y6M`, `2w3d`, `1d12h` | |||
| 121 | 96 | ||
| 122 | 97 | Standard Go durations also work: `24h`, `30m`, `1h30m` | |
| 123 | 98 | ||
| 99 | + | ### Scopes | |
| 100 | + | ||
| 101 | + | Registry scopes: `push`, `pull`, `push,pull` | |
| 102 | + | ||
| 103 | + | Admin scopes: `admin:*:*`, `admin:routes:read`, `admin:routes:write`, `admin:config:read`, `admin:config:write`, `admin:status:read`, `admin:secrets:read`, `admin:secrets:write` | |
| 104 | + | ||
| 105 | + | Combine scopes with commas: | |
| 106 | + | ||
| 107 | + | ```bash | |
| 108 | + | gordon auth token generate --subject admin --scopes "push,pull,admin:*:*" --expiry 0 | |
| 109 | + | ``` | |
| 110 | + | ||
| 124 | 111 | ### Examples | |
| 125 | 112 | ||
| 126 | 113 | ```bash | |
| @@ -136,8 +123,11 @@ gordon auth token generate --subject builder --scopes push --expiry 1y | |||
| 136 | 123 | # Temporary token (24 hours) | |
| 137 | 124 | gordon auth token generate --subject temp --expiry 24h | |
| 138 | 125 | ||
| 139 | - | # Token for 6 months | |
| 140 | - | gordon auth token generate --subject deploy --expiry 6M | |
| 126 | + | # Full admin access token | |
| 127 | + | gordon auth token generate --subject admin --scopes "push,pull,admin:*:*" --expiry 6M | |
| 128 | + | ||
| 129 | + | # Read-only admin token | |
| 130 | + | gordon auth token generate --subject monitor --scopes "admin:status:read" --expiry 30d | |
| 141 | 131 | ``` | |
| 142 | 132 | ||
| 143 | 133 | ### Output | |
| @@ -199,33 +189,6 @@ Token a1b2c3d4-e5f6-7890-abcd-ef1234567890 has been revoked. | |||
| 199 | 189 | ||
| 200 | 190 | --- | |
| 201 | 191 | ||
| 202 | - | ## gordon auth password hash | |
| 203 | - | ||
| 204 | - | Generate a bcrypt hash for password authentication. | |
| 205 | - | ||
| 206 | - | ```bash | |
| 207 | - | gordon auth password hash | |
| 208 | - | ``` | |
| 209 | - | ||
| 210 | - | Interactively prompts for a password and outputs the bcrypt hash. | |
| 211 | - | ||
| 212 | - | ### Output | |
| 213 | - | ||
| 214 | - | ``` | |
| 215 | - | Enter password: ******** | |
| 216 | - | ||
| 217 | - | Bcrypt hash (store in your secrets backend): | |
| 218 | - | $2a$10$N9qo8uLOickgx2ZMRZoMye... | |
| 219 | - | ||
| 220 | - | Then reference the path in your config: | |
| 221 | - | [auth] | |
| 222 | - | username = "deploy" | |
| 223 | - | password_hash = "gordon/auth/password_hash" | |
| 224 | - | token_secret = "gordon/auth/token_secret" | |
| 225 | - | ``` | |
| 226 | - | ||
| 227 | - | --- | |
| 228 | - | ||
| 229 | 192 | ## gordon auth internal | |
| 230 | 193 | ||
| 231 | 194 | Display the auto-generated internal registry credentials. | |
| @@ -272,6 +235,14 @@ Usage: | |||
| 272 | 235 | | `push` | Push images to registry | | |
| 273 | 236 | | `pull` | Pull images from registry | | |
| 274 | 237 | | `push,pull` | Both push and pull (default) | | |
| 238 | + | | `admin:*:*` | Full admin access | | |
| 239 | + | | `admin:routes:read` | Read-only routes access | | |
| 240 | + | | `admin:routes:write` | Routes write access | | |
| 241 | + | | `admin:config:read` | Read-only config access | | |
| 242 | + | | `admin:config:write` | Config write access | | |
| 243 | + | | `admin:status:read` | Read-only status/health | | |
| 244 | + | | `admin:secrets:read` | List secret keys | | |
| 245 | + | | `admin:secrets:write` | Set/delete secrets | | |
| 275 | 246 | ||
| 276 | 247 | ## Token Expiry Formats | |
| 277 | 248 | ||
| @@ -293,8 +264,8 @@ Usage: | |||
| 293 | 264 | gordon auth token generate --subject ci-bot --scopes push,pull --expiry 0 | |
| 294 | 265 | ||
| 295 | 266 | # Save token as CI secret | |
| 296 | - | # GitHub: Settings → Secrets → New repository secret | |
| 297 | - | # GitLab: Settings → CI/CD → Variables | |
| 267 | + | # GitHub: Settings > Secrets > New repository secret | |
| 268 | + | # GitLab: Settings > CI/CD > Variables | |
| 298 | 269 | ``` | |
| 299 | 270 | ||
| 300 | 271 | ### Docker Login | |
| @@ -319,17 +290,9 @@ gordon auth token generate --subject ci-bot --expiry 0 | |||
| 319 | 290 | gordon auth token revoke <old-token-id> | |
| 320 | 291 | ``` | |
| 321 | 292 | ||
| 322 | - | ### Password Setup | |
| 293 | + | ### Token-only Setup | |
| 323 | 294 | ||
| 324 | 295 | ```bash | |
| 325 | - | # Generate hash | |
| 326 | - | gordon auth password hash | |
| 327 | - | # Enter: mypassword | |
| 328 | - | ||
| 329 | - | # Store in pass | |
| 330 | - | pass insert gordon/auth/password_hash | |
| 331 | - | # Paste: $2a$10$... | |
| 332 | - | ||
| 333 | 296 | # Create token secret | |
| 334 | 297 | pass insert gordon/auth/token_secret | |
| 335 | 298 | # Enter a random 32+ character string | |
| @@ -338,9 +301,10 @@ pass insert gordon/auth/token_secret | |||
| 338 | 301 | [auth] | |
| 339 | 302 | enabled = true | |
| 340 | 303 | secrets_backend = "pass" | |
| 341 | - | username = "deploy" | |
| 342 | - | password_hash = "gordon/auth/password_hash" | |
| 343 | 304 | token_secret = "gordon/auth/token_secret" | |
| 305 | + | ||
| 306 | + | # Generate a deploy token | |
| 307 | + | gordon auth token generate --subject deploy --scopes "push,pull" --expiry 0 | |
| 344 | 308 | ``` | |
| 345 | 309 | ||
| 346 | 310 | ## Related | |
| @@ -1,6 +1,6 @@ | |||||
| 1 | # Authentication Commands | 1 | # Authentication Commands | ||
| 2 | 2 | ||||
| 3 | - | Manage Gordon server authentication tokens and passwords. | 3 | + | Manage Gordon server authentication tokens. |
| 4 | 4 | ||||
| 5 | ## gordon auth | 5 | ## gordon auth | ||
| 6 | 6 | ||||
| @@ -12,14 +12,13 @@ Manage Gordon server authentication tokens and passwords. | |||||
| 12 | | `token generate` | Generate a new JWT token | | 12 | | `token generate` | Generate a new JWT token | | ||
| 13 | | `token list` | List all stored tokens | | 13 | | `token list` | List all stored tokens | | ||
| 14 | | `token revoke` | Revoke a token by ID (use `--all` to revoke all tokens) | | 14 | | `token revoke` | Revoke a token by ID (use `--all` to revoke all tokens) | | ||
| 15 | - | | `password hash` | Generate bcrypt password hash | | |||
| 16 | | `internal` | Show internal registry credentials | | 15 | | `internal` | Show internal registry credentials | | ||
| 17 | 16 | ||||
| 18 | --- | 17 | --- | ||
| 19 | 18 | ||||
| 20 | ## gordon auth login | 19 | ## gordon auth login | ||
| 21 | 20 | ||||
| 22 | - | Authenticate with a remote Gordon server using password authentication or a pre-generated token. | 21 | + | Authenticate with a remote Gordon server using a pre-generated token. |
| 23 | 22 | ||||
| 24 | ```bash | 23 | ```bash | ||
| 25 | gordon auth login [options] | 24 | gordon auth login [options] | ||
| @@ -30,34 +29,22 @@ gordon auth login [options] | |||||
| 30 | | Option | Description | | 29 | | Option | Description | | ||
| 31 | |--------|-------------| | 30 | |--------|-------------| | ||
| 32 | | `-r, --remote` | Remote to authenticate with (defaults to active remote) | | 31 | | `-r, --remote` | Remote to authenticate with (defaults to active remote) | | ||
| 33 | - | | `-u, --username` | Username for authentication | | |||
| 34 | - | | `-p, --password` | Password for authentication | | |||
| 35 | | `-t, --token` | Authentication token to store for the remote | | 32 | | `-t, --token` | Authentication token to store for the remote | | ||
| 36 | 33 | ||||
| 37 | ### Description | 34 | ### Description | ||
| 38 | 35 | ||||
| 39 | - | This command prompts for your username and password, authenticates with the remote server's `/auth/password` endpoint, and stores the returned token. When [pass](https://www.passwordstore.org/) is available, the token is stored encrypted at `gordon/remotes/<name>/token` and any plaintext token fields are cleared from `remotes.toml`. When `pass` is unavailable, the token is stored in plaintext in `remotes.toml` with a warning. | 36 | + | This command stores a pre-generated token for use with a remote Gordon server. When [pass](https://www.passwordstore.org/) is available, the token is stored encrypted at `gordon/remotes/<name>/token` and any plaintext token fields are cleared from `remotes.toml`. When `pass` is unavailable, the token is stored in plaintext in `remotes.toml` with a warning. |
| 40 | 37 | ||||
| 41 | - | If you provide `--token`, the token is stored directly and verified against `/admin/status` on a best-effort basis. | 38 | + | The token is verified against `/admin/status` on a best-effort basis. |
| 42 | - | ||||
| 43 | - | The token is a long-lived JWT (7 days) that's used for subsequent CLI operations against the remote. | |||
| 44 | - | ||||
| 45 | - | > **Note:** For token-only servers, you can pass `--token` here or use `gordon remotes set-token`. | |||
| 46 | 39 | ||||
| 47 | ### Examples | 40 | ### Examples | ||
| 48 | 41 | ||||
| 49 | ```bash | 42 | ```bash | ||
| 50 | - | # Login using active remote | 43 | + | # Store a token for the active remote |
| 51 | - | gordon auth login | |||
| 52 | - | ||||
| 53 | - | # Login to specific remote | |||
| 54 | - | gordon auth login --remote prod | |||
| 55 | - | ||||
| 56 | - | # Pre-fill username | |||
| 57 | - | gordon auth login --username admin | |||
| 58 | - | ||||
| 59 | - | # Store a pre-generated token | |||
| 60 | gordon auth login --token <token> | 44 | gordon auth login --token <token> | ||
| 45 | + | ||||
| 46 | + | # Store a token for a specific remote | |||
| 47 | + | gordon auth login --remote prod --token <token> | |||
| 61 | ``` | 48 | ``` | ||
| 62 | 49 | ||||
| 63 | ### Output | 50 | ### Output | ||
| @@ -65,26 +52,14 @@ gordon auth login --token <token> | |||||
| 65 | When `pass` is available: | 52 | When `pass` is available: | ||
| 66 | 53 | ||||
| 67 | ```text | 54 | ```text | ||
| 68 | - | Username: admin | |||
| 69 | - | Password: ******** | |||
| 70 | - | Authenticating with prod... | |||
| 71 | - | ||||
| 72 | - | ✓ Authentication successful! | |||
| 73 | Token stored in pass for remote 'prod' | 55 | Token stored in pass for remote 'prod' | ||
| 74 | - | Expires in: 604800 seconds | |||
| 75 | ``` | 56 | ``` | ||
| 76 | 57 | ||||
| 77 | When `pass` is not available: | 58 | When `pass` is not available: | ||
| 78 | 59 | ||||
| 79 | ```text | 60 | ```text | ||
| 80 | - | Username: admin | |||
| 81 | - | Password: ******** | |||
| 82 | - | Authenticating with prod... | |||
| 83 | - | ||||
| 84 | Warning: 'pass' not available. Storing token in plaintext config. Consider installing pass (https://www.passwordstore.org/) for secure token storage. | 61 | Warning: 'pass' not available. Storing token in plaintext config. Consider installing pass (https://www.passwordstore.org/) for secure token storage. | ||
| 85 | - | ✓ Authentication successful! | |||
| 86 | Token stored for remote 'prod' | 62 | Token stored for remote 'prod' | ||
| 87 | - | Expires in: 604800 seconds | |||
| 88 | ``` | 63 | ``` | ||
| 89 | 64 | ||||
| 90 | --- | 65 | --- | ||
| @@ -121,6 +96,18 @@ Compound durations are also supported: `1y6M`, `2w3d`, `1d12h` | |||||
| 121 | 96 | ||||
| 122 | Standard Go durations also work: `24h`, `30m`, `1h30m` | 97 | Standard Go durations also work: `24h`, `30m`, `1h30m` | ||
| 123 | 98 | ||||
| 99 | + | ### Scopes | |||
| 100 | + | ||||
| 101 | + | Registry scopes: `push`, `pull`, `push,pull` | |||
| 102 | + | ||||
| 103 | + | Admin scopes: `admin:*:*`, `admin:routes:read`, `admin:routes:write`, `admin:config:read`, `admin:config:write`, `admin:status:read`, `admin:secrets:read`, `admin:secrets:write` | |||
| 104 | + | ||||
| 105 | + | Combine scopes with commas: | |||
| 106 | + | ||||
| 107 | + | ```bash | |||
| 108 | + | gordon auth token generate --subject admin --scopes "push,pull,admin:*:*" --expiry 0 | |||
| 109 | + | ``` | |||
| 110 | + | ||||
| 124 | ### Examples | 111 | ### Examples | ||
| 125 | 112 | ||||
| 126 | ```bash | 113 | ```bash | ||
| @@ -136,8 +123,11 @@ gordon auth token generate --subject builder --scopes push --expiry 1y | |||||
| 136 | # Temporary token (24 hours) | 123 | # Temporary token (24 hours) | ||
| 137 | gordon auth token generate --subject temp --expiry 24h | 124 | gordon auth token generate --subject temp --expiry 24h | ||
| 138 | 125 | ||||
| 139 | - | # Token for 6 months | 126 | + | # Full admin access token |
| 140 | - | gordon auth token generate --subject deploy --expiry 6M | 127 | + | gordon auth token generate --subject admin --scopes "push,pull,admin:*:*" --expiry 6M |
| 128 | + | ||||
| 129 | + | # Read-only admin token | |||
| 130 | + | gordon auth token generate --subject monitor --scopes "admin:status:read" --expiry 30d | |||
| 141 | ``` | 131 | ``` | ||
| 142 | 132 | ||||
| 143 | ### Output | 133 | ### Output | ||
| @@ -199,33 +189,6 @@ Token a1b2c3d4-e5f6-7890-abcd-ef1234567890 has been revoked. | |||||
| 199 | 189 | ||||
| 200 | --- | 190 | --- | ||
| 201 | 191 | ||||
| 202 | - | ## gordon auth password hash | |||
| 203 | - | ||||
| 204 | - | Generate a bcrypt hash for password authentication. | |||
| 205 | - | ||||
| 206 | - | ```bash | |||
| 207 | - | gordon auth password hash | |||
| 208 | - | ``` | |||
| 209 | - | ||||
| 210 | - | Interactively prompts for a password and outputs the bcrypt hash. | |||
| 211 | - | ||||
| 212 | - | ### Output | |||
| 213 | - | ||||
| 214 | - | ``` | |||
| 215 | - | Enter password: ******** | |||
| 216 | - | ||||
| 217 | - | Bcrypt hash (store in your secrets backend): | |||
| 218 | - | $2a$10$N9qo8uLOickgx2ZMRZoMye... | |||
| 219 | - | ||||
| 220 | - | Then reference the path in your config: | |||
| 221 | - | [auth] | |||
| 222 | - | username = "deploy" | |||
| 223 | - | password_hash = "gordon/auth/password_hash" | |||
| 224 | - | token_secret = "gordon/auth/token_secret" | |||
| 225 | - | ``` | |||
| 226 | - | ||||
| 227 | - | --- | |||
| 228 | - | ||||
| 229 | ## gordon auth internal | 192 | ## gordon auth internal | ||
| 230 | 193 | ||||
| 231 | Display the auto-generated internal registry credentials. | 194 | Display the auto-generated internal registry credentials. | ||
| @@ -272,6 +235,14 @@ Usage: | |||||
| 272 | | `push` | Push images to registry | | 235 | | `push` | Push images to registry | | ||
| 273 | | `pull` | Pull images from registry | | 236 | | `pull` | Pull images from registry | | ||
| 274 | | `push,pull` | Both push and pull (default) | | 237 | | `push,pull` | Both push and pull (default) | | ||
| 238 | + | | `admin:*:*` | Full admin access | | |||
| 239 | + | | `admin:routes:read` | Read-only routes access | | |||
| 240 | + | | `admin:routes:write` | Routes write access | | |||
| 241 | + | | `admin:config:read` | Read-only config access | | |||
| 242 | + | | `admin:config:write` | Config write access | | |||
| 243 | + | | `admin:status:read` | Read-only status/health | | |||
| 244 | + | | `admin:secrets:read` | List secret keys | | |||
| 245 | + | | `admin:secrets:write` | Set/delete secrets | | |||
| 275 | 246 | ||||
| 276 | ## Token Expiry Formats | 247 | ## Token Expiry Formats | ||
| 277 | 248 | ||||
| @@ -293,8 +264,8 @@ Usage: | |||||
| 293 | gordon auth token generate --subject ci-bot --scopes push,pull --expiry 0 | 264 | gordon auth token generate --subject ci-bot --scopes push,pull --expiry 0 | ||
| 294 | 265 | ||||
| 295 | # Save token as CI secret | 266 | # Save token as CI secret | ||
| 296 | - | # GitHub: Settings → Secrets → New repository secret | 267 | + | # GitHub: Settings > Secrets > New repository secret |
| 297 | - | # GitLab: Settings → CI/CD → Variables | 268 | + | # GitLab: Settings > CI/CD > Variables |
| 298 | ``` | 269 | ``` | ||
| 299 | 270 | ||||
| 300 | ### Docker Login | 271 | ### Docker Login | ||
| @@ -319,17 +290,9 @@ gordon auth token generate --subject ci-bot --expiry 0 | |||||
| 319 | gordon auth token revoke <old-token-id> | 290 | gordon auth token revoke <old-token-id> | ||
| 320 | ``` | 291 | ``` | ||
| 321 | 292 | ||||
| 322 | - | ### Password Setup | 293 | + | ### Token-only Setup |
| 323 | 294 | ||||
| 324 | ```bash | 295 | ```bash | ||
| 325 | - | # Generate hash | |||
| 326 | - | gordon auth password hash | |||
| 327 | - | # Enter: mypassword | |||
| 328 | - | ||||
| 329 | - | # Store in pass | |||
| 330 | - | pass insert gordon/auth/password_hash | |||
| 331 | - | # Paste: $2a$10$... | |||
| 332 | - | ||||
| 333 | # Create token secret | 296 | # Create token secret | ||
| 334 | pass insert gordon/auth/token_secret | 297 | pass insert gordon/auth/token_secret | ||
| 335 | # Enter a random 32+ character string | 298 | # Enter a random 32+ character string | ||
| @@ -338,9 +301,10 @@ pass insert gordon/auth/token_secret | |||||
| 338 | [auth] | 301 | [auth] | ||
| 339 | enabled = true | 302 | enabled = true | ||
| 340 | secrets_backend = "pass" | 303 | secrets_backend = "pass" | ||
| 341 | - | username = "deploy" | |||
| 342 | - | password_hash = "gordon/auth/password_hash" | |||
| 343 | token_secret = "gordon/auth/token_secret" | 304 | token_secret = "gordon/auth/token_secret" | ||
| 305 | + | ||||
| 306 | + | # Generate a deploy token | |||
| 307 | + | gordon auth token generate --subject deploy --scopes "push,pull" --expiry 0 | |||
| 344 | ``` | 308 | ``` | ||
| 345 | 309 | ||||
| 346 | ## Related | 310 | ## Related | ||
M docs/config/auth.md +24 -40
| @@ -4,29 +4,18 @@ Configure authentication for the Gordon registry and Admin API. | |||
| 4 | 4 | ||
| 5 | 5 | Authentication is enabled by default. Gordon will not start without a valid `token_secret` (or `GORDON_AUTH_TOKEN_SECRET`). | |
| 6 | 6 | ||
| 7 | - | ## Pick a Mode | |
| 7 | + | ## Configuration | |
| 8 | 8 | ||
| 9 | - | ### Token-only (recommended for CI/CD) | |
| 9 | + | Gordon uses token-only authentication. All registry and Admin API access is controlled through JWT tokens. | |
| 10 | 10 | ||
| 11 | 11 | ```toml | |
| 12 | 12 | [auth] | |
| 13 | 13 | secrets_backend = "pass" | |
| 14 | 14 | token_secret = "gordon/auth/token_secret" | |
| 15 | 15 | token_expiry = "30d" | |
| 16 | + | access_token_ttl = "15m" | |
| 16 | 17 | ``` | |
| 17 | 18 | ||
| 18 | - | ### Password + Token (interactive + CI/CD) | |
| 19 | - | ||
| 20 | - | ```toml | |
| 21 | - | [auth] | |
| 22 | - | secrets_backend = "pass" | |
| 23 | - | username = "deploy" | |
| 24 | - | password_hash = "gordon/auth/password_hash" | |
| 25 | - | token_secret = "gordon/auth/token_secret" | |
| 26 | - | ``` | |
| 27 | - | ||
| 28 | - | Token auth always works. Adding `username` + `password_hash` enables interactive login. | |
| 29 | - | ||
| 30 | 19 | ## Options | |
| 31 | 20 | ||
| 32 | 21 | | Option | Type | Default | Description | | |
| @@ -35,12 +24,11 @@ Token auth always works. Adding `username` + `password_hash` enables interactive | |||
| 35 | 24 | | `secrets_backend` | string | `"unsafe"` | Secrets backend: `"pass"`, `"sops"`, or `"unsafe"` | | |
| 36 | 25 | | `token_secret` | string | - | **Required.** Path to JWT signing secret in secrets backend | | |
| 37 | 26 | | `token_expiry` | string | `"30d"` | Token validity duration (0 = never expires) | | |
| 38 | - | | `username` | string | - | Username for password auth (optional) | | |
| 39 | - | | `password_hash` | string | - | Path to bcrypt hash in secrets backend (optional) | | |
| 27 | + | | `access_token_ttl` | string | `"15m"` | Lifetime of ephemeral access tokens issued by `/auth/token` | | |
| 40 | 28 | ||
| 41 | 29 | ## Secrets Backends | |
| 42 | 30 | ||
| 43 | - | `token_secret` and `password_hash` are read through the configured backend: | |
| 31 | + | `token_secret` is read through the configured backend: | |
| 44 | 32 | ||
| 45 | 33 | | Backend | Description | | |
| 46 | 34 | | --------- | ------------- | | |
| @@ -52,7 +40,7 @@ See [Secret Providers](./secrets.md) for setup details. | |||
| 52 | 40 | ||
| 53 | 41 | ## Environment Variable | |
| 54 | 42 | ||
| 55 | - | `GORDON_AUTH_TOKEN_SECRET` overrides `token_secret` in the config. If you don’t set the env var, `token_secret` is loaded from the configured secrets backend (including `pass`). | |
| 43 | + | `GORDON_AUTH_TOKEN_SECRET` overrides `token_secret` in the config. If you don't set the env var, `token_secret` is loaded from the configured secrets backend (including `pass`). | |
| 56 | 44 | ||
| 57 | 45 | ```bash | |
| 58 | 46 | export GORDON_AUTH_TOKEN_SECRET="your-32-character-secret-here" | |
| @@ -61,8 +49,6 @@ gordon serve | |||
| 61 | 49 | ||
| 62 | 50 | ## Setup | |
| 63 | 51 | ||
| 64 | - | ### Token-only setup | |
| 65 | - | ||
| 66 | 52 | ```bash | |
| 67 | 53 | # Create token secret (random 32+ characters) | |
| 68 | 54 | pass insert gordon/auth/token_secret | |
| @@ -76,28 +62,9 @@ gordon auth token generate --subject ci-bot --scopes push,pull --expiry 0 | |||
| 76 | 62 | docker login -u ci-bot -p <token> registry.mydomain.com | |
| 77 | 63 | ``` | |
| 78 | 64 | ||
| 79 | - | ### Password + token setup | |
| 80 | - | ||
| 81 | - | ```bash | |
| 82 | - | # Generate bcrypt hash | |
| 83 | - | gordon auth password hash | |
| 84 | - | ||
| 85 | - | # Store hash and token secret | |
| 86 | - | pass insert gordon/auth/password_hash | |
| 87 | - | pass insert gordon/auth/token_secret | |
| 88 | - | ``` | |
| 89 | - | ||
| 90 | - | ```bash | |
| 91 | - | # Docker registry access | |
| 92 | - | docker login -u deploy -p <password> registry.mydomain.com | |
| 93 | - | ||
| 94 | - | # Remote CLI login (stores a token for you) | |
| 95 | - | gordon auth login --remote prod | |
| 96 | - | ``` | |
| 97 | - | ||
| 98 | 65 | ## Remote CLI Tokens | |
| 99 | 66 | ||
| 100 | - | If you already have a token (token-only servers), store it directly: | |
| 67 | + | Store a token for remote CLI access: | |
| 101 | 68 | ||
| 102 | 69 | ```bash | |
| 103 | 70 | gordon auth login --token <token> | |
| @@ -136,6 +103,23 @@ gordon auth token generate --subject builder --scopes push --expiry 0 | |||
| 136 | 103 | gordon auth token generate --subject admin --scopes "push,pull,admin:*:*" --expiry 0 | |
| 137 | 104 | ``` | |
| 138 | 105 | ||
| 106 | + | ## Access Token TTL | |
| 107 | + | ||
| 108 | + | The `access_token_ttl` setting controls the lifetime of ephemeral access tokens issued by the `/auth/token` endpoint. These short-lived tokens are used internally for registry operations and Admin API sessions. | |
| 109 | + | ||
| 110 | + | | Value | Meaning | | |
| 111 | + | |-------|---------| | |
| 112 | + | | `"15m"` | 15 minutes (default) | | |
| 113 | + | | `"30m"` | 30 minutes | | |
| 114 | + | | `"1h"` | 1 hour (maximum before store validation applies) | | |
| 115 | + | ||
| 116 | + | Tokens with a lifetime of 1 hour or less skip store validation for performance. Longer-lived tokens (generated via `gordon auth token generate`) are always validated against the token store. | |
| 117 | + | ||
| 118 | + | ```toml | |
| 119 | + | [auth] | |
| 120 | + | access_token_ttl = "30m" | |
| 121 | + | ``` | |
| 122 | + | ||
| 139 | 123 | ## Token Expiry | |
| 140 | 124 | ||
| 141 | 125 | Durations support `d`, `w`, `M`, `y` and combinations like `1y6M` or `2w3d`. | |
| @@ -4,29 +4,18 @@ Configure authentication for the Gordon registry and Admin API. | |||||
| 4 | 4 | ||||
| 5 | Authentication is enabled by default. Gordon will not start without a valid `token_secret` (or `GORDON_AUTH_TOKEN_SECRET`). | 5 | Authentication is enabled by default. Gordon will not start without a valid `token_secret` (or `GORDON_AUTH_TOKEN_SECRET`). | ||
| 6 | 6 | ||||
| 7 | - | ## Pick a Mode | 7 | + | ## Configuration |
| 8 | 8 | ||||
| 9 | - | ### Token-only (recommended for CI/CD) | 9 | + | Gordon uses token-only authentication. All registry and Admin API access is controlled through JWT tokens. |
| 10 | 10 | ||||
| 11 | ```toml | 11 | ```toml | ||
| 12 | [auth] | 12 | [auth] | ||
| 13 | secrets_backend = "pass" | 13 | secrets_backend = "pass" | ||
| 14 | token_secret = "gordon/auth/token_secret" | 14 | token_secret = "gordon/auth/token_secret" | ||
| 15 | token_expiry = "30d" | 15 | token_expiry = "30d" | ||
| 16 | + | access_token_ttl = "15m" | |||
| 16 | ``` | 17 | ``` | ||
| 17 | 18 | ||||
| 18 | - | ### Password + Token (interactive + CI/CD) | |||
| 19 | - | ||||
| 20 | - | ```toml | |||
| 21 | - | [auth] | |||
| 22 | - | secrets_backend = "pass" | |||
| 23 | - | username = "deploy" | |||
| 24 | - | password_hash = "gordon/auth/password_hash" | |||
| 25 | - | token_secret = "gordon/auth/token_secret" | |||
| 26 | - | ``` | |||
| 27 | - | ||||
| 28 | - | Token auth always works. Adding `username` + `password_hash` enables interactive login. | |||
| 29 | - | ||||
| 30 | ## Options | 19 | ## Options | ||
| 31 | 20 | ||||
| 32 | | Option | Type | Default | Description | | 21 | | Option | Type | Default | Description | | ||
| @@ -35,12 +24,11 @@ Token auth always works. Adding `username` + `password_hash` enables interactive | |||||
| 35 | | `secrets_backend` | string | `"unsafe"` | Secrets backend: `"pass"`, `"sops"`, or `"unsafe"` | | 24 | | `secrets_backend` | string | `"unsafe"` | Secrets backend: `"pass"`, `"sops"`, or `"unsafe"` | | ||
| 36 | | `token_secret` | string | - | **Required.** Path to JWT signing secret in secrets backend | | 25 | | `token_secret` | string | - | **Required.** Path to JWT signing secret in secrets backend | | ||
| 37 | | `token_expiry` | string | `"30d"` | Token validity duration (0 = never expires) | | 26 | | `token_expiry` | string | `"30d"` | Token validity duration (0 = never expires) | | ||
| 38 | - | | `username` | string | - | Username for password auth (optional) | | 27 | + | | `access_token_ttl` | string | `"15m"` | Lifetime of ephemeral access tokens issued by `/auth/token` | |
| 39 | - | | `password_hash` | string | - | Path to bcrypt hash in secrets backend (optional) | | |||
| 40 | 28 | ||||
| 41 | ## Secrets Backends | 29 | ## Secrets Backends | ||
| 42 | 30 | ||||
| 43 | - | `token_secret` and `password_hash` are read through the configured backend: | 31 | + | `token_secret` is read through the configured backend: |
| 44 | 32 | ||||
| 45 | | Backend | Description | | 33 | | Backend | Description | | ||
| 46 | | --------- | ------------- | | 34 | | --------- | ------------- | | ||
| @@ -52,7 +40,7 @@ See [Secret Providers](./secrets.md) for setup details. | |||||
| 52 | 40 | ||||
| 53 | ## Environment Variable | 41 | ## Environment Variable | ||
| 54 | 42 | ||||
| 55 | - | `GORDON_AUTH_TOKEN_SECRET` overrides `token_secret` in the config. If you don’t set the env var, `token_secret` is loaded from the configured secrets backend (including `pass`). | 43 | + | `GORDON_AUTH_TOKEN_SECRET` overrides `token_secret` in the config. If you don't set the env var, `token_secret` is loaded from the configured secrets backend (including `pass`). |
| 56 | 44 | ||||
| 57 | ```bash | 45 | ```bash | ||
| 58 | export GORDON_AUTH_TOKEN_SECRET="your-32-character-secret-here" | 46 | export GORDON_AUTH_TOKEN_SECRET="your-32-character-secret-here" | ||
| @@ -61,8 +49,6 @@ gordon serve | |||||
| 61 | 49 | ||||
| 62 | ## Setup | 50 | ## Setup | ||
| 63 | 51 | ||||
| 64 | - | ### Token-only setup | |||
| 65 | - | ||||
| 66 | ```bash | 52 | ```bash | ||
| 67 | # Create token secret (random 32+ characters) | 53 | # Create token secret (random 32+ characters) | ||
| 68 | pass insert gordon/auth/token_secret | 54 | pass insert gordon/auth/token_secret | ||
| @@ -76,28 +62,9 @@ gordon auth token generate --subject ci-bot --scopes push,pull --expiry 0 | |||||
| 76 | docker login -u ci-bot -p <token> registry.mydomain.com | 62 | docker login -u ci-bot -p <token> registry.mydomain.com | ||
| 77 | ``` | 63 | ``` | ||
| 78 | 64 | ||||
| 79 | - | ### Password + token setup | |||
| 80 | - | ||||
| 81 | - | ```bash | |||
| 82 | - | # Generate bcrypt hash | |||
| 83 | - | gordon auth password hash | |||
| 84 | - | ||||
| 85 | - | # Store hash and token secret | |||
| 86 | - | pass insert gordon/auth/password_hash | |||
| 87 | - | pass insert gordon/auth/token_secret | |||
| 88 | - | ``` | |||
| 89 | - | ||||
| 90 | - | ```bash | |||
| 91 | - | # Docker registry access | |||
| 92 | - | docker login -u deploy -p <password> registry.mydomain.com | |||
| 93 | - | ||||
| 94 | - | # Remote CLI login (stores a token for you) | |||
| 95 | - | gordon auth login --remote prod | |||
| 96 | - | ``` | |||
| 97 | - | ||||
| 98 | ## Remote CLI Tokens | 65 | ## Remote CLI Tokens | ||
| 99 | 66 | ||||
| 100 | - | If you already have a token (token-only servers), store it directly: | 67 | + | Store a token for remote CLI access: |
| 101 | 68 | ||||
| 102 | ```bash | 69 | ```bash | ||
| 103 | gordon auth login --token <token> | 70 | gordon auth login --token <token> | ||
| @@ -136,6 +103,23 @@ gordon auth token generate --subject builder --scopes push --expiry 0 | |||||
| 136 | gordon auth token generate --subject admin --scopes "push,pull,admin:*:*" --expiry 0 | 103 | gordon auth token generate --subject admin --scopes "push,pull,admin:*:*" --expiry 0 | ||
| 137 | ``` | 104 | ``` | ||
| 138 | 105 | ||||
| 106 | + | ## Access Token TTL | |||
| 107 | + | ||||
| 108 | + | The `access_token_ttl` setting controls the lifetime of ephemeral access tokens issued by the `/auth/token` endpoint. These short-lived tokens are used internally for registry operations and Admin API sessions. | |||
| 109 | + | ||||
| 110 | + | | Value | Meaning | | |||
| 111 | + | |-------|---------| | |||
| 112 | + | | `"15m"` | 15 minutes (default) | | |||
| 113 | + | | `"30m"` | 30 minutes | | |||
| 114 | + | | `"1h"` | 1 hour (maximum before store validation applies) | | |||
| 115 | + | ||||
| 116 | + | Tokens with a lifetime of 1 hour or less skip store validation for performance. Longer-lived tokens (generated via `gordon auth token generate`) are always validated against the token store. | |||
| 117 | + | ||||
| 118 | + | ```toml | |||
| 119 | + | [auth] | |||
| 120 | + | access_token_ttl = "30m" | |||
| 121 | + | ``` | |||
| 122 | + | ||||
| 139 | ## Token Expiry | 123 | ## Token Expiry | ||
| 140 | 124 | ||||
| 141 | Durations support `d`, `w`, `M`, `y` and combinations like `1y6M` or `2w3d`. | 125 | Durations support `d`, `w`, `M`, `y` and combinations like `1y6M` or `2w3d`. | ||
M docs/config/reference.md +2 -3
| @@ -28,9 +28,7 @@ enabled = true # Enable registry authentication (d | |||
| 28 | 28 | secrets_backend = "unsafe" # "pass", "sops", or "unsafe" | |
| 29 | 29 | token_secret = "" # Path in secrets backend to JWT signing key (REQUIRED) | |
| 30 | 30 | token_expiry = "720h" # Token expiry duration (720h = 30 days) | |
| 31 | - | # Optional: enable password authentication (for interactive login) | |
| 32 | - | # username = "" # Username for password auth | |
| 33 | - | # password_hash = "" # Path in secrets backend to bcrypt hash | |
| 31 | + | access_token_ttl = "15m" # Ephemeral access token lifetime (default: 15m) | |
| 34 | 32 | ||
| 35 | 33 | # ============================================================================= | |
| 36 | 34 | # API (applies to both Registry and Admin endpoints) | |
| @@ -182,6 +180,7 @@ keep_last = 3 # Keep N newest tags per repository | |||
| 182 | 180 | | `auth.enabled` | `true` | Enable authentication; when `false`, run local-only mode (loopback-only `/v2/*`, `/admin/*` disabled) | | |
| 183 | 181 | | `auth.secrets_backend` | `"unsafe"` | Secrets storage | | |
| 184 | 182 | | `auth.token_expiry` | `"720h"` | 30 days | | |
| 183 | + | | `auth.access_token_ttl` | `"15m"` | Ephemeral access token lifetime | | |
| 185 | 184 | | `api.rate_limit.enabled` | `true` | Enable rate limiting | | |
| 186 | 185 | | `api.rate_limit.global_rps` | `500` | Global requests/second | | |
| 187 | 186 | | `api.rate_limit.per_ip_rps` | `50` | Per-IP requests/second | | |
| @@ -28,9 +28,7 @@ enabled = true # Enable registry authentication (d | |||||
| 28 | secrets_backend = "unsafe" # "pass", "sops", or "unsafe" | 28 | secrets_backend = "unsafe" # "pass", "sops", or "unsafe" | ||
| 29 | token_secret = "" # Path in secrets backend to JWT signing key (REQUIRED) | 29 | token_secret = "" # Path in secrets backend to JWT signing key (REQUIRED) | ||
| 30 | token_expiry = "720h" # Token expiry duration (720h = 30 days) | 30 | token_expiry = "720h" # Token expiry duration (720h = 30 days) | ||
| 31 | - | # Optional: enable password authentication (for interactive login) | 31 | + | access_token_ttl = "15m" # Ephemeral access token lifetime (default: 15m) |
| 32 | - | # username = "" # Username for password auth | |||
| 33 | - | # password_hash = "" # Path in secrets backend to bcrypt hash | |||
| 34 | 32 | ||||
| 35 | # ============================================================================= | 33 | # ============================================================================= | ||
| 36 | # API (applies to both Registry and Admin endpoints) | 34 | # API (applies to both Registry and Admin endpoints) | ||
| @@ -182,6 +180,7 @@ keep_last = 3 # Keep N newest tags per repository | |||||
| 182 | | `auth.enabled` | `true` | Enable authentication; when `false`, run local-only mode (loopback-only `/v2/*`, `/admin/*` disabled) | | 180 | | `auth.enabled` | `true` | Enable authentication; when `false`, run local-only mode (loopback-only `/v2/*`, `/admin/*` disabled) | | ||
| 183 | | `auth.secrets_backend` | `"unsafe"` | Secrets storage | | 181 | | `auth.secrets_backend` | `"unsafe"` | Secrets storage | | ||
| 184 | | `auth.token_expiry` | `"720h"` | 30 days | | 182 | | `auth.token_expiry` | `"720h"` | 30 days | | ||
| 183 | + | | `auth.access_token_ttl` | `"15m"` | Ephemeral access token lifetime | | |||
| 185 | | `api.rate_limit.enabled` | `true` | Enable rate limiting | | 184 | | `api.rate_limit.enabled` | `true` | Enable rate limiting | | ||
| 186 | | `api.rate_limit.global_rps` | `500` | Global requests/second | | 185 | | `api.rate_limit.global_rps` | `500` | Global requests/second | | ||
| 187 | | `api.rate_limit.per_ip_rps` | `50` | Per-IP requests/second | | 186 | | `api.rate_limit.per_ip_rps` | `50` | Per-IP requests/second | | ||
M docs/getting-started.md +1 -1
| @@ -132,7 +132,7 @@ gordon auth token generate --subject deploy --scopes push,pull --expiry 0 | |||
| 132 | 132 | ||
| 133 | 133 | `--expiry 0` creates a non-expiring token. Prefer a finite expiry and a rotation policy unless you explicitly need a long-lived deploy token. | |
| 134 | 134 | ||
| 135 | - | Save this token securely - you'll use it with `gordon --remote` (or a saved remote), and it should be limited to remote deploy use. | |
| 135 | + | Save this token securely -- you will use it to authenticate with your Gordon server from CI/CD pipelines and remote CLI sessions. | |
| 136 | 136 | ||
| 137 | 137 | ## 8. Deploy Your First App | |
| 138 | 138 | ||
| @@ -132,7 +132,7 @@ gordon auth token generate --subject deploy --scopes push,pull --expiry 0 | |||||
| 132 | 132 | ||||
| 133 | `--expiry 0` creates a non-expiring token. Prefer a finite expiry and a rotation policy unless you explicitly need a long-lived deploy token. | 133 | `--expiry 0` creates a non-expiring token. Prefer a finite expiry and a rotation policy unless you explicitly need a long-lived deploy token. | ||
| 134 | 134 | ||||
| 135 | - | Save this token securely - you'll use it with `gordon --remote` (or a saved remote), and it should be limited to remote deploy use. | 135 | + | Save this token securely -- you will use it to authenticate with your Gordon server from CI/CD pipelines and remote CLI sessions. |
| 136 | 136 | ||||
| 137 | ## 8. Deploy Your First App | 137 | ## 8. Deploy Your First App | ||
| 138 | 138 | ||||
M docs/upgrading.md +99 -0
| @@ -2,6 +2,105 @@ | |||
| 2 | 2 | ||
| 3 | 3 | This guide covers breaking changes and migration steps between major versions. | |
| 4 | 4 | ||
| 5 | + | ## v2.7.0 to v2.8.0 | |
| 6 | + | ||
| 7 | + | ### Breaking: Password Authentication Removed | |
| 8 | + | ||
| 9 | + | Gordon v2.8.0 removes password-based authentication entirely. Only token-based authentication is supported. | |
| 10 | + | ||
| 11 | + | **What changed:** | |
| 12 | + | ||
| 13 | + | - `auth.type = "password"` is no longer accepted | |
| 14 | + | - `auth.password` and `auth.password_hash` config fields are removed | |
| 15 | + | - The `gordon auth password hash` CLI command is removed | |
| 16 | + | - The `gordon auth login` command no longer accepts `--username` or `--password` flags | |
| 17 | + | - The `/auth/password` endpoint is removed | |
| 18 | + | ||
| 19 | + | **New features:** | |
| 20 | + | ||
| 21 | + | - `auth.access_token_ttl` configures the lifetime of ephemeral access tokens issued by `/auth/token` (default: `"15m"`) | |
| 22 | + | - Admin scopes (`admin:*:*`, `admin:routes:read`, etc.) allow fine-grained access control for remote CLI operations | |
| 23 | + | ||
| 24 | + | **Migration steps:** | |
| 25 | + | ||
| 26 | + | 1. **Before upgrading**, generate a token on your current Gordon instance: | |
| 27 | + | ||
| 28 | + | ```bash | |
| 29 | + | gordon auth token generate --subject deploy --scopes "push,pull,admin:*:*" --expiry 0 | |
| 30 | + | ``` | |
| 31 | + | ||
| 32 | + | Save this token securely. You will need it after upgrading. | |
| 33 | + | ||
| 34 | + | 2. **Update remotes** to use the generated token: | |
| 35 | + | ||
| 36 | + | ```bash | |
| 37 | + | gordon auth login --token <token> | |
| 38 | + | # or | |
| 39 | + | gordon remotes set-token prod <token> | |
| 40 | + | ``` | |
| 41 | + | ||
| 42 | + | 3. **Update your config** to remove password fields: | |
| 43 | + | ||
| 44 | + | **Before (v2.7.0):** | |
| 45 | + | ```toml | |
| 46 | + | [auth] | |
| 47 | + | enabled = true | |
| 48 | + | secrets_backend = "pass" | |
| 49 | + | username = "deploy" | |
| 50 | + | password_hash = "gordon/auth/password_hash" | |
| 51 | + | token_secret = "gordon/auth/token_secret" | |
| 52 | + | ``` | |
| 53 | + | ||
| 54 | + | **After (v2.8.0):** | |
| 55 | + | ```toml | |
| 56 | + | [auth] | |
| 57 | + | enabled = true | |
| 58 | + | secrets_backend = "pass" | |
| 59 | + | token_secret = "gordon/auth/token_secret" | |
| 60 | + | access_token_ttl = "15m" | |
| 61 | + | ``` | |
| 62 | + | ||
| 63 | + | 4. **Update CI/CD pipelines** to use `GORDON_TOKEN` environment variable for authentication. See the [deployment guides](./deployment/index.md). | |
| 64 | + | ||
| 65 | + | 5. **Upgrade the binary** and restart: | |
| 66 | + | ||
| 67 | + | ```bash | |
| 68 | + | curl -fsSL https://gordon.bnema.dev/install | bash | |
| 69 | + | systemctl --user restart gordon | |
| 70 | + | ``` | |
| 71 | + | ||
| 72 | + | 6. **Verify** the server starts without errors: | |
| 73 | + | ||
| 74 | + | ```bash | |
| 75 | + | journalctl --user -u gordon -f | |
| 76 | + | ``` | |
| 77 | + | ||
| 78 | + | ### New: Configurable Access Token TTL | |
| 79 | + | ||
| 80 | + | Ephemeral access tokens issued by `/auth/token` now have a configurable lifetime via `auth.access_token_ttl`. The default is `"15m"`. Tokens with a lifetime of 1 hour or less skip store validation for performance. | |
| 81 | + | ||
| 82 | + | ```toml | |
| 83 | + | [auth] | |
| 84 | + | access_token_ttl = "30m" | |
| 85 | + | ``` | |
| 86 | + | ||
| 87 | + | ### New: Admin Scopes | |
| 88 | + | ||
| 89 | + | Tokens can now include fine-grained admin scopes for remote CLI operations: | |
| 90 | + | ||
| 91 | + | ```bash | |
| 92 | + | # Full admin access | |
| 93 | + | gordon auth token generate --subject admin --scopes "push,pull,admin:*:*" --expiry 0 | |
| 94 | + | ||
| 95 | + | # Read-only monitoring | |
| 96 | + | gordon auth token generate --subject monitor --scopes "admin:status:read" --expiry 30d | |
| 97 | + | ||
| 98 | + | # CI deploy with route read + config write | |
| 99 | + | gordon auth token generate --subject ci --scopes "push,pull,admin:routes:read,admin:config:write" --expiry 0 | |
| 100 | + | ``` | |
| 101 | + | ||
| 102 | + | See [Token Scopes](./config/auth.md#token-scopes) for the full list. | |
| 103 | + | ||
| 5 | 104 | ## v2.6.0 to v2.7.0 | |
| 6 | 105 | ||
| 7 | 106 | ### Breaking: Token Secret Required | |
| @@ -2,6 +2,105 @@ | |||||
| 2 | 2 | ||||
| 3 | This guide covers breaking changes and migration steps between major versions. | 3 | This guide covers breaking changes and migration steps between major versions. | ||
| 4 | 4 | ||||
| 5 | + | ## v2.7.0 to v2.8.0 | |||
| 6 | + | ||||
| 7 | + | ### Breaking: Password Authentication Removed | |||
| 8 | + | ||||
| 9 | + | Gordon v2.8.0 removes password-based authentication entirely. Only token-based authentication is supported. | |||
| 10 | + | ||||
| 11 | + | **What changed:** | |||
| 12 | + | ||||
| 13 | + | - `auth.type = "password"` is no longer accepted | |||
| 14 | + | - `auth.password` and `auth.password_hash` config fields are removed | |||
| 15 | + | - The `gordon auth password hash` CLI command is removed | |||
| 16 | + | - The `gordon auth login` command no longer accepts `--username` or `--password` flags | |||
| 17 | + | - The `/auth/password` endpoint is removed | |||
| 18 | + | ||||
| 19 | + | **New features:** | |||
| 20 | + | ||||
| 21 | + | - `auth.access_token_ttl` configures the lifetime of ephemeral access tokens issued by `/auth/token` (default: `"15m"`) | |||
| 22 | + | - Admin scopes (`admin:*:*`, `admin:routes:read`, etc.) allow fine-grained access control for remote CLI operations | |||
| 23 | + | ||||
| 24 | + | **Migration steps:** | |||
| 25 | + | ||||
| 26 | + | 1. **Before upgrading**, generate a token on your current Gordon instance: | |||
| 27 | + | ||||
| 28 | + | ```bash | |||
| 29 | + | gordon auth token generate --subject deploy --scopes "push,pull,admin:*:*" --expiry 0 | |||
| 30 | + | ``` | |||
| 31 | + | ||||
| 32 | + | Save this token securely. You will need it after upgrading. | |||
| 33 | + | ||||
| 34 | + | 2. **Update remotes** to use the generated token: | |||
| 35 | + | ||||
| 36 | + | ```bash | |||
| 37 | + | gordon auth login --token <token> | |||
| 38 | + | # or | |||
| 39 | + | gordon remotes set-token prod <token> | |||
| 40 | + | ``` | |||
| 41 | + | ||||
| 42 | + | 3. **Update your config** to remove password fields: | |||
| 43 | + | ||||
| 44 | + | **Before (v2.7.0):** | |||
| 45 | + | ```toml | |||
| 46 | + | [auth] | |||
| 47 | + | enabled = true | |||
| 48 | + | secrets_backend = "pass" | |||
| 49 | + | username = "deploy" | |||
| 50 | + | password_hash = "gordon/auth/password_hash" | |||
| 51 | + | token_secret = "gordon/auth/token_secret" | |||
| 52 | + | ``` | |||
| 53 | + | ||||
| 54 | + | **After (v2.8.0):** | |||
| 55 | + | ```toml | |||
| 56 | + | [auth] | |||
| 57 | + | enabled = true | |||
| 58 | + | secrets_backend = "pass" | |||
| 59 | + | token_secret = "gordon/auth/token_secret" | |||
| 60 | + | access_token_ttl = "15m" | |||
| 61 | + | ``` | |||
| 62 | + | ||||
| 63 | + | 4. **Update CI/CD pipelines** to use `GORDON_TOKEN` environment variable for authentication. See the [deployment guides](./deployment/index.md). | |||
| 64 | + | ||||
| 65 | + | 5. **Upgrade the binary** and restart: | |||
| 66 | + | ||||
| 67 | + | ```bash | |||
| 68 | + | curl -fsSL https://gordon.bnema.dev/install | bash | |||
| 69 | + | systemctl --user restart gordon | |||
| 70 | + | ``` | |||
| 71 | + | ||||
| 72 | + | 6. **Verify** the server starts without errors: | |||
| 73 | + | ||||
| 74 | + | ```bash | |||
| 75 | + | journalctl --user -u gordon -f | |||
| 76 | + | ``` | |||
| 77 | + | ||||
| 78 | + | ### New: Configurable Access Token TTL | |||
| 79 | + | ||||
| 80 | + | Ephemeral access tokens issued by `/auth/token` now have a configurable lifetime via `auth.access_token_ttl`. The default is `"15m"`. Tokens with a lifetime of 1 hour or less skip store validation for performance. | |||
| 81 | + | ||||
| 82 | + | ```toml | |||
| 83 | + | [auth] | |||
| 84 | + | access_token_ttl = "30m" | |||
| 85 | + | ``` | |||
| 86 | + | ||||
| 87 | + | ### New: Admin Scopes | |||
| 88 | + | ||||
| 89 | + | Tokens can now include fine-grained admin scopes for remote CLI operations: | |||
| 90 | + | ||||
| 91 | + | ```bash | |||
| 92 | + | # Full admin access | |||
| 93 | + | gordon auth token generate --subject admin --scopes "push,pull,admin:*:*" --expiry 0 | |||
| 94 | + | ||||
| 95 | + | # Read-only monitoring | |||
| 96 | + | gordon auth token generate --subject monitor --scopes "admin:status:read" --expiry 30d | |||
| 97 | + | ||||
| 98 | + | # CI deploy with route read + config write | |||
| 99 | + | gordon auth token generate --subject ci --scopes "push,pull,admin:routes:read,admin:config:write" --expiry 0 | |||
| 100 | + | ``` | |||
| 101 | + | ||||
| 102 | + | See [Token Scopes](./config/auth.md#token-scopes) for the full list. | |||
| 103 | + | ||||
| 5 | ## v2.6.0 to v2.7.0 | 104 | ## v2.6.0 to v2.7.0 | ||
| 6 | 105 | ||||
| 7 | ### Breaking: Token Secret Required | 106 | ### Breaking: Token Secret Required | ||