Audit logging package for FastAPI applications
Project description
fastapi-audit
Audit logging package for FastAPI applications.
Features
- HTTP Request/Response Capture: Logs method, path, status code, response time, IP, and user agent
- JWT-based Actor Identification: Extracts actor ID, type, and email from JWT tokens
- ORM-level Diff Tracking: Captures INSERT, UPDATE, and DELETE operations across application sessions
- Tenant-Aware Context Support: Works with application-provided tenant context
- Sensitive Data Redaction: Automatically redacts passwords, tokens, secrets, and similar fields
- Fire-and-Forget Writes: Writes audit records asynchronously to avoid adding request latency
- Manual Audit Logging: Supports background tasks and non-HTTP contexts
Installation
From PyPI
# Core package (requires asyncpg for PostgreSQL)
pip install fastapi-audit[asyncpg]
Local Development
pip install -e /path/to/audit[asyncpg]
Database Driver
Only PostgreSQL with asyncpg is tested and supported at this time. Install it via the [asyncpg] extra:
pip install fastapi-audit[asyncpg]
Quick Start
from contextlib import asynccontextmanager
from sqlalchemy.ext.asyncio import create_async_engine
from fastapi import FastAPI
from fastapi_audit import AuditMiddleware, AuditConfig, create_tables
engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/audit_db")
@asynccontextmanager
async def lifespan(app: FastAPI):
await create_tables(engine)
yield
await engine.dispose()
app = FastAPI(lifespan=lifespan)
app.add_middleware(
AuditMiddleware,
config=AuditConfig(control_db_url=str(engine.url))
)
Database Setup
Before using the middleware, provision the audit_logs table in your audit database:
from sqlalchemy.ext.asyncio import create_async_engine
from fastapi_audit import create_tables
engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/audit_db")
await create_tables(engine)
The create_tables() helper creates the audit_logs table and its associated enum type. Call it once during deployment or as part of a migration step.
Configuration
from fastapi_audit import AuditConfig
config = AuditConfig(
# Required: Connection URL for the audit database
control_db_url="postgresql+asyncpg://user:pass@localhost/audit_db",
# Optional: Fields to redact (merged with defaults)
redact_fields={"password", "token", "secret", "custom_field"},
# Optional: Paths to exclude from audit logging
exclude_paths={"/health", "/metrics"},
# Optional: Map incoming actor_type values to canonical public values
actor_type_aliases={"ops_admin": "platform_admin"},
# Optional: Capture request/response bodies
capture_request_body=True,
capture_response_body=True,
# Optional: Enable ORM diff capture
capture_orm_diffs=True,
# Optional: Log requests without authenticated actors
log_anonymous=False,
)
Tenant Context
If your application is tenant-aware, the middleware can read tenant context from:
# Example: in your own tenant-resolution middleware
request.state.tenant = Tenant(tenant_id="...", tenant_slug="example-tenant")
The tenant object should have tenant_id and tenant_slug attributes.
JWT Token Requirements
The middleware extracts actor information from JWT tokens in the Authorization header.
Expected JWT claims:
| Claim | Required | Description |
|---|---|---|
sub |
Yes | User ID |
actor_type |
No | platform_admin, tenant_user, or anonymous (default) |
email |
No | User email address |
Example JWT payload:
{
"sub": "user-123",
"actor_type": "platform_admin",
"email": "user@example.com"
}
Organization-specific actor types can be mapped to canonical public values via
AuditConfig.actor_type_aliases.
Manual Audit Logging
For background tasks or events outside the HTTP lifecycle:
from fastapi_audit import audit_log, ActorType
from sqlalchemy.ext.asyncio import AsyncSession
async def provision_tenant(db: AsyncSession):
await audit_log(
db=db,
action="tenant.provisioned",
actor_id="admin-user-id",
actor_type=ActorType.PLATFORM_ADMIN,
actor_email="admin@example.com",
tenant_id="tenant-uuid",
tenant_slug="example-tenant",
metadata={"plan": "pro", "region": "us-east"}
)
Environment Variables
All configuration can be set via environment variables with the AUDIT_ prefix:
export AUDIT_CONTROL_DB_URL="postgresql+asyncpg://..."
export AUDIT_CAPTURE_ORM_DIFFS="true"
export AUDIT_LOG_ANONYMOUS="false"
Architecture
HTTP Layer
The middleware intercepts requests and captures:
- Request metadata such as method, path, and query params
- Response metadata such as status code and response time
- Actor information from JWT claims
- Optional tenant context from
request.state.tenant
ORM Layer
SQLAlchemy event listeners capture database changes:
- Class-level listeners on
AsyncSessionwork across application sessions - Context variables isolate diffs per request
- INSERT, UPDATE, and DELETE operations are recorded
Storage
All audit logs are written to a single audit_logs table in the audit database,
providing a unified view of application activity.
Requirements
- Python 3.11+
- FastAPI / Starlette
- SQLAlchemy 2.0+ with async support
- Pydantic v2
- asyncpg (via
pip install fastapi-audit[asyncpg])
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fastapi_audit-0.2.3.tar.gz.
File metadata
- Download URL: fastapi_audit-0.2.3.tar.gz
- Upload date:
- Size: 26.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b058210e3303f6a45ba4d56ae01b93b39847023fedc35f1a630dea6535c09567
|
|
| MD5 |
f51cf6ba8c79803bb9bb8669b020d1c3
|
|
| BLAKE2b-256 |
68f7d4e06dbb0f8c55f813f60103bcb9d1b9d7636f43deb84cfc07f50ab4a116
|
Provenance
The following attestation bundles were made for fastapi_audit-0.2.3.tar.gz:
Publisher:
publish.yml on tanmaysheoran/fastapi-audit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastapi_audit-0.2.3.tar.gz -
Subject digest:
b058210e3303f6a45ba4d56ae01b93b39847023fedc35f1a630dea6535c09567 - Sigstore transparency entry: 1214495465
- Sigstore integration time:
-
Permalink:
tanmaysheoran/fastapi-audit@ed5a5773a62d79f2ecf21694159a5c9625d0446c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/tanmaysheoran
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ed5a5773a62d79f2ecf21694159a5c9625d0446c -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file fastapi_audit-0.2.3-py3-none-any.whl.
File metadata
- Download URL: fastapi_audit-0.2.3-py3-none-any.whl
- Upload date:
- Size: 31.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0d13983b2b1051423b4a85a72a2631dc6c05b226c0005be3893fa8fd90dd88bd
|
|
| MD5 |
2a489a3c5148adb7d794c18ab8ad48b6
|
|
| BLAKE2b-256 |
53b3857fb814e3e39634c3b4fff5ad52e1f12b5166229198d8ebc19d1afa586c
|
Provenance
The following attestation bundles were made for fastapi_audit-0.2.3-py3-none-any.whl:
Publisher:
publish.yml on tanmaysheoran/fastapi-audit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastapi_audit-0.2.3-py3-none-any.whl -
Subject digest:
0d13983b2b1051423b4a85a72a2631dc6c05b226c0005be3893fa8fd90dd88bd - Sigstore transparency entry: 1214495522
- Sigstore integration time:
-
Permalink:
tanmaysheoran/fastapi-audit@ed5a5773a62d79f2ecf21694159a5c9625d0446c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/tanmaysheoran
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ed5a5773a62d79f2ecf21694159a5c9625d0446c -
Trigger Event:
workflow_dispatch
-
Statement type: