Appearance
Log Retention and Archive Verification
Overview
HIPAA §164.312(b) requires audit logs to be retained for 6 years. Cirius Group satisfies this with a two-tier architecture:
- Hot tier (90 days): Log Analytics Workspace (
cirius-logging-law-central) — query-able via KQL - Archive tier (6 years): Azure Blob Storage with WORM immutability — raw log export
This document covers how to verify both tiers are functioning, the archive is intact, and the evidence is audit-ready.
For AWS CloudTrail retention, see the dedicated section below.
Log Sources and Retention Targets
| Log Source | Hot Tier Table | Archive Required | Retention Target |
|---|---|---|---|
| Entra sign-in logs | SignInLogs | Yes | 6 years |
| Entra audit logs | AuditLogs | Yes | 6 years |
| Azure Activity Log | AzureActivity | Yes | 6 years |
| Windows Security Events | SecurityEvent | Yes | 6 years |
| Palo Alto firewall logs | CommonSecurityLog | Yes | 6 years |
| Cortex XDR events | CommonSecurityLog | Yes | 6 years |
| AWS CloudTrail | S3 (separate) | Yes | 6 years |
| Container App logs | ContainerAppConsoleLogs_CL | Yes | 6 years |
| Heartbeat | Heartbeat | No | 90 days sufficient |
1 — Hot Tier (LAW 90-Day Window)
Verify LAW Retention Setting
Azure Portal → Log Analytics Workspace → cirius-logging-law-central → Usage and estimated costs → Data retention
Retention should be set to 90 days. Do not pay for hot retention beyond 90 days — data older than 90 days is available via the archive export.
bash
az monitor log-analytics workspace show \
--workspace-name cirius-logging-law-central \
--resource-group rg-logging-logs \
--query "retentionInDays"Expected: 90
Verify Data Is Flowing Into LAW
bash
# Check the most recent data in key tables
az monitor log-analytics query \
--workspace 5d76d1f2 \
--analytics-query "SignInLogs | summarize max(TimeGenerated) by bin(TimeGenerated, 1h) | order by TimeGenerated desc | take 1" \
--output tableIf the most recent SignInLogs entry is more than 2 hours old, sign-in log ingestion may have stopped. Check:
- Entra ID → Diagnostic settings — is the LAW workspace still configured as a destination?
- LAW ingestion health:
Heartbeat | summarize max(TimeGenerated)— is the workspace receiving any data?
Run the same check for other key tables:
AuditLogs | summarize max(TimeGenerated)
AzureActivity | summarize max(TimeGenerated)
SecurityEvent | summarize max(TimeGenerated)
CommonSecurityLog | summarize max(TimeGenerated)2 — Archive Tier (LAW Data Export to Blob)
Architecture
LAW Data Export Rules continuously stream table data to an Azure Storage Account. The storage account has:
- Immutable storage (WORM) — data cannot be modified or deleted within the retention period
- 6-year retention policy — set at the container level
- Blob versioning — protects against accidental overwrites
Check Data Export Rules Are Active
Azure Portal → Log Analytics Workspace → cirius-logging-law-central → Data Export
Each export rule shows its status (Enabled / Disabled) and the destination storage account. All HIPAA-required tables should have an active export rule.
bash
az monitor log-analytics data-export list \
--workspace-name cirius-logging-law-central \
--resource-group rg-logging-logs \
--output tableExpected: one rule per table group (or one rule covering all tables), status = Enabled.
If an export rule is disabled:
- Find when it was disabled: Azure Activity Log → filter for "data export" operations
- Re-enable: Portal → Data Export → [rule] → Enable
- Note: data during the disabled period is NOT retroactively exported — this is a gap that must be documented
Verify Archive Storage Account Immutability
Azure Portal → Storage Account [archive storage account] → Data management → Immutable blob storage
Immutability policy should show:
- Policy type: Time-based retention
- Retention period: 2190 days (6 years)
- State: Locked or Unlocked
Important: Leave the policy state as Unlocked unless permanently locking is explicitly required. A locked policy cannot be shortened — only extended. An unlocked policy still prevents deletion within the retention period.
bash
az storage container immutability-policy show \
--account-name <archive-storage-account> \
--container-name <logs-container> \
--output jsonVerify Archive Data Is Present and Recent
Spot-check that recent data has been exported:
bash
# List blobs in the archive container for today
az storage blob list \
--account-name <archive-storage-account> \
--container-name <logs-container> \
--prefix "$(date +%Y/%m/%d)" \
--output table \
--auth-mode loginIf no blobs exist for today, the export is not running. Check the export rule status and the storage account firewall settings (export requires the LAW service to reach the storage account).
Test Archive Data Readability (Annual)
During the annual DR test or compliance review, verify that archived data can be read:
Download a sample blob from the archive:
bashaz storage blob download \ --account-name <archive-storage-account> \ --container-name <logs-container> \ --name <path-to-blob> \ --file /tmp/log-sample.json \ --auth-mode loginVerify the file is valid JSON:
bashpython3 -m json.tool /tmp/log-sample.json | head -50Confirm the log fields are intact (TimeGenerated, UserPrincipalName, etc.)
Record the test date and result in the audit evidence log.
3 — AWS CloudTrail Retention
CloudTrail logs are written directly to an S3 bucket in the AWS Logging account (038901680748). Separate from the LAW archive.
Verify CloudTrail Is Enabled
bash
# Check CloudTrail is running in all regions, all accounts
aws cloudtrail describe-trails \
--profile logging \
--include-shadow-trails true \
--output tableThe organization trail should show IsOrganizationTrail: True — this covers all 7 accounts from the management account.
Verify S3 Retention and Object Lock
bash
# Check CloudTrail bucket lifecycle (moves to Glacier after 90 days)
aws s3api get-bucket-lifecycle-configuration \
--bucket <cloudtrail-bucket-name> \
--profile logging
# Check Object Lock
aws s3api get-object-lock-configuration \
--bucket <cloudtrail-bucket-name> \
--profile loggingCloudTrail logs should have:
- Lifecycle rule: Standard-IA at 90 days → Glacier at 365 days
- Object Lock: COMPLIANCE mode, 2190 days (6 years)
Verify Recent CloudTrail Data
bash
# Confirm recent events are being logged
aws cloudtrail lookup-events \
--profile logging \
--start-time "$(date -d '1 hour ago' --iso-8601=seconds)" \
--max-results 5If no events in the last hour, CloudTrail delivery is broken. Check:
- S3 bucket policy (CloudTrail needs
s3:PutObjecton the bucket) - CloudTrail status in the console
- CloudWatch Logs delivery if configured
4 — Verification Schedule
| Check | Frequency | Owner | Evidence |
|---|---|---|---|
| LAW hot retention setting | Quarterly | Rory | Portal screenshot |
| LAW table ingestion (all key tables) | Weekly via HIPAA audit email | Automated | Email report |
| Data Export rules — all enabled | Monthly | Rory | CLI output screenshot |
| Archive storage immutability | Quarterly | Rory | Portal/CLI screenshot |
| Archive blobs present for current week | Monthly | Rory | CLI output |
| CloudTrail enabled and org-wide | Quarterly | Rory | CLI output |
| CloudTrail S3 Object Lock | Quarterly | Rory | CLI output |
| Archive data readability test | Annual | Rory | Downloaded file + validation |
What to Do When Verification Fails
| Finding | Severity | Action |
|---|---|---|
| Data Export rule disabled | Critical | Re-enable immediately; document gap period; notify Rory |
| Archive storage immutability removed | Critical — likely a security event | Treat as incident; investigate who removed it; re-enable; escalate |
| LAW retention reduced below 90 days | High | Restore to 90 days; investigate |
| CloudTrail delivery failure | High | Restore delivery; the gap is an audit finding |
| Archive data unreadable | High | Escalate; test older blobs; contact Microsoft if needed |
| Missing blobs for recent period | Medium | Check export rule health; determine gap size |
| LAW table missing recent data | Medium | Check diagnostic settings for that data source |
All failures are documented. If the gap affects HIPAA-covered data, assess whether it constitutes a reportable incident under the HIPAA Breach Notification Rule.
Auditor Evidence Package
For HIPAA §164.312(b) and SOC2 A1.2/A1.3:
- This document — the retention policy and verification procedure
- LAW retention setting screenshot — 90 days confirmed
- Data Export rule list — shows all required tables are being exported
- Archive storage immutability screenshot — shows WORM policy active
- CloudTrail Object Lock screenshot — AWS log immutability
- Archive data readability test record — proves the data is usable
- HIPAA audit email history — weekly automated ingestion health checks
Related Documents
- KQL Query Reference — querying LAW for log health checks
- Cost Management — LAW ingestion cost monitoring
- Backup Restore Verification — backup integrity checks
- AWS Account Access Guide — authenticating for CloudTrail checks
Document History
| Date | Change | Author |
|---|---|---|
| May 2026 | Initial draft — LAW hot tier (90-day), archive export rules, blob storage WORM verification, AWS CloudTrail retention, verification schedule, failure escalation, HIPAA evidence package. | Rory |