shashank created CAMEL-25729:
--------------------------------

             Summary: camel-aws-secrets-manager - the CloudTrail refresh task 
reads one page of events per check and starts the next check one second later, 
so a secret update can be missed and the context is not reloaded
                 Key: CAMEL-25729
                 URL: https://issues.apache.org/jira/browse/CAMEL-25729
             Project: Camel
          Issue Type: Bug
          Components: camel-aws
            Reporter: shashank
            Assignee: shashank


With {{camel.vault.aws.refreshEnabled=true}} and without SQS notification (the 
default mode), {{CloudTrailReloadTriggerTask.run}} (main 55ed20f14e90, lines 
276-291) sends one {{LookupEvents}} request per check:

{code:java}
LookupEventsRequest.Builder eventsRequestBuilder = LookupEventsRequest.builder()
        .maxResults(100)
        .lookupAttributes(... EVENT_SOURCE = "secretsmanager.amazonaws.com" 
...);
if (lastTime != null) {
    eventsRequestBuilder.startTime(lastTime.plusMillis(1000));
}
LookupEventsResponse response = 
cloudTrailClient.lookupEvents(lookupEventsRequest);
List<Event> events = response.events();
if (!events.isEmpty()) {
    lastTime = events.get(0).eventTime();
}
{code}

The lookup is by event source only, so it returns every Secrets Manager call of 
the account and Region, including the read calls ({{GetSecretValue}}, 
{{DescribeSecret}}, ...) of every application, newest first. Three problems, 
the same ones CAMEL-24082 fixed in the camel-aws-cloudtrail consumer:

# {{nextToken}} is never read. The LookupEvents API reference says "The default 
number of results returned is 50, with a maximum of 50 possible" and 
"MaxResults ... Valid Range: Minimum value of 1. Maximum value of 50"; the task 
asks for 100. When more events than one page were recorded after a 
{{PutSecretValue}} / {{UpdateSecret}} of a tracked secret within one check 
period (30 s by default), the update is not in the first page, the position 
moves to the newest event, and the update is never looked at. (If the service 
rejects 100 with {{InvalidMaxResultsException}} instead, every check fails with 
a WARN and the mode never works. This was not checked against AWS; the fix is 
right in both cases.)
# The next check starts at {{lastTime + 1 s}}. {{StartTime}} is inclusive 
("events that occur after or at the specified time") and CloudTrail event times 
have a precision of one second, so an update recorded in the same second as the 
newest event of the previous check, but not yet returned by it, is skipped.
# The first check has no start time and looks at the newest events of the last 
90 days: an old update of a tracked secret among them reloads the context about 
30 seconds after the start.

In cases 1 and 2 the context is not reloaded and keeps the old secret values; 
nothing is logged. With rotation, the application keeps using a credential that 
is replaced (and usually revoked soon after).

h3. Reproduction

New {{CloudTrailReloadTriggerTaskLookupTest}} with a mocked 
{{CloudTrailClient}} that answers like the service (events at or after 
{{startTime}}, newest first, at most 50 per page, a {{nextToken}} while events 
are left):
* {{updateBehindMoreThanOnePageOfOtherEventsReloadsTheContext}}: one 
{{PutSecretValue}} of the tracked secret, then 60 {{GetSecretValue}} of another 
secret; one check must reload the context.
* {{updateInTheSameSecondAsTheNewestEventSeenIsNotSkipped}}: a check sees a 
{{GetSecretValue}} at second T; then a {{PutSecretValue}} at T becomes visible; 
the next check must reload the context, and a third check must not reload it 
again.
* {{firstCheckLooksUpFromTheStartOfTheTask}}: an update made a day before the 
task started must not reload the context, and the first request has a start 
time.
On main all three fail ({{the update on the second page must be seen}}, {{the 
update in the same second must be seen}}, {{the first lookup must not read the 
whole event history}}), 3 of 3 runs.

h3. Proposed fix

Each check reads every page from the newest event time seen (inclusive), 50 
events per page, and skips the events of that instant that the previous check 
already handled, by event id (as {{CloudtrailConsumer.poll}} does on main since 
CAMEL-24082, lines 68-119). The position starts when the task starts. If a page 
fails, the position does not move, and the next check reads the same events 
again. Upgrade note in the 4.24 guide (the first check no longer reacts to an 
update made before the start; one request per 50 events).

Cost and limit: a check sends one request per 50 Secrets Manager events of the 
account and Region since the previous check (main: always one). The API 
reference says "The rate of lookup requests is limited to two per second, per 
account, per Region"; a throttled request is retried by the SDK, and if it 
still fails the check fails as on main (WARN) and the next check reads the same 
events again. There is no cap on the pages of a check (unlike the cloudtrail 
consumer's {{maxResults}}, the page size is fixed): an account with more than 
about 100 Secrets Manager calls per second on average cannot be followed at 
that rate, which is the case where main already misses almost every update; the 
SQS notification mode is the better choice there (said in the upgrade note).

With the fix the camel-aws-secrets-manager tests pass: 9 run, 0 failures, 0 
errors, 0 skipped.

Not covered: an event that becomes visible after a newer one was seen in an 
earlier check (CloudTrail delivery delay); that is the same question as for the 
camel-aws-cloudtrail consumer. Not run against AWS.

Affected: main (tested); camel-4.23.x, camel-4.22.x and camel-4.18.x have the 
same code (read, not run).

Duplicate check (2026-10-17): JIRA text "CloudTrailReloadTriggerTask", "secrets 
manager cloudtrail", "aws secrets refresh": CAMEL-18468 (the task), 
CAMEL-21324, CAMEL-24193 (SQS mode), none about paging or the start time; 
GitHub pull requests "CloudTrailReloadTriggerTask": #24726 (CAMEL-24082, the 
consumer only), #24847, #25326.

_Filed with Claude Code on behalf of allthingssecurity._




--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to