mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-16 01:48:21 +00:00
feat(kms): report which keys have outlived their rotation period (#5769)
rustfs/backlog#1636 rejected a built-in rotation scheduler: rotation is a policy decision with a per-backend cost and a hard upgrade-ordering constraint, and a server that rotated on its own would make that decision on an operator's behalf at a moment they did not choose. This is what that issue resolved to deliver instead — the signal, without the actuator. RUSTFS_KMS_ROTATION_MAX_AGE_SECS names the period. Unset leaves the verdict unreported rather than assuming a policy, because how often keys must be rotated is a compliance decision and a built-in default would report keys as overdue against a rule nobody wrote; an unparsable value is refused the same way, loudly. Values below an hour are raised to it, since a threshold of seconds reports every key as overdue moments after it was rotated and teaches operators to ignore the signal. KeyInfo gains rotation_due and rotation_due_reason, both additive on the wire and both filled in by the manager rather than by each backend, so no two backends can disagree about what overdue means. A backend that does not advertise rotation reports unsupported and is never reported as due — it must not be told to do something it cannot. A key with no recorded rotation is measured from creation, which is how long its material has actually been in use, and is distinguished from a stale rotation so an operator can tell "overdue again" from "never once". Ages are computed saturating, so a timestamp from a node running ahead cannot manufacture an overdue key. The verdict is advisory in the strongest sense: nothing consults it before encrypting or decrypting, a key reported as due keeps serving traffic, and readiness is unaffected. The single-key describe response deliberately does not carry the verdict. Its type records a creation date but no rotation timestamp, so a verdict computed there could not tell a key rotated last week from one never rotated, and reporting never_rotated for a key that was in fact rotated is worse than reporting nothing. The wraps-based branch the issue also specifies is not implemented: it depends on the per-key wrap accounting that does not exist yet.
This commit is contained in:
@@ -503,7 +503,7 @@ mod tests {
|
||||
use jiff::Zoned;
|
||||
use rustfs_kms::{
|
||||
KeyImpactReport, KeyInfo, KeyMetadata, KeyReference, KeyReferenceKind, KeyState, KeyStatus, KeyUsage, KmsError,
|
||||
ReferenceScope,
|
||||
ReferenceScope, RotationDueReason,
|
||||
};
|
||||
use rustfs_policy::policy::action::{Action, AdminAction, KmsAction};
|
||||
use rustfs_policy::policy::{Args, Policy};
|
||||
@@ -972,6 +972,10 @@ mod tests {
|
||||
created_at: fixed_zoned("2026-01-01T00:00:00Z[UTC]"),
|
||||
rotated_at: Some(fixed_zoned("2026-01-15T00:00:00Z[UTC]")),
|
||||
created_by: Some("admin".to_string()),
|
||||
// Pinned as a key with a verdict: the empty case is already the
|
||||
// default, and only a populated one fixes the wire names.
|
||||
rotation_due: true,
|
||||
rotation_due_reason: Some(RotationDueReason::Age),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -14,6 +14,8 @@ expression: "stable_json_value(ListKeysApiResponse\n{\n keys: vec![snapshot_k
|
||||
"origin": "RUSTFS_KMS"
|
||||
},
|
||||
"rotated_at": "2026-01-15T00:00:00+00:00[UTC]",
|
||||
"rotation_due": true,
|
||||
"rotation_due_reason": "age",
|
||||
"status": "Active",
|
||||
"tags": {
|
||||
"name": "key-a"
|
||||
|
||||
+2
@@ -14,6 +14,8 @@ expression: "stable_json_value(ListKeysApiResponse\n{\n keys: vec![snapshot_k
|
||||
"origin": "RUSTFS_KMS"
|
||||
},
|
||||
"rotated_at": "2026-01-15T00:00:00+00:00[UTC]",
|
||||
"rotation_due": true,
|
||||
"rotation_due_reason": "age",
|
||||
"status": "Active",
|
||||
"tags": {
|
||||
"name": "key-a"
|
||||
|
||||
+2
@@ -14,6 +14,8 @@ expression: "stable_json_value(ListKmsKeysResponse\n{\n success: true, messag
|
||||
"origin": "RUSTFS_KMS"
|
||||
},
|
||||
"rotated_at": "2026-01-15T00:00:00+00:00[UTC]",
|
||||
"rotation_due": true,
|
||||
"rotation_due_reason": "age",
|
||||
"status": "Active",
|
||||
"tags": {
|
||||
"name": "key-a"
|
||||
|
||||
+2
@@ -14,6 +14,8 @@ expression: "stable_json_value(ListKmsKeysResponse\n{\n success: true, messag
|
||||
"origin": "RUSTFS_KMS"
|
||||
},
|
||||
"rotated_at": "2026-01-15T00:00:00+00:00[UTC]",
|
||||
"rotation_due": true,
|
||||
"rotation_due_reason": "age",
|
||||
"status": "Active",
|
||||
"tags": {
|
||||
"name": "key-a"
|
||||
|
||||
Reference in New Issue
Block a user