# Audit Logs and Support Access — Multi-Tenant SaaS Architecture

Source: https://www.skillbyai.com/en/multi-tenant-saas/mt-audit-and-support-access

> Record tenant-visible audit events for sensitive actions, and give support staff controlled, logged access to tenant data.

## Who did what, in which tenant

Enterprise tenants expect an **audit log**: an append-only record of security-relevant actions inside their tenant, such as sign-ins, role changes, data exports, API key creation and settings changes. Each entry records the tenant, the actor, the action, the target, the time and relevant details, and tenant admins can usually view or export their own log. The other side is **your** staff. Support engineers sometimes need to see what a customer sees, but unrestricted database access for support is a serious risk. A safer design is **controlled impersonation**: support opens a session into a tenant only through a tool that requires a reason or ticket, possibly the customer's approval, limits the time, can be read-only, and writes every step to the tenant's audit log. Then customers can see exactly when your team accessed their data and why.

## Structured audit events

Every entry is self-describing JSON scoped to a tenant, including support impersonation.

```python
import json
from datetime import datetime, timezone

def audit(tenant_id, actor, action, target, **details):
    entry = {
        # fixed time so the example output is stable; use datetime.now(timezone.utc)
        "ts": datetime(2026, 1, 5, 10, 30, tzinfo=timezone.utc).isoformat(),
        "tenant_id": tenant_id,
        "actor": actor,
        "action": action,
        "target": target,
        "details": details,
    }
    print(json.dumps(entry))   # in production: append-only store, not stdout

audit("acme", "priya@acme.in", "user.role_changed", "user:42", old="viewer", new="admin")
audit("acme", "support@vendor", "tenant.impersonation_started", "tenant:acme", ticket="SUP-981")
```

Output:

```
{"ts": "2026-01-05T10:30:00+00:00", "tenant_id": "acme", "actor": "priya@acme.in", "action": "user.role_changed", "target": "user:42", "details": {"old": "viewer", "new": "admin"}}
{"ts": "2026-01-05T10:30:00+00:00", "tenant_id": "acme", "actor": "support@vendor", "action": "tenant.impersonation_started", "target": "tenant:acme", "details": {"ticket": "SUP-981"}}
```

## Make audit logs tamper-evident

Store audit events in an append-only store that the application cannot update or delete, separate from ordinary tables. Some teams also chain hashes of entries so tampering is detectable.

**Quiz:** Which practice best balances support needs with tenant trust?

- [x] Time-limited, reason-required impersonation that is recorded in the tenant's audit log
- [ ] Giving support engineers the database superuser password
- [ ] Asking customers to share their passwords with support
- [ ] Letting support export any tenant's data without records

*Answer:* Time-limited, reason-required impersonation that is recorded in the tenant's audit log. Controlled impersonation gives support what it needs while making access explicit, minimal and visible to the customer. The other options remove accountability.
