Enterprise Audit Logging#
Note
Enterprise Feature: Built-in compliance auditing for SOC 2, HIPAA, PCI-DSS
This feature is unique to HFortix and not available in Fortinet’s official fortiosapi library.
Overview#
HFortix includes enterprise-grade audit logging that automatically tracks all API operations to FortiGate devices. This feature is essential for compliance and provides complete visibility into infrastructure changes.
Why Audit Logging Matters#
- Compliance Requirements
SOC 2, HIPAA, and PCI-DSS require audit trails of infrastructure changes
- Security
Track who changed what, when, and why
- Troubleshooting
Complete history of configuration changes
- Accountability
Link changes to users, tickets, and applications
Competitive Advantage#
Feature |
HFortix |
fortiosapi (Official) |
|---|---|---|
Audit Logging |
✅ Built-in |
❌ None |
Multiple Formats |
✅ JSON, Syslog, CEF |
❌ N/A |
SIEM Integration |
✅ Yes |
❌ No |
Compliance Ready |
✅ SOC 2, HIPAA, PCI-DSS |
❌ Manual implementation required |
Quick Start#
Basic File Logging#
from hfortix import FortiOS
from hfortix_core.audit import FileHandler
# Log all API operations to a file
handler = FileHandler("/var/log/fortinet-audit.jsonl")
fgt = FortiOS("192.168.1.99", token="your-token", audit_handler=handler)
# All operations now automatically logged
fgt.api.cmdb.firewall.address.post(name="test", subnet="10.0.0.1/32")
Result: Every API call logged to /var/log/fortinet-audit.jsonl in JSON Lines format:
{"timestamp":"2026-01-02T14:23:45Z","request_id":"a1b2c3d4","method":"POST","endpoint":"/api/v2/cmdb/firewall/address","vdom":"root","action":"create","object_type":"firewall.address","object_name":"test","data":{"name":"test","subnet":"10.0.0.1/32"},"status_code":200,"success":true,"duration_ms":145,"host":"192.168.1.99"}
SIEM Integration (Syslog)#
from hfortix_core.audit import SyslogHandler
# Send audit logs to your SIEM
handler = SyslogHandler("siem.company.com:514")
fgt = FortiOS("192.168.1.99", token="your-token", audit_handler=handler)
# All operations sent to SIEM in RFC 5424 format
Use Cases:
Splunk
ELK Stack (Elasticsearch, Logstash, Kibana)
QRadar
ArcSight
Any syslog-compatible SIEM
Container/Kubernetes Logs#
import sys
from hfortix_core.audit import StreamHandler
# Log to stdout (captured by container orchestration)
handler = StreamHandler(sys.stdout)
fgt = FortiOS("192.168.1.99", token="your-token", audit_handler=handler)
Captured by:
Docker (
docker logs)Kubernetes (
kubectl logs)AWS ECS (CloudWatch)
Azure Container Apps (Log Analytics)
Google Cloud Run (Cloud Logging)
Multiple Destinations#
from hfortix_core.audit import CompositeHandler, FileHandler, SyslogHandler, StreamHandler
# Send to multiple destinations simultaneously
handler = CompositeHandler([
SyslogHandler("siem.company.com:514"), # Compliance team
FileHandler("/var/log/fortinet.jsonl"), # Local backup
StreamHandler(sys.stdout), # Real-time monitoring
])
fgt = FortiOS("192.168.1.99", token="your-token", audit_handler=handler)
Built-in Handlers#
FileHandler#
Writes audit logs to a file in JSON Lines format with automatic rotation.
FileHandler(
filepath="/var/log/fortinet-audit.jsonl",
max_bytes=10_000_000, # Rotate at 10MB
backup_count=5, # Keep 5 backups
)
Features:
JSON Lines format (one JSON per line)
Automatic log rotation
Compatible with log shippers (Fluentd, Filebeat, Logstash)
SyslogHandler#
Sends audit logs to a syslog server in RFC 5424 format.
SyslogHandler(
server="siem.company.com:514", # host:port
)
Features:
RFC 5424 compliant
UDP transport (fire-and-forget)
Compatible with all major SIEMs
StreamHandler#
Writes audit logs to stdout/stderr.
StreamHandler(
stream=sys.stdout, # or sys.stderr
)
Features:
JSON format
Captured by container orchestration
Real-time monitoring
CompositeHandler#
Sends audit logs to multiple handlers.
CompositeHandler([
handler1,
handler2,
handler3,
])
Note
✨ NEW in v0.4.1: CompositeHandler now supports priority-based routing, conditional filtering, error aggregation, and dynamic handler management.
See Handler Protocol System for advanced CompositeHandler features and custom handler examples.
Features:
Parallel logging
Error isolation (one failure doesn’t stop others)
Useful for compliance + debugging
User Context Tracking#
Add metadata to every audit log to track users, applications, and change tickets:
from hfortix_core.audit import FileHandler
handler = FileHandler("/var/log/fortinet-audit.jsonl")
fgt = FortiOS(
"192.168.1.99",
token="your-token",
audit_handler=handler,
user_context={
"username": "admin",
"app_name": "backup_automation",
"change_ticket": "CHG-12345",
"team": "network_ops",
"environment": "production",
}
)
# Every audit log now includes user context
Audit Log Format#
Every audit log contains:
Field |
Type |
Description |
|---|---|---|
|
string |
ISO 8601 timestamp |
|
string |
Unique request identifier |
|
string |
HTTP method (GET, POST, PUT, DELETE) |
|
string |
Full API endpoint path |
|
string |
API category (cmdb, monitor, log, service) |
|
string |
Relative path |
|
string |
Virtual domain |
|
string |
High-level action (create, update, delete, read, list) |
|
string |
Object type (e.g., “firewall.address”) |
|
string |
Object name (if available) |
|
object |
Request payload (sanitized) |
|
object |
Query parameters (sanitized) |
|
integer |
HTTP status code |
|
boolean |
Whether operation succeeded |
|
integer |
Operation duration in milliseconds |
|
string |
FortiGate IP/hostname |
|
string |
Error message (if failed) |
|
object |
User-provided context |
|
boolean |
Whether simulated in read-only mode |
Security Features#
Automatic Data Sanitization#
Sensitive fields are automatically redacted:
# Input data
data = {
"name": "vpn-user",
"password": "secret123",
"api_key": "abc123def456",
}
# Audit log (sanitized)
{
"data": {
"name": "vpn-user",
"password": "***REDACTED***",
"api_key": "***REDACTED***",
}
}
Automatically redacted: password, secret, token, api_key, key, private, credential
Non-Blocking#
Audit logging failures never break API operations:
# If syslog server is down, operation still succeeds
fgt.api.cmdb.firewall.address.post(...) # ✅ Succeeds
# Error logged but doesn't raise exception
# ERROR: Audit handler failed: Connection refused
Compliance Use Cases#
SOC 2#
from hfortix_core.audit import CompositeHandler, SyslogHandler, FileHandler
# SOC 2 requires audit trail of infrastructure changes
handler = CompositeHandler([
SyslogHandler("siem.company.com:514"), # Real-time SIEM
FileHandler("/archive/fortinet-audit.jsonl"), # Long-term storage
])
fgt = FortiOS(
"192.168.1.99",
token="your-token",
audit_handler=handler,
user_context={"auditor": "SOC2", "period": "Q1-2026"}
)
HIPAA#
# HIPAA requires tracking who accessed/modified what and when
fgt = FortiOS(
"192.168.1.99",
token="your-token",
audit_handler=SyslogHandler("hipaa-siem.hospital.com:514"),
user_context={
"operator": "john.doe@hospital.com",
"department": "IT Security",
"compliance": "HIPAA",
}
)
PCI-DSS#
# PCI-DSS 10.2: Track all access to cardholder data environment
fgt = FortiOS(
"192.168.1.99",
token="your-token",
audit_handler=FileHandler("/pci/audit-trail.jsonl"),
user_context={
"pci_zone": "cardholder_data_environment",
"compliance": "PCI-DSS v4.0",
}
)
Real-World Examples#
Multi-Team Environment#
# Track which team made changes
teams = {
"network": {"handler": FileHandler("/logs/network-team.jsonl")},
"security": {"handler": FileHandler("/logs/security-team.jsonl")},
}
# Network team
fgt_network = FortiOS(
"192.168.1.99",
token="network-token",
audit_handler=teams["network"]["handler"],
user_context={"team": "network", "shift": "day"}
)
# Security team
fgt_security = FortiOS(
"192.168.1.99",
token="security-token",
audit_handler=teams["security"]["handler"],
user_context={"team": "security", "shift": "night"}
)
Change Management Integration#
def get_change_ticket():
"""Get current change ticket from environment or system"""
import os
return os.getenv("CHANGE_TICKET", "NO-TICKET")
ticket = get_change_ticket()
fgt = FortiOS(
"192.168.1.99",
token="your-token",
audit_handler=SyslogHandler("siem.company.com:514"),
user_context={
"change_ticket": ticket,
"approved_by": "change-board",
"window": "2026-01-02 02:00-04:00 UTC",
}
)
# All changes now linked to change ticket
Performance Impact#
Near Zero: Audit logging is non-blocking and uses minimal CPU/memory.
Logging happens after API response
Failed audit logs don’t retry (fire-and-forget)
No performance penalty on API operations
Demo Script#
Run the included demo to see all features:
python3 examples/audit_logging_demo.py
See Also#
Handler Protocol System - Custom audit handlers and plugin architecture (New in v0.4.1)
Logging & Observability - Structured logging and distributed tracing
/fortios/examples/basic-usage - Basic FortiOS usage examples
Validation - Input validation guide
Performance Testing and Optimization - Performance optimization guide