Operations
Monitoring
Audit logs, log formats, and alerting recommendations.
Monitoring
OpenApe produces audit logs at three levels: IdP, proxy, and escapes. All use JSONL format (one JSON object per line) for easy parsing.
Audit Log Sources
| Source | Location | What it logs |
|---|---|---|
| IdP | Application logs (stdout/stderr) | Logins, registrations, grant decisions, agent enrollment |
| Proxy | Configurable (audit_log in TOML) | Every HTTP request, rule evaluation, grant requests |
| escapes | /var/log/openape/audit.log | Every command execution, verification results |
escapes Audit Log
Every execution attempt is logged:
{"timestamp":"2025-01-15T10:30:00Z","grant_id":"abc123","command":["systemctl","restart","nginx"],"requester":"agent+deploy@example.com","approver":"admin@example.com","result":"success","exit_code":0,"duration_ms":1234}
Failed attempts include error details:
{"timestamp":"2025-01-15T10:31:00Z","error":"cmd_hash mismatch","command":["rm","-rf","/"],"requester":"agent+deploy@example.com","result":"verification_failed"}
Fields
| Field | Type | Description |
|---|---|---|
timestamp | string | ISO 8601 |
grant_id | string | Grant UUID |
command | string[] | Command that was (or would have been) executed |
requester | string | Agent email |
approver | string | Who approved the grant |
result | string | success, verification_failed, exec_failed |
exit_code | number | Command exit code |
duration_ms | number | Execution time |
error | string | Error message (on failure) |
Proxy Audit Log
Every request through the proxy is logged:
{"ts":"2025-01-15T10:30:00.123Z","agent":"agent+deploy@example.com","action":"allow","domain":"api.github.com","method":"GET","path":"/repos/org/repo","grant_id":null,"rule":"allow[0]","waited_ms":0}
Fields
| Field | Type | Description |
|---|---|---|
ts | string | ISO 8601 with milliseconds |
agent | string | Agent email |
action | string | allow, deny, grant_approved, grant_denied, grant_timeout, error |
domain | string | Target domain |
method | string | HTTP method |
path | string | Request path |
grant_id | string | null | Associated grant ID (if grant_required rule matched) |
rule | string | Which rule matched (e.g., allow[0], deny[2]) |
waited_ms | number | Time spent waiting for grant approval |
request_hash | string | Request fingerprint for deduplication |
error | string | Error message (if action is error) |
Querying Logs
Find all denied grants
grep '"action":"deny"' /var/log/openape-proxy/audit.jsonl | jq .
Find failed escapes executions
grep '"result":"verification_failed"' /var/log/openape/audit.log | jq .
Count requests per agent
cat /var/log/openape-proxy/audit.jsonl | jq -r '.agent' | sort | uniq -c | sort -rn
Find all actions by a specific agent
grep 'agent+deploy@example.com' /var/log/openape-proxy/audit.jsonl | jq -c '{ts, action, domain, method}'
Alerting Recommendations
Critical Alerts
| Condition | What it means | Query |
|---|---|---|
Multiple verification_failed from same agent | Possible key compromise or misconfiguration | result == "verification_failed" count > 5 in 1h |
cmd_hash mismatch | Someone is trying to run a different command than approved | error contains "cmd_hash" |
| Unknown agent email in logs | Unauthorized agent attempting access | agent not in known_agents |
| Management Token used from unexpected IP | Possible token leak | IdP access logs |
Warning Alerts
| Condition | What it means |
|---|---|
High volume of grant_timeout | Approvers not responding to grant requests |
deny rate > 50% | Rules may be too restrictive, or agents misconfigured |
once grants created but never consumed | Agents requesting but not using grants |
Log Rotation
escapes
# logrotate config: /etc/logrotate.d/openape
/var/log/openape/audit.log {
daily
rotate 90
compress
delaycompress
missingok
notifempty
}
Proxy
Configure rotation for the proxy audit log similarly, or pipe to a log aggregation service (Datadog, Loki, etc.).
Integration with Log Aggregation
JSONL format is directly compatible with:
- Datadog — use the file tailing agent
- Grafana Loki — use promtail with JSON parsing
- ELK Stack — use Filebeat with JSON input
- CloudWatch — pipe to CloudWatch Logs agent
Each JSONL entry is a self-contained JSON object, so no multi-line parsing is needed.