772 lines
20 KiB
Markdown
772 lines
20 KiB
Markdown
# Secret Management API
|
|
|
|
The Secret Management API provides secure endpoints for storing, retrieving, and managing sensitive credentials, API keys, tokens, and other secret values in the Attune automation platform. All secret values are encrypted at rest using AES-256-GCM encryption.
|
|
|
|
## Table of Contents
|
|
|
|
- [Overview](#overview)
|
|
- [Security Model](#security-model)
|
|
- [Key Model](#key-model)
|
|
- [Authentication](#authentication)
|
|
- [Endpoints](#endpoints)
|
|
- [List Keys](#list-keys)
|
|
- [Get Key by Reference](#get-key-by-reference)
|
|
- [Create Key](#create-key)
|
|
- [Update Key](#update-key)
|
|
- [Delete Key](#delete-key)
|
|
- [Use Cases](#use-cases)
|
|
- [Security Best Practices](#security-best-practices)
|
|
- [Related Resources](#related-resources)
|
|
|
|
---
|
|
|
|
## Overview
|
|
|
|
The Secret Management API enables secure storage and retrieval of sensitive data that actions and sensors need to execute. Common use cases include:
|
|
|
|
- **API Credentials**: Store API keys, tokens, and secrets for external services
|
|
- **Database Credentials**: Store database passwords and connection strings
|
|
- **SSH Keys**: Store private SSH keys for remote access
|
|
- **OAuth Tokens**: Store OAuth access and refresh tokens
|
|
- **Service Account Keys**: Store service account credentials for cloud providers
|
|
|
|
### Key Features
|
|
|
|
- **Encryption at Rest**: All secret values are encrypted using AES-256-GCM
|
|
- **Value Redaction**: List views never expose actual secret values
|
|
- **Owner Association**: Link secrets to identities, packs, actions, or sensors
|
|
- **Audit Trail**: Track creation and modification timestamps
|
|
- **Flexible Ownership**: Support multiple ownership models (system, identity, pack, action, sensor)
|
|
|
|
---
|
|
|
|
## Security Model
|
|
|
|
### Encryption
|
|
|
|
All secret values marked as `encrypted: true` are encrypted using AES-256-GCM encryption before being stored in the database. The encryption process:
|
|
|
|
1. **Key Derivation**: The server's encryption key is hashed using SHA-256 to derive a 256-bit AES key
|
|
2. **Random Nonce**: A random 96-bit nonce is generated for each encryption operation
|
|
3. **Encryption**: The plaintext is encrypted using AES-256-GCM with the derived key and nonce
|
|
4. **Storage**: The encrypted value (nonce + ciphertext + authentication tag) is base64-encoded and stored
|
|
|
|
### Decryption
|
|
|
|
When retrieving a secret value via GET `/api/v1/keys/:ref`, the server automatically decrypts the value if it's encrypted:
|
|
|
|
1. The encrypted value is base64-decoded
|
|
2. The nonce is extracted from the beginning of the data
|
|
3. The ciphertext is decrypted using the server's encryption key
|
|
4. The decrypted plaintext is returned in the API response
|
|
|
|
### Access Control
|
|
|
|
- **Authentication Required**: All endpoints require JWT authentication
|
|
- **No List Value Exposure**: List endpoints (`GET /keys`) never return actual secret values
|
|
- **Individual Retrieval**: Secret values can only be retrieved one at a time via GET `/keys/:ref`
|
|
- **Audit Logging**: All access is logged (future enhancement)
|
|
|
|
### Server Configuration
|
|
|
|
The server must have an encryption key configured:
|
|
|
|
```yaml
|
|
security:
|
|
encryption_key: "your-encryption-key-must-be-at-least-32-characters-long"
|
|
```
|
|
|
|
Or via environment variable:
|
|
|
|
```bash
|
|
ATTUNE__SECURITY__ENCRYPTION_KEY="your-encryption-key-must-be-at-least-32-characters-long"
|
|
```
|
|
|
|
⚠️ **Warning**: The encryption key must be:
|
|
- At least 32 characters long
|
|
- Kept secret and secure
|
|
- Backed up securely
|
|
- Never committed to version control
|
|
- Rotated periodically (requires re-encrypting all secrets)
|
|
|
|
---
|
|
|
|
## Key Model
|
|
|
|
### Key Object
|
|
|
|
```json
|
|
{
|
|
"id": 123,
|
|
"ref": "github_api_token",
|
|
"owner_type": "pack",
|
|
"owner": "github-integration",
|
|
"owner_identity": null,
|
|
"owner_pack": 456,
|
|
"owner_pack_ref": "github",
|
|
"owner_action": null,
|
|
"owner_action_ref": null,
|
|
"owner_sensor": null,
|
|
"owner_sensor_ref": null,
|
|
"name": "GitHub Personal Access Token",
|
|
"encrypted": true,
|
|
"value": "ghp_1234567890abcdefghijklmnopqrstuvwxyz",
|
|
"created": "2024-01-15T10:00:00Z",
|
|
"updated": "2024-01-15T10:00:00Z"
|
|
}
|
|
```
|
|
|
|
### Fields
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `id` | integer | Unique key identifier |
|
|
| `ref` | string | Unique reference (e.g., "github_token", "aws_secret_key") |
|
|
| `owner_type` | string | Owner type: `system`, `identity`, `pack`, `action`, `sensor` |
|
|
| `owner` | string | Optional owner string identifier |
|
|
| `owner_identity` | integer | Optional owner identity ID |
|
|
| `owner_pack` | integer | Optional owner pack ID |
|
|
| `owner_pack_ref` | string | Optional owner pack reference |
|
|
| `owner_action` | integer | Optional owner action ID |
|
|
| `owner_action_ref` | string | Optional owner action reference |
|
|
| `owner_sensor` | integer | Optional owner sensor ID |
|
|
| `owner_sensor_ref` | string | Optional owner sensor reference |
|
|
| `name` | string | Human-readable name |
|
|
| `encrypted` | boolean | Whether the value is encrypted (recommended: true) |
|
|
| `value` | string | The secret value (decrypted in single-item GET, omitted in lists) |
|
|
| `created` | datetime | Timestamp when key was created |
|
|
| `updated` | datetime | Timestamp of last update |
|
|
|
|
### Owner Types
|
|
|
|
| Type | Description | Use Case |
|
|
|------|-------------|----------|
|
|
| `system` | System-wide secret | Global configuration, shared credentials |
|
|
| `identity` | User-owned secret | Personal API keys, user-specific tokens |
|
|
| `pack` | Pack-scoped secret | Credentials for a specific integration pack |
|
|
| `action` | Action-specific secret | Credentials used by a single action |
|
|
| `sensor` | Sensor-specific secret | Credentials used by a sensor |
|
|
|
|
---
|
|
|
|
## Authentication
|
|
|
|
All secret management endpoints require authentication. Include a valid JWT access token in the `Authorization` header:
|
|
|
|
```
|
|
Authorization: Bearer <access_token>
|
|
```
|
|
|
|
See the [Authentication Guide](./authentication.md) for details on obtaining tokens.
|
|
|
|
---
|
|
|
|
## Endpoints
|
|
|
|
### List Keys
|
|
|
|
Retrieve a paginated list of keys with optional filtering. **Values are redacted** in list views for security.
|
|
|
|
**Endpoint:** `GET /api/v1/keys`
|
|
|
|
**Query Parameters:**
|
|
|
|
| Parameter | Type | Default | Description |
|
|
|-----------|------|---------|-------------|
|
|
| `owner_type` | string | - | Filter by owner type (system, identity, pack, action, sensor) |
|
|
| `owner` | string | - | Filter by owner string |
|
|
| `page` | integer | 1 | Page number (1-indexed) |
|
|
| `per_page` | integer | 50 | Items per page (max 100) |
|
|
|
|
**Example Request:**
|
|
|
|
```bash
|
|
curl -X GET "http://localhost:8080/api/v1/keys?owner_type=pack&page=1" \
|
|
-H "Authorization: Bearer <access_token>"
|
|
```
|
|
|
|
**Response:** `200 OK`
|
|
|
|
```json
|
|
{
|
|
"data": [
|
|
{
|
|
"id": 123,
|
|
"ref": "github_api_token",
|
|
"owner_type": "pack",
|
|
"owner": "github-integration",
|
|
"name": "GitHub Personal Access Token",
|
|
"encrypted": true,
|
|
"created": "2024-01-15T10:00:00Z"
|
|
},
|
|
{
|
|
"id": 124,
|
|
"ref": "aws_secret_key",
|
|
"owner_type": "pack",
|
|
"owner": "aws-integration",
|
|
"name": "AWS Secret Access Key",
|
|
"encrypted": true,
|
|
"created": "2024-01-15T11:00:00Z"
|
|
}
|
|
],
|
|
"pagination": {
|
|
"page": 1,
|
|
"page_size": 50,
|
|
"total_items": 2,
|
|
"total_pages": 1
|
|
}
|
|
}
|
|
```
|
|
|
|
**Note**: Secret values are **never** included in list responses for security.
|
|
|
|
---
|
|
|
|
### Get Key by Reference
|
|
|
|
Retrieve a single key by its reference. **The secret value is decrypted and returned** in the response.
|
|
|
|
**Endpoint:** `GET /api/v1/keys/:ref`
|
|
|
|
**Path Parameters:**
|
|
|
|
| Parameter | Type | Description |
|
|
|-----------|------|-------------|
|
|
| `ref` | string | Key reference (e.g., "github_token") |
|
|
|
|
**Example Request:**
|
|
|
|
```bash
|
|
curl -X GET "http://localhost:8080/api/v1/keys/github_api_token" \
|
|
-H "Authorization: Bearer <access_token>"
|
|
```
|
|
|
|
**Response:** `200 OK`
|
|
|
|
```json
|
|
{
|
|
"data": {
|
|
"id": 123,
|
|
"ref": "github_api_token",
|
|
"owner_type": "pack",
|
|
"owner": "github-integration",
|
|
"owner_identity": null,
|
|
"owner_pack": 456,
|
|
"owner_pack_ref": "github",
|
|
"owner_action": null,
|
|
"owner_action_ref": null,
|
|
"owner_sensor": null,
|
|
"owner_sensor_ref": null,
|
|
"name": "GitHub Personal Access Token",
|
|
"encrypted": true,
|
|
"value": "ghp_1234567890abcdefghijklmnopqrstuvwxyz",
|
|
"created": "2024-01-15T10:00:00Z",
|
|
"updated": "2024-01-15T10:00:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Security Note**: The `value` field contains the **decrypted plaintext** secret. Handle this data carefully and never log or expose it.
|
|
|
|
**Error Responses:**
|
|
|
|
- `404 Not Found`: Key not found
|
|
- `500 Internal Server Error`: Decryption failed (wrong encryption key or corrupted data)
|
|
|
|
---
|
|
|
|
### Create Key
|
|
|
|
Create a new secret key with automatic encryption.
|
|
|
|
**Endpoint:** `POST /api/v1/keys`
|
|
|
|
**Request Body:**
|
|
|
|
```json
|
|
{
|
|
"ref": "github_api_token",
|
|
"owner_type": "pack",
|
|
"owner": "github-integration",
|
|
"owner_pack": 456,
|
|
"owner_pack_ref": "github",
|
|
"name": "GitHub Personal Access Token",
|
|
"value": "ghp_1234567890abcdefghijklmnopqrstuvwxyz",
|
|
"encrypted": true
|
|
}
|
|
```
|
|
|
|
**Field Validation:**
|
|
|
|
| Field | Required | Constraints |
|
|
|-------|----------|-------------|
|
|
| `ref` | Yes | 1-255 characters, must be unique |
|
|
| `owner_type` | Yes | Must be: system, identity, pack, action, sensor |
|
|
| `owner` | No | Max 255 characters |
|
|
| `owner_identity` | No | Valid identity ID |
|
|
| `owner_pack` | No | Valid pack ID |
|
|
| `owner_pack_ref` | No | Max 255 characters |
|
|
| `owner_action` | No | Valid action ID |
|
|
| `owner_action_ref` | No | Max 255 characters |
|
|
| `owner_sensor` | No | Valid sensor ID |
|
|
| `owner_sensor_ref` | No | Max 255 characters |
|
|
| `name` | Yes | 1-255 characters |
|
|
| `value` | Yes | 1-10,000 characters |
|
|
| `encrypted` | No | Boolean (default: true) |
|
|
|
|
**Example Request:**
|
|
|
|
```bash
|
|
curl -X POST "http://localhost:8080/api/v1/keys" \
|
|
-H "Authorization: Bearer <access_token>" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"ref": "github_api_token",
|
|
"owner_type": "pack",
|
|
"owner_pack_ref": "github",
|
|
"name": "GitHub Personal Access Token",
|
|
"value": "ghp_1234567890abcdefghijklmnopqrstuvwxyz",
|
|
"encrypted": true
|
|
}'
|
|
```
|
|
|
|
**Response:** `201 Created`
|
|
|
|
```json
|
|
{
|
|
"data": {
|
|
"id": 123,
|
|
"ref": "github_api_token",
|
|
"owner_type": "pack",
|
|
"owner": null,
|
|
"owner_identity": null,
|
|
"owner_pack": null,
|
|
"owner_pack_ref": "github",
|
|
"owner_action": null,
|
|
"owner_action_ref": null,
|
|
"owner_sensor": null,
|
|
"owner_sensor_ref": null,
|
|
"name": "GitHub Personal Access Token",
|
|
"encrypted": true,
|
|
"value": "ghp_1234567890abcdefghijklmnopqrstuvwxyz",
|
|
"created": "2024-01-15T10:00:00Z",
|
|
"updated": "2024-01-15T10:00:00Z"
|
|
},
|
|
"message": "Key created successfully"
|
|
}
|
|
```
|
|
|
|
**Error Responses:**
|
|
|
|
- `400 Bad Request`: Validation error or encryption key not configured
|
|
- `409 Conflict`: Key with same `ref` already exists
|
|
|
|
---
|
|
|
|
### Update Key
|
|
|
|
Update an existing key's name or value. If the value is updated and encryption is enabled, it will be re-encrypted.
|
|
|
|
**Endpoint:** `PUT /api/v1/keys/:ref`
|
|
|
|
**Path Parameters:**
|
|
|
|
| Parameter | Type | Description |
|
|
|-----------|------|-------------|
|
|
| `ref` | string | Key reference |
|
|
|
|
**Request Body:**
|
|
|
|
```json
|
|
{
|
|
"name": "GitHub Token (Updated)",
|
|
"value": "ghp_newtoken123456789abcdefghijklmnopqr",
|
|
"encrypted": true
|
|
}
|
|
```
|
|
|
|
**Updatable Fields:**
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `name` | string | Update the human-readable name |
|
|
| `value` | string | Update the secret value (will be re-encrypted if needed) |
|
|
| `encrypted` | boolean | Change encryption status (re-encrypts/decrypts value) |
|
|
|
|
**Example Request:**
|
|
|
|
```bash
|
|
curl -X PUT "http://localhost:8080/api/v1/keys/github_api_token" \
|
|
-H "Authorization: Bearer <access_token>" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"name": "GitHub Token (Production)",
|
|
"value": "ghp_newtoken123456789abcdefghijklmnopqr"
|
|
}'
|
|
```
|
|
|
|
**Response:** `200 OK`
|
|
|
|
```json
|
|
{
|
|
"data": {
|
|
"id": 123,
|
|
"ref": "github_api_token",
|
|
"owner_type": "pack",
|
|
"owner": "github-integration",
|
|
"owner_identity": null,
|
|
"owner_pack": 456,
|
|
"owner_pack_ref": "github",
|
|
"owner_action": null,
|
|
"owner_action_ref": null,
|
|
"owner_sensor": null,
|
|
"owner_sensor_ref": null,
|
|
"name": "GitHub Token (Production)",
|
|
"encrypted": true,
|
|
"value": "ghp_newtoken123456789abcdefghijklmnopqr",
|
|
"created": "2024-01-15T10:00:00Z",
|
|
"updated": "2024-01-15T14:30:00Z"
|
|
},
|
|
"message": "Key updated successfully"
|
|
}
|
|
```
|
|
|
|
**Error Responses:**
|
|
|
|
- `404 Not Found`: Key not found
|
|
- `400 Bad Request`: Validation error
|
|
|
|
---
|
|
|
|
### Delete Key
|
|
|
|
Delete a secret key permanently.
|
|
|
|
**Endpoint:** `DELETE /api/v1/keys/:ref`
|
|
|
|
**Path Parameters:**
|
|
|
|
| Parameter | Type | Description |
|
|
|-----------|------|-------------|
|
|
| `ref` | string | Key reference |
|
|
|
|
**Example Request:**
|
|
|
|
```bash
|
|
curl -X DELETE "http://localhost:8080/api/v1/keys/github_api_token" \
|
|
-H "Authorization: Bearer <access_token>"
|
|
```
|
|
|
|
**Response:** `200 OK`
|
|
|
|
```json
|
|
{
|
|
"message": "Key deleted successfully",
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
**Error Responses:**
|
|
|
|
- `404 Not Found`: Key not found
|
|
|
|
---
|
|
|
|
## Use Cases
|
|
|
|
### Store API Credentials
|
|
|
|
Store third-party API credentials for use in actions:
|
|
|
|
```bash
|
|
curl -X POST "http://localhost:8080/api/v1/keys" \
|
|
-H "Authorization: Bearer <token>" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"ref": "sendgrid_api_key",
|
|
"owner_type": "pack",
|
|
"owner_pack_ref": "email",
|
|
"name": "SendGrid API Key",
|
|
"value": "SG.abcdefghijklmnopqrstuvwxyz",
|
|
"encrypted": true
|
|
}'
|
|
```
|
|
|
|
### Store Database Credentials
|
|
|
|
Store database connection credentials:
|
|
|
|
```bash
|
|
curl -X POST "http://localhost:8080/api/v1/keys" \
|
|
-H "Authorization: Bearer <token>" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"ref": "prod_db_password",
|
|
"owner_type": "system",
|
|
"name": "Production Database Password",
|
|
"value": "supersecretpassword123!",
|
|
"encrypted": true
|
|
}'
|
|
```
|
|
|
|
### Store OAuth Tokens
|
|
|
|
Store OAuth access tokens for external services:
|
|
|
|
```bash
|
|
curl -X POST "http://localhost:8080/api/v1/keys" \
|
|
-H "Authorization: Bearer <token>" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"ref": "slack_oauth_token",
|
|
"owner_type": "identity",
|
|
"owner_identity": 789,
|
|
"name": "Slack OAuth Token",
|
|
"value": "xoxb-1234567890-abcdefghijklmnopqr",
|
|
"encrypted": true
|
|
}'
|
|
```
|
|
|
|
### Retrieve Secret for Action
|
|
|
|
Actions can retrieve secrets at runtime:
|
|
|
|
```bash
|
|
# Get secret value
|
|
SECRET_VALUE=$(curl -s -X GET "http://localhost:8080/api/v1/keys/github_api_token" \
|
|
-H "Authorization: Bearer <token>" | jq -r '.data.value')
|
|
|
|
# Use in action
|
|
curl -X GET "https://api.github.com/user" \
|
|
-H "Authorization: token $SECRET_VALUE"
|
|
```
|
|
|
|
### List Secrets by Owner
|
|
|
|
List all secrets owned by a specific pack:
|
|
|
|
```bash
|
|
curl -X GET "http://localhost:8080/api/v1/keys?owner_type=pack&owner=github-integration" \
|
|
-H "Authorization: Bearer <token>"
|
|
```
|
|
|
|
### Update Expired Token
|
|
|
|
Update a secret when credentials change:
|
|
|
|
```bash
|
|
curl -X PUT "http://localhost:8080/api/v1/keys/github_api_token" \
|
|
-H "Authorization: Bearer <token>" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"value": "ghp_newtoken_after_rotation"
|
|
}'
|
|
```
|
|
|
|
---
|
|
|
|
## Security Best Practices
|
|
|
|
### 1. Always Encrypt Sensitive Data
|
|
|
|
**Always** set `encrypted: true` when creating keys containing sensitive data:
|
|
|
|
```json
|
|
{
|
|
"ref": "aws_secret_key",
|
|
"name": "AWS Secret Access Key",
|
|
"value": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
|
|
"encrypted": true
|
|
}
|
|
```
|
|
|
|
### 2. Use Descriptive References
|
|
|
|
Use clear, descriptive references that indicate the purpose:
|
|
|
|
✅ Good:
|
|
- `github_api_token`
|
|
- `prod_db_password`
|
|
- `slack_oauth_token`
|
|
|
|
❌ Bad:
|
|
- `token1`
|
|
- `secret`
|
|
- `key`
|
|
|
|
### 3. Associate with Owners
|
|
|
|
Always associate secrets with appropriate owners for better organization:
|
|
|
|
```json
|
|
{
|
|
"ref": "github_deploy_key",
|
|
"owner_type": "action",
|
|
"owner_action_ref": "deploy_to_production",
|
|
"name": "GitHub Deployment Key",
|
|
"value": "ssh-rsa AAAAB3NzaC1...",
|
|
"encrypted": true
|
|
}
|
|
```
|
|
|
|
### 4. Rotate Secrets Regularly
|
|
|
|
Implement a secret rotation policy:
|
|
|
|
```bash
|
|
# Update secret with new value
|
|
curl -X PUT "http://localhost:8080/api/v1/keys/api_key" \
|
|
-H "Authorization: Bearer <token>" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"value": "new_rotated_value"}'
|
|
```
|
|
|
|
### 5. Never Log Secret Values
|
|
|
|
Never log or print secret values in application code:
|
|
|
|
```python
|
|
# ❌ BAD - Logs secret value
|
|
logger.info(f"Using API key: {secret_value}")
|
|
|
|
# ✅ GOOD - Logs redacted info
|
|
logger.info(f"Using API key: {secret_value[:4]}...{secret_value[-4:]}")
|
|
```
|
|
|
|
### 6. Limit Access
|
|
|
|
Use authentication and authorization to limit who can access secrets:
|
|
|
|
- Implement RBAC (future enhancement)
|
|
- Audit secret access (future enhancement)
|
|
- Rotate tokens regularly
|
|
- Use least-privilege principle
|
|
|
|
### 7. Backup Encryption Key
|
|
|
|
**Critical**: Securely backup your encryption key. If you lose it, encrypted secrets cannot be recovered:
|
|
|
|
```bash
|
|
# Backup encryption key to secure location
|
|
echo "$ATTUNE__SECURITY__ENCRYPTION_KEY" | gpg --encrypt > encryption_key.gpg.backup
|
|
```
|
|
|
|
### 8. Use Environment-Specific Secrets
|
|
|
|
Use different secrets for different environments:
|
|
|
|
- `dev_api_key` - Development environment
|
|
- `staging_api_key` - Staging environment
|
|
- `prod_api_key` - Production environment
|
|
|
|
---
|
|
|
|
## Error Handling
|
|
|
|
### Common Error Codes
|
|
|
|
| Status Code | Description |
|
|
|-------------|-------------|
|
|
| `400 Bad Request` | Invalid input, validation error, or encryption not configured |
|
|
| `401 Unauthorized` | Missing or invalid authentication token |
|
|
| `404 Not Found` | Key not found |
|
|
| `409 Conflict` | Key with same reference already exists |
|
|
| `500 Internal Server Error` | Encryption/decryption error or server error |
|
|
|
|
### Example Error Responses
|
|
|
|
**Encryption Key Not Configured:**
|
|
|
|
```json
|
|
{
|
|
"error": "Cannot encrypt: encryption key not configured on server",
|
|
"status": 400
|
|
}
|
|
```
|
|
|
|
**Key Already Exists:**
|
|
|
|
```json
|
|
{
|
|
"error": "Key with ref 'github_api_token' already exists",
|
|
"status": 409
|
|
}
|
|
```
|
|
|
|
**Decryption Failed:**
|
|
|
|
```json
|
|
{
|
|
"error": "Failed to decrypt key: Decryption failed",
|
|
"status": 500
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Encryption Details
|
|
|
|
### Algorithm
|
|
|
|
- **Cipher**: AES-256-GCM (Galois/Counter Mode)
|
|
- **Key Size**: 256 bits (32 bytes)
|
|
- **Nonce Size**: 96 bits (12 bytes)
|
|
- **Authentication**: Built-in AEAD authentication
|
|
|
|
### Key Derivation
|
|
|
|
The server's encryption key (configured in `security.encryption_key`) is hashed using SHA-256 to derive the actual AES-256 key:
|
|
|
|
```
|
|
AES_KEY = SHA256(encryption_key)
|
|
```
|
|
|
|
### Encrypted Value Format
|
|
|
|
Encrypted values are stored as base64-encoded strings containing:
|
|
|
|
```
|
|
BASE64(nonce || ciphertext || authentication_tag)
|
|
```
|
|
|
|
Where:
|
|
- `nonce`: 12 bytes (randomly generated for each encryption)
|
|
- `ciphertext`: Variable length (encrypted plaintext)
|
|
- `authentication_tag`: 16 bytes (GCM authentication tag)
|
|
|
|
### Security Properties
|
|
|
|
- **Confidentiality**: AES-256 encryption prevents unauthorized reading
|
|
- **Authenticity**: GCM mode prevents tampering and forgery
|
|
- **Non-deterministic**: Random nonces ensure same plaintext produces different ciphertexts
|
|
- **Forward Security**: Key rotation possible (requires re-encrypting all secrets)
|
|
|
|
---
|
|
|
|
## Related Resources
|
|
|
|
- [Action Management API](./api-actions.md) - Actions that use secrets
|
|
- [Pack Management API](./api-packs.md) - Packs that own secrets
|
|
- [Authentication Guide](./authentication.md) - API authentication details
|
|
- [Configuration Guide](./configuration.md) - Server configuration including encryption key
|
|
|
|
---
|
|
|
|
## Future Enhancements
|
|
|
|
### Planned Features
|
|
|
|
1. **Key Rotation**: Automatic re-encryption when changing encryption keys
|
|
2. **Access Control Lists**: Fine-grained permissions on who can access which secrets
|
|
3. **Audit Logging**: Detailed logs of all secret access and modifications
|
|
4. **Secret Expiration**: Time-to-live (TTL) for temporary secrets
|
|
5. **Secret Versioning**: Keep history of secret value changes
|
|
6. **Import/Export**: Secure import/export of secrets with encryption
|
|
7. **Secret References**: Reference secrets from other secrets
|
|
8. **Integration with Vaults**: Support for HashiCorp Vault, AWS Secrets Manager, etc.
|
|
|
|
---
|
|
|
|
**Last Updated:** 2024-01-13
|
|
**API Version:** v1
|
|
**Security Note:** Always use HTTPS in production to protect secrets in transit |