Major refactoring to hexagonal (ports & adapters) architecture: - Add service layer (apikey_service, project_service) for business logic - Add webhook system with dispatcher and delivery tracking - Add command queue with priority-based processing - Add rate limiting with sliding window algorithm - Add audit logging for command execution - Add OpenTelemetry integration (traces, metrics, spans) - Add circuit breaker for fault tolerance - Add cached repository wrapper for performance - Add comprehensive validation package - Add Kubernetes client integration for pod management - Add database migrations (allowed_ips, audit_log, rate_limiting, queue, webhooks) - Add network policy and PodDisruptionBudget for k8s - Remove legacy executor and projects/registry packages - Untrack secrets.yaml (now managed via envault) - Add coverage.out to .gitignore - Add e2e test infrastructure with docker-compose - Add comprehensive documentation (API, architecture, operations, plans) - Add golangci-lint config and pre-commit hook Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
258 lines
4.5 KiB
Markdown
258 lines
4.5 KiB
Markdown
# Authentication Guide
|
|
|
|
rdev uses API keys for authentication. This guide covers how to authenticate requests and manage API keys.
|
|
|
|
## API Key Format
|
|
|
|
API keys follow this format:
|
|
```
|
|
rdev_<32 random characters>
|
|
```
|
|
|
|
Example:
|
|
```
|
|
rdev_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
|
|
```
|
|
|
|
## Authenticating Requests
|
|
|
|
### Using X-API-Key Header
|
|
|
|
```bash
|
|
curl https://rdev.example.com/projects \
|
|
-H "X-API-Key: rdev_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
|
|
```
|
|
|
|
### Using Authorization Header
|
|
|
|
```bash
|
|
curl https://rdev.example.com/projects \
|
|
-H "Authorization: Bearer rdev_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
|
|
```
|
|
|
|
## Scopes
|
|
|
|
API keys have scopes that limit what actions they can perform:
|
|
|
|
| Scope | Description |
|
|
|-------|-------------|
|
|
| `projects:read` | List and view projects |
|
|
| `projects:execute` | Execute commands in projects |
|
|
| `keys:read` | List API keys |
|
|
| `keys:write` | Create and revoke API keys |
|
|
| `admin` | Full access to all operations |
|
|
|
|
### Scope Inheritance
|
|
|
|
- `admin` scope includes all other scopes
|
|
- Command execution requires `projects:execute`
|
|
- Reading projects requires `projects:read` or `projects:execute`
|
|
|
|
## Managing API Keys
|
|
|
|
### List Keys
|
|
|
|
```bash
|
|
curl https://rdev.example.com/keys \
|
|
-H "X-API-Key: your-admin-key"
|
|
```
|
|
|
|
Response:
|
|
```json
|
|
{
|
|
"data": [
|
|
{
|
|
"id": "key-001",
|
|
"name": "production-key",
|
|
"key_prefix": "rdev_a1b2",
|
|
"scopes": ["projects:read", "projects:execute"],
|
|
"created_at": "2024-01-01T00:00:00Z",
|
|
"last_used_at": "2024-01-15T10:30:00Z"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Create Key
|
|
|
|
```bash
|
|
curl -X POST https://rdev.example.com/keys \
|
|
-H "X-API-Key: your-admin-key" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"name": "ci-pipeline",
|
|
"scopes": ["projects:execute"],
|
|
"expires_in": "30d",
|
|
"allowed_ips": ["10.0.0.0/8"]
|
|
}'
|
|
```
|
|
|
|
Request body:
|
|
```json
|
|
{
|
|
"name": "ci-pipeline",
|
|
"scopes": ["projects:read", "projects:execute"],
|
|
"expires_in": "30d",
|
|
"allowed_ips": ["10.0.0.0/8", "192.168.1.0/24"]
|
|
}
|
|
```
|
|
|
|
| Field | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `name` | string | yes | Human-readable key name |
|
|
| `scopes` | array | yes | Permission scopes |
|
|
| `expires_in` | string | no | Expiration duration (e.g., "30d", "24h") |
|
|
| `allowed_ips` | array | no | IP allowlist in CIDR notation |
|
|
|
|
Response:
|
|
```json
|
|
{
|
|
"data": {
|
|
"id": "key-002",
|
|
"name": "ci-pipeline",
|
|
"key": "rdev_x1y2z3...",
|
|
"scopes": ["projects:execute"],
|
|
"created_at": "2024-01-15T10:30:00Z",
|
|
"expires_at": "2024-02-14T10:30:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
> **Important**: The full key is only returned once at creation time. Store it securely!
|
|
|
|
### Revoke Key
|
|
|
|
```bash
|
|
curl -X DELETE https://rdev.example.com/keys/key-002 \
|
|
-H "X-API-Key: your-admin-key"
|
|
```
|
|
|
|
## IP Allowlisting
|
|
|
|
Keys can be restricted to specific IP addresses:
|
|
|
|
```json
|
|
{
|
|
"name": "restricted-key",
|
|
"scopes": ["projects:execute"],
|
|
"allowed_ips": [
|
|
"10.0.0.0/8",
|
|
"192.168.1.100/32"
|
|
]
|
|
}
|
|
```
|
|
|
|
If `allowed_ips` is empty or not set, all IPs are allowed.
|
|
|
|
## Key Expiration
|
|
|
|
Keys can have an expiration time:
|
|
|
|
- Set at creation with `expires_in`
|
|
- Cannot be extended after creation
|
|
- Expired keys return `KEY_EXPIRED` error
|
|
|
|
## Best Practices
|
|
|
|
### 1. Use Least Privilege
|
|
|
|
Create keys with only the scopes needed:
|
|
```json
|
|
{
|
|
"name": "read-only-dashboard",
|
|
"scopes": ["projects:read"]
|
|
}
|
|
```
|
|
|
|
### 2. Set Expiration
|
|
|
|
For temporary access, set expiration:
|
|
```json
|
|
{
|
|
"name": "contractor-access",
|
|
"scopes": ["projects:execute"],
|
|
"expires_in": "7d"
|
|
}
|
|
```
|
|
|
|
### 3. Use IP Restrictions
|
|
|
|
For CI/CD pipelines with known IPs:
|
|
```json
|
|
{
|
|
"name": "github-actions",
|
|
"scopes": ["projects:execute"],
|
|
"allowed_ips": ["192.30.252.0/22"]
|
|
}
|
|
```
|
|
|
|
### 4. Rotate Keys Regularly
|
|
|
|
Create new keys and revoke old ones periodically.
|
|
|
|
### 5. Use Descriptive Names
|
|
|
|
Name keys by their purpose:
|
|
- `ci-github-actions`
|
|
- `dev-jordan-laptop`
|
|
- `prod-monitoring`
|
|
|
|
## Error Responses
|
|
|
|
### 401 Unauthorized
|
|
|
|
Missing or invalid API key:
|
|
```json
|
|
{
|
|
"error": {
|
|
"code": "UNAUTHORIZED",
|
|
"message": "Missing API key"
|
|
}
|
|
}
|
|
```
|
|
|
|
### 401 Key Revoked
|
|
|
|
```json
|
|
{
|
|
"error": {
|
|
"code": "KEY_REVOKED",
|
|
"message": "API key has been revoked"
|
|
}
|
|
}
|
|
```
|
|
|
|
### 401 Key Expired
|
|
|
|
```json
|
|
{
|
|
"error": {
|
|
"code": "KEY_EXPIRED",
|
|
"message": "API key has expired"
|
|
}
|
|
}
|
|
```
|
|
|
|
### 403 IP Not Allowed
|
|
|
|
```json
|
|
{
|
|
"error": {
|
|
"code": "IP_NOT_ALLOWED",
|
|
"message": "IP address not allowed for this API key"
|
|
}
|
|
}
|
|
```
|
|
|
|
### 403 Forbidden
|
|
|
|
Insufficient scopes:
|
|
```json
|
|
{
|
|
"error": {
|
|
"code": "FORBIDDEN",
|
|
"message": "Insufficient permissions. Required: projects:execute"
|
|
}
|
|
}
|
|
```
|