CAS Audit Log
The CAS audit log is a cryptographically provable journal of security-sensitive operations executed over the course of the lifetime of a CAS instance. The audit log can be evaluated to learn - among others -
- how a SCONE application's configuration came about,
- how its secrets were created, and
- which services accessed these secrets.
This can be used to prove that an application's configuration has not been tampered with. The log is created and signed by the SCONE-secured CAS itself, therefore even untrusted CAS owners or operators cannot tamper with the log. It might also be used for billing session owners.
By default, audit logging is disabled. It must be enabled in the CAS owner configuration. If logging to a file, the log file path can be adjusted in the CAS availability configuration. More for more details, please see below.
Currently, the log file will be stored unencrypted. The CAS operator will therefore be able to read the log as well! Note that audit log verification can be used to ensure that the log file was not manipulated.
Fundamentally, whenever a CAS attempts a security-sensitive operation, it pushes a log entry in the audit log before committing the operation. Note that this behavior can lead to logs containing operations that never happened since CAS pushes the log entry before the operation was fully committed, leaving a small window in which the transaction can fail. While unlikely, this may occur during normal CAS operation. In alternative implementations where log entries are pushed only after the operation was fully committed, the log pushing might fail, leading to lost updates and invalidating the whole audit log from that point onward, which we see as the worse outcome. In our implementation, if the operation failed, CAS will use the same sequence number in the next log entry. This basically constitutes a one-operation rollback from the audit log's perspective and has to be regarded during audit log verification.
Log entries consist of a sequence number, a description of the operation and a cryptographic signature. The sequence number and the signature are essential for the cryptographic verification of the audit log (detailed below). The sequence number is a strictly monotonically increasing value that is incremented with each security-sensitive operation. The signature is not only computed over the operation's description and sequence number, but also incorporates the previous log entry's signature value. This builds a cryptographically secured sequence of security-sensitive operations that cannot be tampered with (without knowledge of the signing key, which is protected by SCONE).
The latest message's sequence number and signature, as well as occasional history checkpoints, are maintained within the CAS database, while the entire log entry is written to a file on disk or sent to a log server. This enables the verifier - with help of the CAS - to detect whether the audit log at hand describes the most recent CAS state.
For verification of the authenticity of the audit log, the key used for log entry signing has to be attributable to the CAS instance. Therefore, CAS creates a log entry on startup which links the utilized signing key to its identity. The identity itself can be proved through SGX attestation, using one of two methods:
- A certificate chain, embedded in an event that was created when CAS was started or audit logging was enabled, links the audit log signing key to the CAS (root CA) key. If this key was attested before, certificate chain verification is sufficient.
- EPID attestation reports, embedded in the log, allow verifying the audit log signing key directly. These audit log attestation report entries are created after CAS was started or audit logging was enabled, but only if the CAS owner configuration specifies IAS credentials. If the reports cannot be created, e.g. due to network issues, CAS will start normally, and creating them will be retried in the background.
Currently, the following operations/events will be logged:
- Audit logging enabled
- Audit logging disabled
- Audit log attestation report
- CAS started
- CAS exited
- Session created
- Session read
- Session updated
- Service attested
- Service FSPF tag updated
- Service exited
- Volume FSPF tag updated
In order to protect the session owners' privacy, only limited information will be logged for events involving sessions and services.
Each log entry is encoded in JSON format. If the log is written to a file, each line contains exactly one entry. If the log is sent to a server, each entry will be sent as a POST request body.
Audit log verification
- ensures the authenticity and integrity of every entry of the audit log by verifying that signatures are correct and signature keys belong to the expected attested CAS,
- detects rollbacks of the CAS database,
- detects log truncation and deletion of intermediate entries,
- and detects failed and rolled back transactions.
The verification is provided by the
scone cas verify-audit-log and
scone cas attest-audit-log CLI tools. Basic usage:
scone cas verify-audit-log /var/log/cas/audit/cas_audit.log -p
-p switch, all events will be printed in a human-readable format. Omit it if you are only interested in the verification result.
The default CAS will be used for verification. The CAS will be contacted to download and compare audit log history entries. If the CAS is unreachable, rollback and truncation detection will not work. Use the
--cas option to select another CAS. You must be the CAS owner (in possession of the CAS owner client certificate).
In addition to printing the verification status, the command will exit with one of the following exit codes (most severe first):
20- Log authenticity/integrity violation - parsing error or signature verification failed
19- The log does not originate from the expected CAS
18- CAS rollback detected (excluding single failed & rolled back transactions)
17- CAS rollback or missing/deleted log entries detected
16- CAS rollback cannot be ruled out (necessary CAS history entries are unavailable; also used if CAS cannot be contacted)
15- Log was truncated (older entries are missing)
14- Log was truncated (recent entries are missing)
10- Log is correct, but at least one failed & rolled back transaction was detected
0- Log is fully correct
- other - Fatal error during verification
scone cas verify-audit-log will re-use attestation information from a previously attested CAS. To specify custom attestation settings, use
scone cas attest-audit-log instead, which supports the same options as
scone cas attest. At the moment, only
scone cas attest-audit-log will verify the attestation reports embedded in the log.
Verification requires a signed audit log. The verification of unsigned logs will always fail.
By default, audit log verification assumes a complete log, i.e. containing all events starting with the very first logged event (which has sequence number 1) up to the most recent event.
If this assumption does not hold, a log truncation exit code will be returned.
If the log file is being rotated, archived logs are expected to only hold a subset of all events. In order to verify them successfully, specify the arguments
--predecessor <predecessor-signature> and/or
--last <last-signature> during verification, where
<predecessor-signature> is the signature of the last event in the preceding log file, and
<last-signature> is the predecessor signature of the first event in the succeeding log file; e.g.:
scone cas verify-audit-log /var/log/cas/audit/cas_audit.log -p --predecessor 22a4543d69def755646c359... --last 863d7fb739c950b0559a69d...
When the audit log is sent to a log server, log entries have to be queried and written to a file prior to verification, one log entry per line, sorted by sequence number (ascending). How this can be achieved depends on the used log server software. To facilitate successful verification, we recommend gathering all log entries for a given CAS instance ID - this ensures that the necessary CAS identity log entry is present, and matching log history entries can be found in the CAS database.
The Audit Log is verified in two steps:
- Integrity Verification, and
- Rollback & Truncation Detection.
During Integrity Verification, individual log entries are parsed and their signatures are verified (on failure: exit code
Subsequently, it is checked that all encountered signing keys belong to the expected CAS (on failure: exit code
19). For this purpose, it must be checked that
- each signing key is part of a valid certificate chain extracted from a
audit_log_enabledevent, whose root certificate contains an expected CAS (root CA) key that was attested previously, and/or
- each signing key can be verified using an attestation report in a
audit_log_attestation_reportevent. This requires verification of the report's authenticity, expected enclave properties (such as CAS mrenclave, mrsigner, etc.) and that the SGX report data matches
public_key_bytesis the 32 bytes long audit log signing public key.
All events are assembled into an event tree / forest (as there can be multiple roots). The event tree links individual log entries together if their signature matches the next entry's predecessor signature. In principle, the tree could/should consist of a single branch, i.e. it would be a list. However, whenever one or multiple event(s) are rolled back, a new branch appears (log forking). When intermediate entries are deleted from the log, a new root branch appears (log splitting). Remember that single event rollbacks are considered benign since they can develop even during nonmalignant operations, like database transaction failures. Therefore, one must expect an event tree with multiple branches.
For Rollback & Truncation Detection, the previously created event tree is analysed and CAS is contacted to query its most recent state.
CAS' state is described with the latest entry's sequence number and its signature (checkpoint), as well as occasional history checkpoints. CAS only returns history checkpoints within the range of encountered sequence numbers, and may truncate the list if it becomes too long (by default, it returns at most 100 checkpoints, with one checkpoint created each 250 log entries). History checkpoints allow the verifier to determine whether a sequence of events/transactions was persisted in the CAS database, even if the log is missing some of the most recent entries. CAS tries to align history checkpoints with log file rotations, such that old, rotated log files can still be verified successfully in their entirety.
For the analysis, the event tree is walked along, annotating each entry with one of the following rollback statuses:
- Not Rolled Back - the event's signature matches one of the checkpoints received from CAS, or it is a direct or transitive predecessor of such an event.
- Rolled Back - the event has a sequence number greater than that of the most recent entry received from CAS (definitive rollback); or the event has sequence number identical or adjacent to a Not Rolled Back event, but a mismatching signature (explicit parallel branch); or the event has a sequence number identical to one of the checkpoints received from CAS but a different signature (implicit parallel branch); or the event is a direct or transitive successor of a Rolled Back event.
- Rolled Back or Missing Entries - for events that are neither Rolled Back nor Not Rolled Back, and have a sequence number < the maximum sequence number of received CAS checkpoints matched by a Not Rolled Back event (events may be missing from the log that link it to a Not Rolled Back branch)
- Unknown - for events that are neither Rolled Back nor Not Rolled Back, and have a sequence number > the maximum sequence number of received checkpoints matched by a Not Rolled Back event (a checkpoint may be missing that links it to a Not Rolled Back branch)
Subsequently, a rollback and truncation status is determined for the log in its entirety:
- If there is at least one Rolled Back event (excluding single transaction rollbacks, see below) or there are at least two parallel branches (i.e. containing entries with matching sequence numbers but mismatching signatures) with each more than one entry, a rollback was detected (exit code
- If there is at least one Rolled Back Or Missing Entries event or there are multiple Not Rolled Back root events (indicating that intermediate events have been deleted from the log, otherwise they would have been assigned to a single branch), a rollback or missing entries have been detected (exit code
- If there is at least one event with an Unknown status, a rollback cannot be ruled out (exit code
- If the oldest event's predecessor does not match the expected signature, a log truncation has occurred (exit code
- If the signature of the last expected event (if specified) or most recent checkpoint received from CAS was not matched by any event in the log, a log truncation has occurred (exit code
- If there is at least one single transaction rollback (exit code
10). This denotes branches consisting of a single event, which has a Not Rolled Back sibling (event with an identical predecessor, but mismatching signature).
- The remaining case is the best case: The latest entry of the audit log matched the latest CAS checkpoint, there was no rollback nor log truncation, and no single transactions were rolled back either (exit code
The SCONE CAS audit log can be configured as part of the owners config of a CAS instance:
[audit_log] mode = "signed"
Optional. Select one of the following audit log modes:
disabled(default) - No audit log will be created
unsigned- An audit log will be created, but its entries will not be signed. The log cannot be cryptographically verified. More efficient than
signed- An audit log will be created, and its entries will be signed (recommended).
[audit_log] sink = "file"
Optional. Select one of the following destinations that the audit log will be written to:
file(default) - The audit log will be written to a file (the file path is configurable in the availability configuration).
network- The audit log will be sent to a network server. Additional properties:
url(required) - URL of the log server. Each log entry will be sent as a POST request with a JSON-encoded body to the given URL.
server_ca_certificate(optional) - PEM-encoded X.509 (CA) certificate to authenticate the server with. If omitted, a list of default Web PKI root CA certificates will be used.
[audit_log] sink = "network" url = "https://logs.example.com/append" server_ca_certificate = """ -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- """
If the log server cannot be reached, all logged operations will fail and be rolled back. This means that most requests to CAS will fail, rendering CAS unusable. This includes updating the CAS owner configuration! Therefore, make sure the configured server is available at all times.