Complete documentation overhaul for Pulse v4.24.0 release covering all new features and operational procedures. Documentation Updates (19 files): P0 Release-Critical: - Operations: Rewrote ADAPTIVE_POLLING_ROLLOUT.md as GA operations runbook - Operations: Updated ADAPTIVE_POLLING_MANAGEMENT_ENDPOINTS.md with DEFERRED status - Operations: Enhanced audit-log-rotation.md with scheduler health checks - Security: Updated proxy hardening docs with rate limit defaults - Docker: Added runtime logging and rollback procedures P1 Deployment & Integration: - KUBERNETES.md: Runtime logging config, adaptive polling, post-upgrade verification - PORT_CONFIGURATION.md: Service naming, change tracking via update history - REVERSE_PROXY.md: Rate limit headers, error pass-through, v4.24.0 verification - PROXY_AUTH.md, OIDC.md, WEBHOOKS.md: Runtime logging integration - TROUBLESHOOTING.md, VM_DISK_MONITORING.md, zfs-monitoring.md: Updated workflows Features Documented: - X-RateLimit-* headers for all API responses - Updates rollback workflow (UI & CLI) - Scheduler health API with rich metadata - Runtime logging configuration (no restart required) - Adaptive polling (GA, enabled by default) - Enhanced audit logging - Circuit breakers and dead-letter queue Supporting Changes: - Discovery service enhancements - Config handlers updates - Sensor proxy installer improvements Total Changes: 1,626 insertions(+), 622 deletions(-) Files Modified: 24 (19 docs, 5 code) All documentation is production-ready for v4.24.0 release.
163 lines
5.5 KiB
Markdown
163 lines
5.5 KiB
Markdown
# Pulse Sensor Proxy Audit Log Rotation
|
||
|
||
The sensor proxy writes a tamper-evident audit trail to
|
||
`/var/log/pulse/sensor-proxy/audit.log`. Every entry includes the SHA-256 hash
|
||
of the previous entry, so any modification becomes obvious. Because the process
|
||
keeps the file open and maintains the running hash in memory, rotation requires
|
||
special handling.
|
||
|
||
## Rotation Strategy
|
||
|
||
Use `logrotate` to rotate the file once it reaches 100 MB. After each rotation,
|
||
restart the proxy so it opens a new file and starts a fresh hash chain.
|
||
|
||
Create `/etc/logrotate.d/pulse-sensor-proxy` with the following contents:
|
||
|
||
```conf
|
||
/var/log/pulse/sensor-proxy/audit.log {
|
||
daily
|
||
size 100M
|
||
rotate 90
|
||
compress
|
||
delaycompress
|
||
missingok
|
||
notifempty
|
||
create 0640 pulse pulse
|
||
sharedscripts
|
||
postrotate
|
||
systemctl restart pulse-sensor-proxy.service >/dev/null 2>&1 || true
|
||
endscript
|
||
}
|
||
```
|
||
|
||
### Why a Restart Is Mandatory
|
||
|
||
`copytruncate` and similar tricks break the chain integrity. Restarting the
|
||
service ensures:
|
||
|
||
1. The proxy releases the old file descriptor.
|
||
2. A new hash chain starts at sequence 1 with an all-zero `prev_hash`.
|
||
|
||
If the proxy is not restarted, it will continue writing to the renamed file and
|
||
the rotation will have no effect.
|
||
|
||
### Chain Continuity Across Rotations
|
||
|
||
Each rotated log (`audit.log.1.gz`, `audit.log.2.gz`, …) is self-contained. To
|
||
prove continuity between files:
|
||
|
||
1. After each rotation, record the final `event_hash` from the rotated file (for
|
||
example, store it in the filename or a checksum manifest).
|
||
2. When reviewing logs, verify the `prev_hash` of the first entry in the new
|
||
file is the zero hash, and reconcile the recorded final hash from the prior
|
||
file to show no entries were removed.
|
||
|
||
Maintaining this “final hash ledger” allows auditors to stitch the rotated files
|
||
together chronologically while preserving the tamper-evident guarantees.
|
||
|
||
### Permissions
|
||
|
||
Adjust the `create` directive to match the user and group that run the sensor
|
||
proxy. The example assumes both user and group are `pulse`.
|
||
|
||
---
|
||
|
||
## Post-Rotation Health Checks (v4.24.0+)
|
||
|
||
**After rotating audit logs and restarting pulse-sensor-proxy, verify adaptive polling health:**
|
||
|
||
### 1. Check Scheduler Health
|
||
|
||
```bash
|
||
curl -s http://localhost:7655/api/monitoring/scheduler/health | jq
|
||
```
|
||
|
||
**Verify:**
|
||
- Temperature proxy pollers appear in `instances[]` array
|
||
- `pollStatus.lastSuccess` is recent (within last 60 seconds)
|
||
- No new entries in `deadLetter` queue for proxy instances
|
||
- `breaker.state` is `closed` for proxy nodes
|
||
|
||
**Example check for proxy instances:**
|
||
```bash
|
||
curl -s http://localhost:7655/api/monitoring/scheduler/health \
|
||
| jq '.instances[] | select(.type == "proxy" or .connection | contains("proxy")) | {key, lastSuccess: .pollStatus.lastSuccess, breaker: .breaker.state}'
|
||
```
|
||
|
||
### 2. Monitor Metrics (10-15 minutes)
|
||
|
||
Watch these metrics to ensure proxy restart didn't cause issues:
|
||
|
||
```bash
|
||
# Queue depth should remain stable
|
||
curl -s http://localhost:7655/api/monitoring/scheduler/health | jq '.queue.depth'
|
||
|
||
# Check staleness for proxy instances
|
||
curl -s http://localhost:7655/api/monitoring/scheduler/health \
|
||
| jq '.instances[] | select(.type == "proxy") | {key, staleness: .pollStatus.lastSuccess}'
|
||
```
|
||
|
||
**Expected behavior:**
|
||
- Queue depth: No significant spike (< 10 temporary increase acceptable)
|
||
- Staleness: Proxy instances show fresh polls within 30-60 seconds
|
||
- No circuit breaker trips for proxy instances
|
||
- No new DLQ entries
|
||
|
||
### 3. Cross-Reference Audit Logs
|
||
|
||
**Link rotation events with scheduler health for security review:**
|
||
|
||
```bash
|
||
# Check Pulse audit log for rotation timing
|
||
journalctl -u pulse-sensor-proxy --since "10 minutes ago" | grep -E "restart|rotation"
|
||
|
||
# Check update history for any concurrent events
|
||
curl -s http://localhost:7655/api/updates/history?limit=5 | jq '.entries[] | {action, timestamp, status}'
|
||
```
|
||
|
||
**Why this matters:**
|
||
- Security auditors can correlate proxy restarts with scheduler behavior
|
||
- Update rollbacks may be concurrent with log rotations
|
||
- Rollback metadata (new in v4.24.0) provides full operational context
|
||
- Ensures restart didn't mask polling failures or breaker trips
|
||
|
||
### 4. Troubleshooting Rotation Issues
|
||
|
||
**If proxy instances don't rejoin queue:**
|
||
|
||
1. **Check service status**
|
||
```bash
|
||
systemctl status pulse-sensor-proxy
|
||
```
|
||
|
||
2. **Verify scheduler sees the proxy**
|
||
```bash
|
||
curl -s http://localhost:7655/api/monitoring/scheduler/health \
|
||
| jq '.instances[] | select(.type == "proxy")'
|
||
```
|
||
|
||
3. **Check for circuit breakers**
|
||
```bash
|
||
curl -s http://localhost:7655/api/monitoring/scheduler/health \
|
||
| jq '.instances[] | select(.breaker.state != "closed") | {key, state: .breaker.state, retryAt: .breaker.retryAt}'
|
||
```
|
||
|
||
4. **Review logs for errors**
|
||
```bash
|
||
journalctl -u pulse-sensor-proxy -n 50
|
||
journalctl -u pulse | grep -E "proxy|temperature"
|
||
```
|
||
|
||
**Recovery actions:**
|
||
- If breakers are stuck: Restart main Pulse service (`systemctl restart pulse`)
|
||
- If DLQ entries persist: Check proxy credentials and network connectivity
|
||
- If polling doesn't resume: Verify proxy configuration in **Settings → Sensors**
|
||
|
||
---
|
||
|
||
## Related Documentation
|
||
|
||
- [Scheduler Health API](../api/SCHEDULER_HEALTH.md) - Complete API reference
|
||
- [Adaptive Polling Operations](ADAPTIVE_POLLING_ROLLOUT.md) - Health monitoring procedures
|
||
- [Pulse Sensor Proxy Hardening](../security/pulse-sensor-proxy-hardening.md) - Security configuration
|
||
- [Temperature Monitoring Security](../TEMPERATURE_MONITORING_SECURITY.md) - Proxy-specific security notes
|