The Stellar Micro-Donation API implements comprehensive audit logging for all security-sensitive operations. Audit logs provide an immutable, tamper-evident trail for compliance, security monitoring, and incident investigation.
- Immutable Storage: Audit logs are write-once and cannot be modified
- Integrity Verification: Each log entry includes a cryptographic hash for tamper detection
- Sensitive Data Masking: Automatic sanitization prevents exposure of secrets and PII
- Structured Logging: Consistent format with standard fields for easy querying
- Real-time Monitoring: High-severity events are logged to application logs for alerting
- Query API: Flexible filtering and pagination for audit trail analysis
-
AuditLogService (
src/services/AuditLogService.js)- Core audit logging functionality
- Integrity hash generation and verification
- Query and statistics APIs
-
Database Table (
audit_logs)- Immutable storage for audit entries
- Indexed for efficient querying
- Includes integrity hash for tamper detection
-
Integration Points
- API Key Middleware (
src/middleware/apiKey.js) - RBAC Middleware (
src/middleware/rbac.js) - API Keys Routes (
src/routes/apiKeys.js) - Rate Limiter (
src/middleware/rateLimiter.js) - Abuse Detection (
src/middleware/abuseDetection.js)
- API Key Middleware (
- API key validation (success/failure)
- Missing API key attempts
- Legacy key usage
- Invalid/expired key attempts
- Permission checks (granted/denied)
- Admin access attempts (granted/denied)
- Role-based access control violations
- API key creation
- API key deprecation
- API key revocation
- API key listing (MEDIUM severity)
- Donation creation
- Donation verification
- Transaction recording
- Donation status updates
- Rate limit exceeded events
- Burst detection
- Repeated failures
- IP flagging
- Suspicious activity patterns
- Replay detection
Each audit log entry contains:
{
id: 123, // Auto-increment ID
timestamp: "2024-01-15T10:30:00Z", // ISO 8601 timestamp
category: "AUTHENTICATION", // Event category
action: "API_KEY_VALIDATED", // Specific action
severity: "HIGH", // HIGH, MEDIUM, or LOW
result: "SUCCESS", // SUCCESS or FAILURE
userId: "user-123", // User/API key identifier
requestId: "req-456", // Request correlation ID
ipAddress: "192.168.1.1", // Client IP
resource: "/api/v1/donations", // Resource accessed
reason: "Invalid credentials", // Failure reason (optional)
details: { // Additional context (sanitized)
role: "user",
method: "POST"
},
integrityHash: "abc123...", // SHA-256 hash for tamper detection
createdAt: "2024-01-15T10:30:00Z" // Database timestamp
}const AuditLogService = require('../services/AuditLogService');
// Log a security-sensitive operation
await AuditLogService.log({
category: AuditLogService.CATEGORY.AUTHENTICATION,
action: AuditLogService.ACTION.API_KEY_VALIDATED,
severity: AuditLogService.SEVERITY.HIGH,
result: 'SUCCESS',
userId: 'user-123',
requestId: req.id,
ipAddress: req.ip,
resource: req.path,
details: {
role: 'admin',
keyPrefix: 'sk_live_abc...'
}
});// Query with filters
const logs = await AuditLogService.query({
category: AuditLogService.CATEGORY.AUTHENTICATION,
severity: AuditLogService.SEVERITY.HIGH,
startDate: '2024-01-01T00:00:00Z',
endDate: '2024-01-31T23:59:59Z',
limit: 100,
offset: 0
});
// Get statistics
const stats = await AuditLogService.getStatistics({
category: AuditLogService.CATEGORY.API_KEY_MANAGEMENT,
startDate: '2024-01-01T00:00:00Z'
});// Verify an audit log entry hasn't been tampered with
const entry = await Database.get('SELECT * FROM audit_logs WHERE id = ?', [123]);
const isValid = AuditLogService.verifyIntegrity(entry);
if (!isValid) {
console.error('Audit log tampering detected!');
}AuditLogService.SEVERITY.HIGH // Critical security events
AuditLogService.SEVERITY.MEDIUM // Important operations
AuditLogService.SEVERITY.LOW // Informational eventsAuditLogService.CATEGORY.AUTHENTICATION
AuditLogService.CATEGORY.AUTHORIZATION
AuditLogService.CATEGORY.API_KEY_MANAGEMENT
AuditLogService.CATEGORY.FINANCIAL_OPERATION
AuditLogService.CATEGORY.WALLET_OPERATION
AuditLogService.CATEGORY.CONFIGURATION
AuditLogService.CATEGORY.RATE_LIMITING
AuditLogService.CATEGORY.ABUSE_DETECTION
AuditLogService.CATEGORY.DATA_ACCESS// Authentication
AuditLogService.ACTION.API_KEY_VALIDATED
AuditLogService.ACTION.API_KEY_VALIDATION_FAILED
AuditLogService.ACTION.LEGACY_KEY_USED
// Authorization
AuditLogService.ACTION.PERMISSION_GRANTED
AuditLogService.ACTION.PERMISSION_DENIED
AuditLogService.ACTION.ADMIN_ACCESS_GRANTED
AuditLogService.ACTION.ADMIN_ACCESS_DENIED
// API Key Management
AuditLogService.ACTION.API_KEY_CREATED
AuditLogService.ACTION.API_KEY_LISTED
AuditLogService.ACTION.API_KEY_DEPRECATED
AuditLogService.ACTION.API_KEY_REVOKED
// Financial Operations
AuditLogService.ACTION.DONATION_CREATED
AuditLogService.ACTION.DONATION_VERIFIED
AuditLogService.ACTION.DONATION_STATUS_UPDATED
AuditLogService.ACTION.TRANSACTION_RECORDED
// Rate Limiting & Abuse
AuditLogService.ACTION.RATE_LIMIT_EXCEEDED
AuditLogService.ACTION.ABUSE_DETECTED
AuditLogService.ACTION.IP_FLAGGED
AuditLogService.ACTION.REPLAY_DETECTEDCREATE TABLE audit_logs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT NOT NULL,
category TEXT NOT NULL,
action TEXT NOT NULL,
severity TEXT NOT NULL,
result TEXT NOT NULL,
userId TEXT,
requestId TEXT,
ipAddress TEXT,
resource TEXT,
reason TEXT,
details TEXT,
integrityHash TEXT NOT NULL,
createdAt DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- Indexes for efficient querying
CREATE INDEX idx_audit_logs_timestamp ON audit_logs(timestamp);
CREATE INDEX idx_audit_logs_category ON audit_logs(category);
CREATE INDEX idx_audit_logs_action ON audit_logs(action);
CREATE INDEX idx_audit_logs_severity ON audit_logs(severity);
CREATE INDEX idx_audit_logs_userId ON audit_logs(userId);
CREATE INDEX idx_audit_logs_requestId ON audit_logs(requestId);Run the migration to create the audit logs table:
node src/scripts/migrations/addAuditLogsTable.js// ✅ Good: Log both success and failure
if (isValid) {
await AuditLogService.log({ /* success */ });
return next();
} else {
await AuditLogService.log({ /* failure */ });
return res.status(401).json({ error: 'Unauthorized' });
}- HIGH: Authentication failures, permission denials, API key operations
- MEDIUM: Configuration changes, wallet operations, rate limiting
- LOW: Successful authentication, read operations
// ✅ Good: Rich context for investigation
await AuditLogService.log({
category: AuditLogService.CATEGORY.AUTHENTICATION,
action: AuditLogService.ACTION.API_KEY_VALIDATION_FAILED,
severity: AuditLogService.SEVERITY.HIGH,
result: 'FAILURE',
userId: null,
requestId: req.id,
ipAddress: req.ip,
resource: req.path,
reason: 'Invalid API key format',
details: {
keyPrefix: apiKey.substring(0, 8) + '...',
userAgent: req.get('User-Agent'),
method: req.method
}
});// ❌ Bad: Exposes sensitive data
details: {
apiKey: 'sk_live_1234567890',
password: 'secret123'
}
// ✅ Good: Sanitized automatically by AuditLogService
details: {
keyPrefix: 'sk_live_12...',
role: 'admin'
}// ✅ Good: Don't block operations if audit logging fails
try {
await AuditLogService.log({ /* ... */ });
} catch (error) {
console.error('Audit log failed:', error);
// Continue with operation
}
// Or use .catch() for non-blocking
AuditLogService.log({ /* ... */ }).catch(err => {
console.error('Audit log failed:', err);
});Monitor these events for security incidents:
-
Multiple Failed Authentication Attempts
- Action:
API_KEY_VALIDATION_FAILED - Threshold: 5+ failures from same IP in 5 minutes
- Action:
-
Admin Access Denials
- Action:
ADMIN_ACCESS_DENIED - Alert on any occurrence
- Action:
-
API Key Revocations
- Action:
API_KEY_REVOKED - Alert on any occurrence
- Action:
-
Rate Limit Exceeded
- Action:
RATE_LIMIT_EXCEEDED - Threshold: 10+ occurrences from same IP
- Action:
-
IP Flagging
- Action:
IP_FLAGGED - Alert on any occurrence
- Action:
// Find failed authentication attempts in last hour
const failedAuth = await AuditLogService.query({
category: AuditLogService.CATEGORY.AUTHENTICATION,
result: 'FAILURE',
startDate: new Date(Date.now() - 3600000).toISOString()
});
// Find all admin operations today
const adminOps = await AuditLogService.query({
action: AuditLogService.ACTION.ADMIN_ACCESS_GRANTED,
startDate: new Date().toISOString().split('T')[0] + 'T00:00:00Z'
});
// Get security statistics for the month
const stats = await AuditLogService.getStatistics({
severity: AuditLogService.SEVERITY.HIGH,
startDate: '2024-01-01T00:00:00Z',
endDate: '2024-01-31T23:59:59Z'
});Audit logs support compliance with:
- SOC 2: Security monitoring and incident response
- PCI DSS: Access control and audit trail requirements
- GDPR: Data access logging and breach detection
- ISO 27001: Information security management
- Minimum: 90 days for operational security
- Recommended: 1 year for compliance
- Long-term: Archive to cold storage for legal requirements
Run audit log tests:
npm test tests/audit-logs.test.jsTests cover:
- Audit log creation with integrity hashing
- Query and filtering capabilities
- Sensitive data masking
- Immutability verification
- Statistics generation
-
Check database table exists:
node src/scripts/migrations/addAuditLogsTable.js
-
Verify database permissions
-
Check application logs for errors
If verifyIntegrity() returns false:
- Database tampering detected - Investigate immediately
- Check for database corruption
- Review database access logs
- Consider forensic analysis
If audit logging impacts performance:
- Ensure indexes are created (see migration script)
- Use
.catch()for non-blocking audit logs - Consider async queue for high-volume operations
- Archive old logs to separate table
- Export audit logs to external SIEM systems
- Real-time alerting for high-severity events
- Audit log visualization dashboard
- Automated compliance reporting
- Blockchain-based immutability (Stellar ledger)
- Machine learning for anomaly detection
For questions or issues:
- Review this documentation
- Check test files for examples
- Open an issue on GitHub
- Contact the security team