Releases: microsoft/CCF
Releases · microsoft/CCF
Release list
7.0.13
Changed
- Governance endpoints now select the API implemented by the running CCF build when
api-versionis omitted or set tolatest.GET /gov/apireturns an auto-generated OpenAPI document for this moving API, while datedapi-versionvalues continue to return their frozen documents. (#8147)
Added
- C++ endpoints can now use
ccf::endpoints::Endpoint::add_openapi_response<Out>()to document additional HTTP responses in their generated OpenAPI schema without changing the endpoint's primary success response (#8115). - New
ledger.max_transaction_sizenode configuration option (default32MB), which caps the total serialised size of transactions written to the ledger. The limit covers the whole ledger entry: the fixed 8-byte ledger entry header, the ledger encryption header, public domain size field, public domain and encrypted private domain. It is checked before a transaction is applied, so an oversized transaction is now rejected with413 Payload Too Largeand error codeTransactionTooLarge, and subsequent transactions are unaffected, where previously an excessively large transaction could terminate the node. Reserved internal signature transactions are exempt because they must fill their reserved ledger version. The limit applies only to newly serialised non-reserved transactions; deserialising existing entries (including during recovery), historical queries and snapshots are unaffected, so entries written under a larger or unset limit remain readable. It must be smaller thanmemory.max_msg_sizeby at least the ring-buffer range response overhead, which is validated at node startup and by--check(#7992).
Changed
ccf::SessionContext::caller_certis now immutable, and its SHA-256 digest is cached per session to avoid repeated hashing during user and member certificate authentication (#8164).- Clang builds now enable compile-time thread safety analysis for CCF's annotated PAL mutexes and condition-variable waits, with reusable annotations available from
ccf/ds/thread_safety.h(#8180).
Fixed
- Nodes from the previous service are now removed during disaster recovery instead of being retained as retired entries in
GET /node/network/nodes, andledger_code.pyreports their code identities as removed (#8177). - Fixed an edge case where a follower could incorrectly commit to an abandoned fork while synchronising with the leader, causing it to become unavailable (#8172).
7.0.12
7.0.11
Added
- Recovery can now use a COSE snapshot signed by an earlier service identity after one or more disaster recoveries. Before deserialising the snapshot, the node reads previous-service-identity endorsement candidates from the public ledger suffix, validates a complete chain against the operator-provided identity, and retains it only for the current recovery attempt. Invalid or incomplete endorsement chains fall back to full-ledger replay (#8092).
Fixed
- Asynchronous ledger reads (used to serve committed entry ranges to the enclave) no longer access the host
Ledgerobject after it has been destroyed during shutdown. TheLedgernow waits for any in-flight read workers to finish, and workers that have not yet started skip accessing it, fixing a potential use-after-free on shutdown (#8003).
Changed
- TLS handshakes now prefer hybrid post-quantum key exchange groups, in the order
SecP384r1MLKEM1024,SecP256r1MLKEM768,X25519MLKEM768, when the linked crypto provider supports them. TheP-521,P-384andP-256groups are retained as fallbacks (#8107). ccf.cose.verify_receipt()has moved and been renamed toccf.receipt.verify_cose(); the old name still works but is deprecated (#8109).
7.0.10
Changed
ccf::http::ParsedQuery(ininclude/ccf/http_query.h), returned byccf::http::parse_query(), is now astd::multimap<std::string, std::string, std::less<>>that owns its decoded keys and values, rather than astd::multimap<std::string_view, std::string_view>pointing into the source query string. Owned storage is required because each key and value is now URL-decoded individually after splitting, which produces bytes not present in the original query. Application code that consumed the previousstd::string_viewkeys/values may need to be updated (#8024).ccf::RpcContext::get_request_query()(C++) andrequest.query(JavaScript apps) now return the raw, still percent-encoded query string, instead of a whole-string URL-decoded copy. This is what allows escaped separators to be preserved. Callers must decode each parameter after splitting: useccf::http::parse_query()/ccf::http::get_query_value()(C++) orparse_request_query()(JS), orccf::http::decode_query_component()to decode a whole query string (#8024).
Fixed
- HTTP query parameters are now split before URL-decoding, so escaped ampersands in query parameter names and values are preserved correctly (#8024).
- HTTP messages (requests or replies) whose
Content-Lengthheader advertises a body larger than the configured maximum body size are now rejected as soon as the headers have been parsed, rather than after enough body chunks have been received to exceed the limit (#8045). - The thread-identifier helpers used by
ccf/ds/logger.h(ccf::threading::get_current_thread_id,set_current_thread_id, andreset_thread_id_generator) have moved out oflibccfinto a new standaloneccf_threadingstatic library, whichfind_package(ccf)exports automatically. This removes a long-standing implicit circular dependency (#7977). - Build-graph change for consumers that link CCF component libraries directly.
ccfcryptonow links the newccf_threadinglibrary, andccf_tasksandccf_kvlinkccf_threadingdirectly instead ofccfcrypto. Downstream targets that linkedccf_tasksorccf_kvdirectly and relied on them transitively supplying CCF cryptography must now linkccfcryptoexplicitly. Applications built withadd_ccf_app(which linkccfandccf_launcher) are unaffected (#7977). - As a temporary workaround for a Linux CIFS client kernel bug present in Confidential Azure Container Instances, uncommitted recovery ledger chunks are closed before their
.recoverysuffix is removed and reopened afterwards. This preserves the SMB write-caching lease on Azure Files, avoiding synchronous round trips for subsequent ledger writes. The workaround should be reverted once the Confidential Azure Container Instances platform upgrades to a kernel containing upstream fix2c7d399e551c(#8072).
7.0.9
Fixed
- Curl request bodies can now be replayed when following redirects or retrying authentication (#8052).
7.0.8
Changed
- The node join protocol client now uses the curl multi singleton client (introduced in #7102) instead of the legacy enclave
RPCSessions::create_client()HTTP client, matching the JWT refresh and snapshot-fetch clients. The service certificate remains the sole trust anchor for the join connection (the host certificate store is never consulted) (#8040). - Node joins now check the target RPC address against the target node's certificate SANs. TLS certificate hostname verification (
CURLOPT_SSL_VERIFYHOST) is now enforced on the join connection: the host injoin.target_rpc_addressmust be covered by one of the target node's certificate Subject Alternative Names (SANs), and a join to an address absent from the target's SANs is now rejected (the previous join client did not check the target certificate name at all). CCF derives node-certificate SANs fromnode_certificate.subject_alt_names, or by default from each RPC interface'spublished_address, so standard deployments are unaffected; operators that configure a bespokejoin.target_rpc_addressmust ensure it is present in the target node's certificate SANs (#8040).
Removed
- The unused enclave-side HTTP client infrastructure (
RPCSessions::create_client,HTTPClientSession,HTTP2ClientSession,UnencryptedHTTPClientSession, and theClientSessionbase) has been removed following the migration of the node join client to curl, completing the legacy HTTP client removal tracked in #7262 (#8040).
Fixed
- A node joining or recovering from a stale snapshot no longer fails to bootstrap its network identity history when the local key-value store briefly exposes a previous service identity. The network identity subsystem now detects that the topmost endorsement is signed by a stale service identity and retries (unbounded, matching the other pre-bootstrap waits) until the committed ledger suffix is replayed and the local store reaches the current service identity. Each retry logs the topmost endorsement's txid and the mismatching public keys (the endorsement's signer and the expected current network identity), so an operator can diagnose a node that stays in this state (#8042).
7.0.7
Changed
- JWT/JWK auto-refresh outbound HTTP fetches (OpenID metadata and JWKS) now use the curl multi singleton client introduced in #7102, replacing the previous
RPCSessions::create_client()path. Connection and TLS failures are now counted in refresh failure metrics viasend_refresh_jwt_keys_error(), improving observability of network-level refresh errors (#7989). - JWT/JWK auto-refresh now supports configuring the maximum response body size for fetched OpenID metadata and JWKS via the
jwt.key_refresh_max_response_sizenode startup config setting (#7989). - Fatal task worker stack traces now use libbacktrace for improved function and source-location resolution. Building CCF now requires the libbacktrace development package, and the RPM development package depends on
libbacktrace-static(#7721).
Fixed
- Curl multi client shutdown now aborts queued async requests without performing network I/O, and curl response header capture now enforces default header size and count limits (#8005).
- Changing recovery members or the recovery threshold, refreshing recovery shares, or rekeying the ledger while the service is recovering now correctly returns an error instead of appearing to succeed. These operations were always potentially unsafe because at-recovery ledger secrets cannot be rekeyed; services with custom constitutions should update their
set_member,remove_member,set_recovery_threshold,trigger_recovery_shares_refresh, andtrigger_ledger_rekeyactions to reject them while recovering (#7980).
7.0.6
Added
- Experimental support for IPv6. Node RPC and node-to-node interface hosts may now be specified as IPv6 literals in bracketed form (e.g.
[::1]:8000), and addresses are consistently parsed, bound, connected (with fallback across mixed IPv4/IPv6 resolved addresses), serialised, and embedded in redirect URLs for IPv6 (#7671).
Fixed
- Forwarded commands are no longer processed until the node is part of the network, matching the existing behaviour for other node-to-node messages. Previously a forwarded command could be executed while the node was in an earlier startup state, which could lead to undefined behaviour for some commands (#7936).
7.0.5
Changed
- The default and minimal sample constitutions reject
set_jwt_issuerproposals whoseissueris not anhttps://URL with no query or fragment. Previously, any string was accepted whenauto_refreshwasfalse(#7924). - The default and minimal sample constitutions reject
set_ca_cert_bundleproposals containing non-CA certificates or intermediate CA certificates; every certificate in the bundle must be a self-signed (root) CA (#7924). - The default and minimal sample constitutions validate every JWK in
set_jwt_issuerandset_jwt_public_signing_keysproposals:n/e/x/ymust be base64url-encoded,ktymust match the supplied key material,kidmust be unique within a key set,use(if present) must be"sig", andalg(if present) must match the key type and curve per RFC 7518 section 3.4 (RS256for RSA;ES256/ES384/ES512bound toP-256/P-384/P-521). RSA keys must be at least 2048 bits, and EC coordinates must use the full zero-padded length for their curve (RFC 7518 section 6.2.1.2). P-521 is now an accepted EC curve (#7924). - The default and minimal sample constitutions validate that
set_member'sencryption_pub_key, when present, is a well-formed RSA public key (#7924).
Security
- Host-created files (ledger chunks, snapshots, PID file, and node certificate/key files) are now created with restrictive permissions (
0600) instead of relying on the processumask. Existing deployments will not see existing files affected; only newly created files will have these restricted permissions (#7916).
Dependencies
- Updated didx509cpp to 0.99.0 (#7943).
6.0.28
Fixed
- Nodes started in recovery or join mode from a snapshot more recent than the latest ledger file now correctly resume writing from the snapshot boundary (#7901).