CAS Database Audit Log
The CAS database audit log is a cryptographically provable journal of security-sensitive operations executed over the course of the lifetime of a CAS database. 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.
Configuration
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.
Warning
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.
Logging
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.
Logged Operations
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.
Note
Session Hashes will be included in the audit log under the following conditions:
(a) the session can be read publicly, i.e. it has an access_policy with read: ANY, or
(b) the session is salted.
Service Attested
In SCONE 7.0.0 the Service Attested event was extended with information allowing the auditor to verify CAS attestation decision.
The data included in the attestation bundle is highly dependent on the attestation method used.
"No" Attestation Bundle
Services "attested" with the none attestation strategy are not attested, thus, CAS has no information about them and the attestation_bundle is empty.
{
"attestation_method":"none",
"attestation_bundle":""
}
SGX Local Attestation Bundle
For services attested with SGX local attestation, the CAS merely receives an SGX report, which can only be verified for software having access to the CPU that produced the report.
The attestation_bundle consists of the SGX report and the singleton_ctx, in case the enclave used singleton mode.
{
"attestation_method":"sgx-local",
"attestation_bundle": {
"report":"AAAAAAAAAAAAAAAAAAAAAA==",
"singleton_ctx": {
"singleton_page_offset":0,
"singleton_page":"AAAAAAAAAAAAAAAAAAAAAA==",
"base_hash":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"common_mrenclave":"0000000000000000000000000000000000000000000000000000000000000000",
"final_mrenclave":"0000000000000000000000000000000000000000000000000000000000000000"
}
}
}
SGX DCAP Attestation Bundle
For services attested with SGX DCAP remote attestation, the CAS obtains a DCAP quote of the service.
This quote can be verified independently.
However, the verification requieres auxilliary data, such as the sgx_tcb_info or sgx_qe_identity as provided by the Intel PCS (see https://api.portal.trustedservices.intel.com/).
All data the CAS used to verify the DCAP quote is included in the attestation_bundle.
Note that, the verification data "ages" by the discovery of vulnerabilities.
I.e., a system state that once was believed to be trustworhty may become untrustworthy with time as a vulnerability in the TEE implementation is detected.
The data provided in attestation_bundle shows the state of the information the CAS used to decide to trust the service.
In case the service used singleton mode, singleton_ctx is included as well.
{
"attestation_method":"sgx-dcap",
"attestation_bundle": {
"quote":"AAAAAAAAAAAAAAAAAAAAAA==",
"singleton_ctx": {
"singleton_page_offset":0,
"singleton_page":"AAAAAAAAAAAAAAAAAAAAAA==",
"base_hash":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"common_mrenclave":"0000000000000000000000000000000000000000000000000000000000000000",
"final_mrenclave":"0000000000000000000000000000000000000000000000000000000000000000"
},
"sgx_tcb_info":"{\\"tcbInfo\\":{},\\"signature\\":\\"0000000000000000\\"}",
"sgx_tcb_info_signing_certificate":"-----BEGIN CERTIFICATE-----\\nQUFBQQ==\\n-----END CERTIFICATE-----\\n",
"sgx_qe_identity":"{\\"enclaveIdentity\\":{},\\"signature\\":\\"0000000000000000\\"}",
"sgx_qe_identity_signing_certificate":"-----BEGIN CERTIFICATE-----\\nQUFBQQ==\\n-----END CERTIFICATE-----\\n",
"intel_sgx_root_ca_crl":"-----BEGIN X509 CRL-----\\nQUFBQQ==\\n-----END X509 CRL-----\\n",
"intel_sgx_pck_ca_crl":"-----BEGIN X509 CRL-----\\nQUFBQQ==\\n-----END X509 CRL-----\\n"
}
}
MAA Attestation Bundle
Services attested with Microsoft Azure Attestation provide the quote and the MAA Attestation token maa_token in the attestation bundle:
{
"attestation_method":"sgx-maa",
"attestation_bundle": {
"quote":"AAAAAAAAAAAAAAAAAAAAAA==",
"maa_token":"eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJyZWRhY3RlZCI6dHJ1ZX0.",
"singleton_ctx": {
"singleton_page_offset":0,
"singleton_page":"AAAAAAAAAAAAAAAAAAAAAA==",
"base_hash":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"common_mrenclave":"0000000000000000000000000000000000000000000000000000000000000000",
"final_mrenclave":"0000000000000000000000000000000000000000000000000000000000000000"
}
}
}
Service Exited
When a service exits, it attempts to send the CAS a message to inform it of that. The CAS then logs this message. However, many problems can prevent the service from sending this message to the CAS. These include:
- If there is a network outage at the moment the service crashes.
- Under some circumstances, SCONE runtime errors that cause the service to abort, such as integrity verification errors, may lead to the service being incapable of acquiring the resources that would allow it to communicate with the CAS.
- If code within the SCONE runtime provokes a segmentation fault or similar uncaught synchronous signal, it may deadlock as it attempts to communicate with the cas.
Log Schema
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.
Note
More event types and fields may be added in the future. This is not considered a breaking change.
Verification
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
With the -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 failed19- The log does not originate from the expected CAS18- CAS rollback detected (excluding single failed & rolled back transactions)17- CAS rollback or missing/deleted log entries detected16- 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 detected0- 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.
Note
Verification requires a signed audit log. The verification of unsigned logs will always fail.
Note
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...
Note
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.
Verification Algorithm
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 20).
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
cas_startedoraudit_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<sha512(utf8_encode('{"type":"CasAuditLogSigningKey", "signing_key":"<hex_encode(public_key_bytes)>"}'))>wherepublic_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
18) - 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
17) - If there is at least one event with an Unknown status, a rollback cannot be ruled out (exit code
16) - If the oldest event's predecessor does not match the expected signature, a log truncation has occurred (exit code
15) - 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
14) - 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
0).