oscerd opened a new pull request, #28094:
URL: https://github.com/apache/camel/pull/28094

   Fixes [CAMEL-25797](https://issues.apache.org/jira/browse/CAMEL-25797).
   
   `KeyRotationScheduler` documents three rotation signals — key age, usage 
count, and a `PENDING_ROTATION` status. Two
   of the three could never trigger.
   
   ## 1. `usageCount` was only advanced for stateful keys
   
   `KeyMetadata.updateLastUsed()` is the only thing that increments the 
counter, and its single production caller sat
   inside `persistStatefulKeyStateAfterSign()` behind:
   
   ```java
   long remaining = getStatefulKeyRemaining(privateKey);
   if (remaining < 0) {
       // Not a stateful key
       return;
   }
   ```
   
   So for ML-DSA, SLH-DSA, Falcon and every KEM key — the overwhelming majority 
— the counter stayed at `0` forever,
   while all five lifecycle managers gate on `maxUsage > 0 && 
metadata.getUsageCount() >= maxUsage`.
   `setMaxKeyUsage` and the documented 
`camel.component.pqc.key-rotation-max-usage` property were inert.
   
   The method is now `recordKeyUsageAfterSign()`. It advances and persists the 
usage count for **every** key, and
   re-stores the key pair itself only for the stateful algorithms, where the 
advanced one-time index has to survive a
   restart. That also drops a redundant remote write per signature for 
non-stateful keys — they previously did a
   `storeKey` only in the stateful branch, so this strictly reduces traffic 
relative to what stateful keys already do
   while finally recording usage for the rest.
   
   ## 2. `PENDING_ROTATION` was filtered out before it was read
   
   ```java
   private Predicate<KeyMetadata> keyFilter = metadata -> metadata.getStatus() 
== KeyMetadata.KeyStatus.ACTIVE;
   ```
   
   `KeyMetadata.needsRotation()` does test for `PENDING_ROTATION`, but a key 
marked that way is no longer `ACTIVE`, so
   the scheduler `continue`d past it at the filter before `needsRotation()` was 
ever consulted. Only `nextRotationAt` on
   an otherwise-ACTIVE key actually worked.
   
   The default filter now accepts `ACTIVE` and `PENDING_ROTATION`. A filter 
supplied via `setKeyFilter` is unaffected.
   Javadoc on the class and on `setKeyFilter` updated to match.
   
   ## Tests
   
   New `KeyRotationSignalsTest`:
   
   - `signingAStatelessKeyAdvancesTheUsageCount` — three ML-DSA signatures, 
asserts the count reaches 3 and that
     `needsRotation(.., maxUsage=3)` then reports true;
   - `aPendingRotationKeyIsSelectedByTheDefaultFilter` — asserts the default 
filter accepts the key and that
     `checkAndRotate()` actually rotates it.
   
   Against `main`: `expected: <3> but was: <0>` and `expected: <true> but was: 
<false>`. Full `camel-pqc` build green:
   241 tests, 0 failures, no regenerated-file drift.
   
   ## Scope note
   
   Usage is recorded on the signing paths, which are the ones that already had 
the hook. A pure-KEM deployment still
   will not advance `usageCount`; extending the hook to the KEM operations is a 
larger behavioural change and is better
   done separately if wanted.
   
   ## Upgrade guide
   
   Added a 4.24 entry. This makes previously-inert configuration take effect, 
so a deployment that already set
   `maxKeyUsage` may rotate on the first check once the counter starts moving — 
worth flagging before upgrade.
   
   ---
   _Reported, analysed and fixed by Claude Code (AI agent) on behalf of 
@oscerd._
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to