@@ -15,7 +15,12 @@ Within a zone, the token can be limited to one or more records.
1515Containers are available under [ Packages] ( https://github.com/akquinet/powerdns-api-proxy/pkgs/container/powerdns-api-proxy ) .
1616
1717``` bash
18- docker run -v config:/config -e PROXY_CONFIG_PATH=/config/config.yaml -e LOG_LEVEL=WARNING --name powerdns-api-proxy ghcr.io/akquinet/powerdns-api-proxy:latest
18+ docker run -v config:/config \
19+ -e PROXY_CONFIG_PATH=/config/config.yaml \
20+ -e LOG_LEVEL=INFO \
21+ -e LOG_FORMAT=json \
22+ --name powerdns-api-proxy \
23+ ghcr.io/akquinet/powerdns-api-proxy:latest
1924```
2025
2126### Authentication
@@ -303,6 +308,78 @@ index_enabled: false # default is true
303308index_html: "<html><body><h1>PowerDNS API Proxy</h1></body></html>"
304309` ` `
305310
311+ # # Logging
312+
313+ # ## Environment Variables
314+
315+ ` ` ` bash
316+ LOG_LEVEL=DEBUG # Optional: DEBUG, INFO, WARNING, ERROR (default: DEBUG)
317+ LOG_FORMAT=json # Optional: "text" (default) or "json" for structured logging
318+ ALLOWED_HOSTS=0.0.0.0 # Optional: Host to bind to (default: 0.0.0.0)
319+ LISTEN_PORT=8000 # Optional: Port to listen on (default: 8000)
320+ ` ` `
321+
322+ When `LOG_FORMAT=json` is set, all logs (application and uvicorn access logs) will be output in JSON format.
323+
324+ Set `AUDIT_LOGGING=false` to disable automatic audit logging of API requests.
325+
326+ # ## Audit Logging
327+
328+ All API operations (GET, POST, PUT, PATCH, DELETE) are automatically logged to stderr with structured data via middleware.
329+
330+ This includes both successful operations and forbidden attempts (HTTP 403).
331+
332+ Each audit log entry contains :
333+
334+ * `timestamp`: ISO 8601 timestamp
335+ * `level`: Log level (INFO)
336+ * `event_type`: "audit" for easy filtering
337+ * `audit`: Structured audit data object containing:
338+ * `environment`: Name of the authenticated environment/token
339+ * `method`: HTTP method (GET, POST, PUT, PATCH, DELETE)
340+ * `path`: Resource path that was accessed/modified
341+ * `status_code`: HTTP response status code
342+ * `payload`: Request payload (optional, for write operations; omitted for sensitive endpoints like `/cryptokeys` and `/tsigkeys`)
343+ * `query_params`: Query parameters (optional, for GET requests)
344+
345+ # ### Text Format (default)
346+
347+ ```
348+ INFO - 2026-03-26 12:03:21,323 - powerdns_api_proxy - proxy.py - audit - 70 - AUDIT: Test1 PATCH /zones/example.com 204 payload={'rrsets': [ ] }
349+ INFO - 2026-03-26 12:03:21,323 - powerdns_api_proxy - proxy.py - audit - 70 - AUDIT: Test1 GET /zones 200 query_params={'rrsets': 'true'}
350+ INFO - 2026-03-26 12:03:21,323 - powerdns_api_proxy - proxy.py - audit - 70 - AUDIT: Test1 DELETE /zones/test.com 403
351+ ```
352+
353+ #### JSON Format (set LOG_FORMAT=json)
354+
355+ ```json
356+ {"timestamp": "2026-03-26T11:39:29", "level": "INFO", "event_type": "audit", "audit": {"environment": "Test1", "method": "PATCH", "path": "/zones/example.com", "status_code": 204, "payload": {"rrsets": [...]}}}
357+ ```
358+
359+ #### Analyzing Audit Logs
360+
361+ With JSON format enabled, you can use ` jq ` to filter and analyze audit logs:
362+
363+ ``` bash
364+ # Filter only audit events
365+ docker logs powerdns-api-proxy 2>&1 | jq ' select(.event_type == "audit")'
366+
367+ # Filter by environment
368+ docker logs powerdns-api-proxy 2>&1 | jq ' select(.event_type == "audit" and .audit.environment == "Test1")'
369+
370+ # Filter by HTTP method
371+ docker logs powerdns-api-proxy 2>&1 | jq ' select(.event_type == "audit" and .audit.method == "PATCH")'
372+
373+ # Filter by zone
374+ docker logs powerdns-api-proxy 2>&1 | jq ' select(.event_type == "audit" and (.audit.path | contains("/zones/example.com")))'
375+
376+ # Extract only key audit fields
377+ docker logs powerdns-api-proxy 2>&1 | jq ' select(.event_type == "audit") | {timestamp, environment: .audit.environment, method: .audit.method, path: .audit.path, status: .audit.status_code}'
378+
379+ # Show failed attempts (403)
380+ docker logs powerdns-api-proxy 2>&1 | jq ' select(.event_type == "audit" and .audit.status_code == 403)'
381+ ```
382+
306383## Development
307384
308385### Install requirements
0 commit comments