GxP / Guide 5
Data integrity and audit trails
Application audit trails versus platform logs, making cloud logs tamper-evident and long-lived, time synchronization, and how to run audit trail review.
An audit trail answers who did what, when, and why, to a GxP record. Most of that comes from the application: a LIMS records who changed a result and why. But the platform underneath has its own trail (who changed the database, who restored a backup, who granted access) and inspectors increasingly ask for both. This guide covers both layers and how to keep them trustworthy.
Two layers of audit trail
| Application audit trail | Platform logs | |
|---|---|---|
| Records | Creation, change and deletion of GxP records, with old value, new value and reason | Changes to infrastructure, access, keys, backups; data plane access where logged |
| Required by | Part 11 11.10(e), Annex 11 §9 | Annex 11 §12 (access changes recorded), data integrity guidance, your own risk assessment |
| Kept | As long as the record it describes | As long as your procedures say, usually at least as long as it's useful for investigations (often 1 to 7 years) |
| Reviewed | Before data is used for decisions, per risk | Periodically, and during investigations |
| Owned by | System owner and business | IT |
Platform logs don't replace an application audit trail. If an application can't record who changed a record and why, fixing that is a requirement for the application, not something logging can cover.
What the platforms keep by default
Out of the box, cloud logs don't last long enough for GxP:
- Azure activity log: 90 days. Resource logs (Key Vault access, SQL auditing, storage reads): not kept at all unless a diagnostic setting sends them somewhere.
- Microsoft Entra ID sign-in and audit logs: 30 days with Entra ID P1 or P2, 7 days on the free tier.
- AWS CloudTrail event history: 90 days of management events per region. Data events (S3 object reads and writes, for example) only if a trail or event data store records them.
- Microsoft Purview Audit: 180 days with Audit (Standard); 1 year for SharePoint, OneDrive, Exchange and Entra ID with Audit (Premium); up to 10 years with the 10-year retention add-on.
So the first control is simple: export everything relevant, to a place that keeps it long enough.
Azure: export and protect logs
- Add a subscription diagnostic setting for the activity log on every GxP subscription, sending to
log-notes-gxp. Assign the built-in policy that deploys it, so new subscriptions are covered automatically. - Add resource diagnostic settings (category group audit or allLogs) for Key Vault, SQL, storage, App Service and anything else holding or guarding GxP data. Again, use policy.
- Set workspace retention to what your procedure requires. Interactive retention goes up to two years, and long-term retention up to twelve years at lower cost.
- For tamper evidence, also send logs to a storage account with immutable blob storage (a locked time-based retention policy). Nobody, including the subscription owner, can delete or change blobs until retention ends.
- Export Entra ID sign-in and audit logs the same way.
Get-AzGxPAuditLogCoverage.ps1 checks all of this for GxP-tagged scope: activity log exported, each resource's diagnostic settings, and workspace retention against your minimum.
.\Get-AzGxPAuditLogCoverage.ps1 -MinRetentionDays 730 -GapsOnly
AWS: CloudTrail done properly
- One organization trail, multi-region, delivering to an S3 bucket in a separate log archive account that workload admins can't reach.
- Log file integrity validation on: CloudTrail writes hourly digest files signed with SHA-256, so you can prove delivered log files weren't changed or deleted (
aws cloudtrail validate-logs). - S3 Object Lock in compliance mode on the log bucket, with versioning, and KMS encryption on the trail.
- Data events for S3 buckets and other resources holding GxP data, where your risk assessment calls for read and write tracking.
- An SCP that denies
cloudtrail:StopLogging,cloudtrail:DeleteTrailand changes to the trail, and AWS Config recording in every region. - For long-term querying, CloudTrail Lake event data stores can keep events for up to about ten years.
Get-AwsGxPAuditTrailStatus.ps1 reports each of these per account: trail logging and last delivery, validation, KMS, bucket versioning and Object Lock, CloudWatch Logs retention, and the Config recorder in every region.
Time you can trust
Contemporaneous records need consistent clocks. Cloud platform logs use the provider's synchronized UTC time. Your virtual machines should use the provider's time service (Azure hosts provide time to VMs; on AWS use the Amazon Time Sync Service), with drift monitored. Store time stamps in UTC and show local time with its offset in reports, so records from different systems line up during an investigation.
Audit trail review
Keeping audit trails isn't enough: regulators expect them to be reviewed. Make the review risk-based and specific:
- What: for each GxP system, decide which events matter (changes to results after approval, deletions, re-processing, changes to user rights, configuration changes, failed logins on privileged accounts).
- When: application audit trails for critical data before the data is used for a decision, such as batch release; platform logs on a fixed schedule, such as monthly.
- How: saved queries or reports that surface only the events that matter, not a raw dump. Record who reviewed, when, what was found and what was done about it.
A saved Log Analytics query for monthly platform review might look like this:
AzureActivity
| where TimeGenerated > ago(31d)
| where OperationNameValue has_any ("roleAssignments", "locks", "diagnosticSettings",
"immutabilityPolicies", "backupPolicies", "protectedItems", "backupconfig")
| where OperationNameValue endswith "/WRITE" or OperationNameValue endswith "/DELETE"
| where ActivityStatusValue =~ "Success"
| project TimeGenerated, Caller, OperationNameValue, ResourceGroup, _ResourceId
| order by TimeGenerated desc
Common findings
- Audit trail can be turned off, or was off during part of the retention period.
- Admins can edit or delete audit data, or the database behind it, with no record.
- Shared or generic accounts, so actions can't be attributed.
- Logs kept 90 days by default, when procedures say years.
- Audit trails exist but nobody reviews them, or review records don't show what was checked.
- Clock differences between systems make sequences impossible to reconstruct.