|
| 1 | +# Audit Trail Feature for Docker Agent |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +The Audit Trail feature provides cryptographic, tamper-proof logging of all agent actions for governance and compliance purposes. Each tool call, file operation, HTTP request, or command execution is recorded with a cryptographic signature that can be independently verified. |
| 6 | + |
| 7 | +## Features |
| 8 | + |
| 9 | +- **Cryptographic Signing**: Each audit record is signed using Ed25519 digital signatures |
| 10 | +- **Chain Integrity**: Records are chained together using hash links (like a blockchain) |
| 11 | +- **Tamper-Proof**: Any modification to audit records can be detected |
| 12 | +- **Independent Verification**: Records can be verified without trusting the agent |
| 13 | +- **Configurable Recording**: Fine-grained control over what actions to record |
| 14 | +- **Privacy Controls**: Options to exclude sensitive input/output content |
| 15 | + |
| 16 | +## Configuration |
| 17 | + |
| 18 | +Enable auditing in your agent configuration file: |
| 19 | + |
| 20 | +```yaml |
| 21 | +audit: |
| 22 | + enabled: true |
| 23 | + storage_path: ./audit-logs |
| 24 | + key_path: ./audit-key |
| 25 | + record_tool_calls: true |
| 26 | + record_file_ops: true |
| 27 | + record_http: true |
| 28 | + record_commands: true |
| 29 | + record_sessions: true |
| 30 | + include_input_content: false |
| 31 | + include_output_content: false |
| 32 | +``` |
| 33 | +
|
| 34 | +### Configuration Options |
| 35 | +
|
| 36 | +| Field | Type | Default | Description | |
| 37 | +|-------|------|---------|-------------| |
| 38 | +| `enabled` | boolean | `false` | Enable audit trail recording | |
| 39 | +| `storage_path` | string | `~/.cagent/audit` | Directory to store audit records | |
| 40 | +| `key_path` | string | `{storage_path}/audit_key` | Path to the Ed25519 signing key | |
| 41 | +| `record_tool_calls` | boolean | `true` | Record tool call actions | |
| 42 | +| `record_file_ops` | boolean | `true` | Record file read/write/delete operations | |
| 43 | +| `record_http` | boolean | `true` | Record HTTP requests and responses | |
| 44 | +| `record_commands` | boolean | `true` | Record shell command executions | |
| 45 | +| `record_sessions` | boolean | `true` | Record session start/end events | |
| 46 | +| `include_input_content` | boolean | `false` | Include user input in audit records | |
| 47 | +| `include_output_content` | boolean | `false` | Include tool output in audit records | |
| 48 | + |
| 49 | +## Audit Record Structure |
| 50 | + |
| 51 | +Each audit record contains: |
| 52 | + |
| 53 | +```json |
| 54 | +{ |
| 55 | + "id": "unique-record-id", |
| 56 | + "timestamp": "2026-03-28T12:00:00Z", |
| 57 | + "action_type": "tool_call", |
| 58 | + "session_id": "session-123", |
| 59 | + "agent_name": "my-agent", |
| 60 | + "action": { |
| 61 | + "tool_name": "read_file", |
| 62 | + "tool_type": "function", |
| 63 | + "tool_call_id": "call-abc", |
| 64 | + "arguments": {"path": "/test/file.txt"} |
| 65 | + }, |
| 66 | + "result": { |
| 67 | + "success": true, |
| 68 | + "output": "file content", |
| 69 | + "duration": "100ms" |
| 70 | + }, |
| 71 | + "previous_hash": "sha256-of-previous-record", |
| 72 | + "hash": "sha256-of-this-record", |
| 73 | + "signature": "ed25519-signature", |
| 74 | + "public_key": "base64-encoded-public-key" |
| 75 | +} |
| 76 | +``` |
| 77 | + |
| 78 | +## Action Types |
| 79 | + |
| 80 | +The audit system records the following action types: |
| 81 | + |
| 82 | +- `tool_call`: Tool invocations with arguments and results |
| 83 | +- `file_read`: File read operations |
| 84 | +- `file_write`: File write operations |
| 85 | +- `file_delete`: File deletion operations |
| 86 | +- `http_request`: HTTP requests with method, URL, and response |
| 87 | +- `command_exec`: Shell command executions |
| 88 | +- `session_start`: Session initialization |
| 89 | +- `session_end`: Session termination |
| 90 | +- `user_input`: User input (if enabled) |
| 91 | +- `model_response`: LLM response metadata |
| 92 | +- `handoff`: Agent handoff events |
| 93 | +- `error`: Error conditions |
| 94 | + |
| 95 | +## Verification |
| 96 | + |
| 97 | +### Programmatic Verification |
| 98 | + |
| 99 | +Use the audit package to verify records: |
| 100 | + |
| 101 | +```go |
| 102 | +import "github.com/docker/docker-agent/pkg/audit" |
| 103 | +
|
| 104 | +// Verify a single record |
| 105 | +valid, err := audit.VerifyRecord(record) |
| 106 | +if err != nil { |
| 107 | + log.Fatalf("Verification failed: %v", err) |
| 108 | +} |
| 109 | +
|
| 110 | +// Verify an entire chain (all records for a session) |
| 111 | +records := getRecordsForSession(sessionID) |
| 112 | +valid, err := audit.VerifyChain(records) |
| 113 | +if err != nil { |
| 114 | + log.Fatalf("Chain verification failed: %v", err) |
| 115 | +} |
| 116 | +``` |
| 117 | + |
| 118 | +### Manual Verification |
| 119 | + |
| 120 | +1. Extract the public key from any audit record |
| 121 | +2. Verify the signature using the public key |
| 122 | +3. Verify the hash matches the record content |
| 123 | +4. Verify the chain by checking previous_hash links |
| 124 | + |
| 125 | +## Storage |
| 126 | + |
| 127 | +Audit records are stored as JSON files organized by session ID: |
| 128 | + |
| 129 | +``` |
| 130 | +audit-logs/ |
| 131 | +├── session-abc123/ |
| 132 | +│ ├── record-001.json |
| 133 | +│ ├── record-002.json |
| 134 | +│ └── ... |
| 135 | +├── session-def456/ |
| 136 | +│ └── ... |
| 137 | +└── audit-key (signing key) |
| 138 | +``` |
| 139 | + |
| 140 | +## Security Considerations |
| 141 | + |
| 142 | +### Key Management |
| 143 | + |
| 144 | +- The signing key is automatically generated on first run |
| 145 | +- Store the key securely with appropriate file permissions (0600) |
| 146 | +- Backup the key for long-term verification capability |
| 147 | +- Consider using HSM or secure key storage for production deployments |
| 148 | + |
| 149 | +### Privacy |
| 150 | + |
| 151 | +- By default, input and output content is NOT recorded |
| 152 | +- Enable content recording only when necessary for compliance |
| 153 | +- Consider encrypting audit storage at rest |
| 154 | +- Implement appropriate access controls for audit logs |
| 155 | + |
| 156 | +### Integrity |
| 157 | + |
| 158 | +- The chain structure makes tampering evident |
| 159 | +- Each record's hash depends on the previous record |
| 160 | +- Signatures prevent unauthorized modifications |
| 161 | +- Regular verification recommended for compliance |
| 162 | + |
| 163 | +## Compliance Use Cases |
| 164 | + |
| 165 | +### SOC 2 Compliance |
| 166 | + |
| 167 | +- Demonstrates control over AI agent actions |
| 168 | +- Provides audit trail for access reviews |
| 169 | +- Enables incident investigation |
| 170 | + |
| 171 | +### GDPR Compliance |
| 172 | + |
| 173 | +- Records data access operations |
| 174 | +- Supports data subject access requests |
| 175 | +- Enables privacy impact assessments |
| 176 | + |
| 177 | +### Financial Regulations |
| 178 | + |
| 179 | +- Provides transaction audit trail |
| 180 | +- Supports regulatory examinations |
| 181 | +- Enables forensic analysis |
| 182 | + |
| 183 | +## Example Usage |
| 184 | + |
| 185 | +See `examples/audit-example.yaml` for a complete example configuration. |
| 186 | + |
| 187 | +## API Reference |
| 188 | + |
| 189 | +### Creating an Auditor |
| 190 | + |
| 191 | +```go |
| 192 | +auditor, err := audit.New(audit.Config{ |
| 193 | + Enabled: true, |
| 194 | + StoragePath: "/var/log/audit", |
| 195 | + KeyPath: "/secure/keys/audit-key", |
| 196 | +}) |
| 197 | +``` |
| 198 | + |
| 199 | +### Recording Actions |
| 200 | + |
| 201 | +```go |
| 202 | +// Tool call |
| 203 | +record, err := auditor.RecordToolCall(ctx, sess, agentName, toolCall, result, duration) |
| 204 | +
|
| 205 | +// File operation |
| 206 | +record, err := auditor.RecordFileOperation(ctx, sess, agentName, actionType, path, content, mode) |
| 207 | +
|
| 208 | +// HTTP request |
| 209 | +record, err := auditor.RecordHTTPRequest(ctx, sess, agentName, method, url, headers, body, statusCode, response, duration) |
| 210 | +
|
| 211 | +// Session events |
| 212 | +record, err := auditor.RecordSessionStart(ctx, sess, agentName) |
| 213 | +record, err := auditor.RecordSessionEnd(ctx, sess, agentName, reason) |
| 214 | +``` |
| 215 | + |
| 216 | +### Exporting Records |
| 217 | + |
| 218 | +```go |
| 219 | +// Export all records for a session |
| 220 | +data, err := auditor.ExportRecords(sessionID) |
| 221 | +
|
| 222 | +// Get public key for verification |
| 223 | +pubKey := auditor.PublicKey() |
| 224 | +``` |
| 225 | + |
| 226 | +## Troubleshooting |
| 227 | + |
| 228 | +### Audit Records Not Being Created |
| 229 | + |
| 230 | +1. Check that `audit.enabled` is set to `true` |
| 231 | +2. Verify the storage directory is writable |
| 232 | +3. Check logs for initialization errors |
| 233 | + |
| 234 | +### Verification Failures |
| 235 | + |
| 236 | +1. Ensure you're using the correct public key |
| 237 | +2. Check that records haven't been modified |
| 238 | +3. Verify the chain hasn't been broken |
| 239 | + |
| 240 | +### Performance Impact |
| 241 | + |
| 242 | +- Auditing adds minimal overhead (<1ms per record) |
| 243 | +- Consider async writing for high-volume scenarios |
| 244 | +- Monitor storage growth in long-running sessions |
| 245 | + |
| 246 | +## Future Enhancements |
| 247 | + |
| 248 | +- Encrypted audit storage |
| 249 | +- Remote audit log shipping |
| 250 | +- Integration with SIEM systems |
| 251 | +- Audit log rotation and retention policies |
| 252 | +- Real-time alerting on specific actions |
0 commit comments