Skip to content

Audit logging#199

Merged
rwxd merged 1 commit into
mainfrom
audit-log
Mar 27, 2026
Merged

Audit logging#199
rwxd merged 1 commit into
mainfrom
audit-log

Conversation

@rwxd
Copy link
Copy Markdown
Contributor

@rwxd rwxd commented Mar 26, 2026

Add Audit Logging with JSON Support

Adds automatic audit logging for all API operations via middleware.

Features

  • Logs all requests (GET, POST, PUT, PATCH, DELETE) including forbidden attempts (403)
  • Structured JSON format with LOG_FORMAT=json
  • Captures environment, method, path, status code, payload, and query params

Closes #182

@rwxd rwxd force-pushed the audit-log branch 11 times, most recently from 0d5e0f2 to 8674135 Compare March 26, 2026 12:50
@rwxd rwxd requested review from Copilot and kuhball March 26, 2026 12:51
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds structured audit logging across the FastAPI proxy, with optional JSON output, and updates the runtime entrypoint to start via python -m powerdns_api_proxy so Uvicorn can be configured with a custom logging config.

Changes:

  • Introduces AuditMiddleware to emit audit log events for /api/v1/* requests (including unauthorized/forbidden responses).
  • Adds AuditLogger.audit() and a JSONFormatter to support structured JSON logs when LOG_FORMAT=json.
  • Updates runtime/docs/tooling: Uvicorn log_config, new __main__.py runner, README logging docs, Docker/Makefile tweaks, and new unit tests.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
tests/unit/middleware_test.py Adds tests asserting audit events are emitted by middleware.
tests/unit/logging_test.py Adds tests for audit log formatting (text + JSON).
powerdns_api_proxy/uvicorn_config.py Adds dictConfig for Uvicorn logging with optional JSON formatter.
powerdns_api_proxy/proxy.py Registers AuditMiddleware on the FastAPI app.
powerdns_api_proxy/middleware.py Implements audit logging middleware capturing env/method/path/status/payload/query params.
powerdns_api_proxy/logging.py Adds AuditLogger + JSONFormatter and toggles formatter via LOG_FORMAT.
powerdns_api_proxy/config.py Minor refactor in load_config return path (no functional change).
powerdns_api_proxy/main.py Runs Uvicorn programmatically with LOGGING_CONFIG.
README.md Documents JSON/audit logging and adds env var examples.
Makefile Switches make run to python -m powerdns_api_proxy.
Dockerfile Switches CMD to python -m powerdns_api_proxy and installs jq.
Comments suppressed due to low confidence (1)

powerdns_api_proxy/logging.py:91

  • Audit events are logged at INFO (AuditLogger.audit() uses self.info(...)), but the stderr handler is filtered by LOG_LEVEL. With LOG_LEVEL=WARNING (as shown in the README), audit logs won’t be emitted to stderr. Consider ensuring audit logs bypass this filter (e.g., a dedicated audit handler/logger at INFO) or documenting the requirement explicitly.
default_stream_handler = logging.StreamHandler(stderr)
default_stream_handler.setLevel(LOG_LEVEL)
default_stream_handler.setFormatter(default_formatter)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread powerdns_api_proxy/middleware.py
Comment thread powerdns_api_proxy/middleware.py Outdated
Comment thread powerdns_api_proxy/middleware.py Outdated
Comment thread tests/unit/logging_test.py
Comment thread Dockerfile
Comment thread powerdns_api_proxy/middleware.py Outdated
Comment thread tests/unit/middleware_test.py
Comment thread powerdns_api_proxy/logging.py
Comment thread powerdns_api_proxy/logging.py
Comment thread README.md Outdated
@rwxd rwxd force-pushed the audit-log branch 2 times, most recently from 6d8e212 to 93f37d6 Compare March 26, 2026 13:09
@rwxd rwxd requested a review from Copilot March 26, 2026 13:10
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 10 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread powerdns_api_proxy/middleware.py
Comment thread powerdns_api_proxy/middleware.py
Comment on lines +24 to +42
try:
token = request.headers.get("X-API-Key", "")
if token:
environment = get_environment_for_token(_config, token)
environment_name = environment.name
except Exception:
pass

# Store request body for logging (only for write operations)
payload = None
if request.method in ["POST", "PUT", "PATCH"]:
try:
# Read raw request body bytes; FastAPI/Starlette will cache the body for downstream handlers
body_bytes = await request.body()
if body_bytes:
payload = json.loads(body_bytes)
except Exception:
pass

Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are multiple broad except Exception: pass blocks around token parsing and payload JSON parsing. This can hide real bugs (e.g., config errors) and makes troubleshooting difficult. Narrow these to the expected exceptions (e.g., ValueError from get_environment_for_token, json.JSONDecodeError) and consider logging at debug level when unexpected exceptions occur.

Copilot uses AI. Check for mistakes.
Comment thread powerdns_api_proxy/middleware.py
Comment thread tests/unit/middleware_test.py
Comment thread README.md
Comment thread README.md
Comment thread powerdns_api_proxy/__main__.py Outdated
Comment thread README.md
Comment thread powerdns_api_proxy/middleware.py
WIP

feat: audit log and structured logging
@rwxd rwxd merged commit ba3bb35 into main Mar 27, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Audit logging

3 participants