oscerd opened a new pull request, #27781:
URL: https://github.com/apache/camel/pull/27781
## Backport of #27716
Backport of #27716 (CAMEL-25564, merged on `main` as 60104cd3a195) onto
`camel-4.22.x`.
**Original PR:** #27716 - CAMEL-25564: camel-telegram - verify the Bot API
secret token on webhook updates
**Original author:** @oscerd
**Target branch:** `camel-4.22.x`
### Differences from #27716
This is not a straight cherry-pick, so it needs a review:
- `TelegramAsyncHandler`: #27716 sits on CAMEL-25577 (#27761), which is on
`main` only and removed the
`AsyncCallback` from the handler. `camel-4.22.x` still has the
five-argument constructor and the
`finally { callback.done(false); }`. The change of #27716 (the HTTP method
and the method of the Bot API instead of
the request URI, in the TRACE log and in the exception messages) is
applied to that version of the handler, and
`TelegramServiceRestBotAPIAdapterErrorTest` passes a callback to it.
- The upgrade-guide note is not part of the backport: it is on `main`
already, in `camel-4x-upgrade-guide-4_22.adoc`
("Upgrading from 4.22.1 to 4.22.2").
- The generated files are regenerated on this branch.
The options, the endpoint, the webhook processor, the adapter, the component
page and the other tests are identical
to #27716.
### Tests
- `camel-telegram` on `camel-4.22.x`: 105 tests, 0 failures (1 skipped, as
before).
- Full reactor `mvn clean install -DskipTests -DskipITs` on `camel-4.22.x`:
green. Regenerated: the component JSON,
configurer and URI factory, the catalog JSON and component page mirror,
the endpoint DSL, and the `SecurityUtils`
entry for `webhookSecretTokenEnabled`.
### Original description
## Description
[CAMEL-25564](https://issues.apache.org/jira/browse/CAMEL-25564)
In webhook mode, camel-telegram registered the webhook with the `url`
parameter only. The Bot API's `setWebhook` also
accepts a `secret_token`, which Telegram sends back in the
`X-Telegram-Bot-Api-Secret-Token` header of every webhook
request. This PR uses it:
- New endpoint option `webhookSecretToken` (label `consumer,security`,
marked as a secret). When it is not set, the
token is derived from the authorization token: HMAC-SHA256, base64url
without padding, so 43 characters from the set
Telegram allows. A derived value, rather than a random one, stays the same
across restarts and across replicas that
serve the same webhook URL. It also lets the two sides of the
`WebhookRoutePolicy` flow (a registration run and the
serving instances, both with `webhookAutoRegister=false`) agree on the
token without extra configuration. A
configured value is checked against Telegram's rules: 1 to 256 characters,
only `A-Z`, `a-z`, `0-9`, `_` and `-`.
- New endpoint option `webhookSecretTokenEnabled` (default `true`, marked
`insecure:dev` with insecure value `false`).
Setting it to `false` restores the previous behaviour: the webhook is
registered without a secret token, and webhook
requests are not verified. The endpoint logs a WARN at startup in that
case.
- `TelegramEndpoint.registerWebhook()` passes the token to `setWebhook`,
through a new
`TelegramService.setWebhook(url, secretToken)` overload. The existing
one-argument method is kept, and is used when
the secret token is disabled.
- `TelegramWebhookProcessor` compares the header with the token in constant
time, before it parses the body. A
request without the header, or with a different value, gets HTTP 403, is
logged at WARN, and does not reach the
route. The header is removed from the message, so the token is not passed
on to the route.
- The errors and TRACE logs of the Bot API requests no longer show the
request URI, which contains the authorization
token (and now the secret token of `setWebhook`). They show the HTTP
method and the method of the Bot API instead,
such as `Could not GET setWebhook: 401 ...` or `POST sendMessage
responded: 400...`. This applies to
`TelegramServiceRestBotAPIAdapter.sendSyncRequest` (`getUpdates`,
`setWebhook`, `deleteWebhook`) and to the
producer's `TelegramAsyncHandler`.
- Docs: the webhook mode section of the component page, and upgrade-guide
notes for 4.24, 4.22.2 and 4.18.6. The
backports to `camel-4.22.x` and `camel-4.18.x` will follow once this is
merged.
### Behaviour change
- When Camel registers the webhook at startup (the default
`webhookAutoRegister=true`), nothing needs to change:
each upgraded instance registers the webhook with the token, and the
instances that are not upgraded yet ignore the
header.
- When the webhook is registered in another way, through the
`WebhookRoutePolicy` or outside Camel, the registration
made with the previous version has no secret token, so the upgraded
instances reject every update until the webhook
is registered again with it. The upgrade notes give the safe order:
register again first (the instances of the
previous version ignore the header), then upgrade the instances that
receive the updates. Outside Camel,
`webhookSecretToken` must be set and passed as `secret_token`.
- The default webhook path is a hash of the endpoint URI, so adding an
option to the URI, such as
`webhookSecretToken` or `webhookSecretTokenEnabled`, changes the path.
When the webhook is not registered by Camel
at startup, `webhookPath` keeps the registered path. The upgrade notes and
the component page say so.
- `webhookSecretTokenEnabled=false` restores the previous behaviour.
- A client that calls the webhook endpoint directly must send the header.
That includes two downstream tests:
`TelegramWebhookCallTest` in camel-spring-boot (`camel-telegram-starter`),
and `TelegramTest#testWebhookEndpoint`
in the camel-quarkus telegram integration tests. As
`deriveWebhookSecretToken` is package-private, they need to set
`webhookSecretToken` and send the same value.
## Tests
- `TelegramWebhookCallTest`: a request is accepted with the derived token
and with a configured token, and the route
does not see the header. A request without the header, or with a wrong
value, gets 403, and the route is not invoked.
With `webhookSecretTokenEnabled=false`, a request without the header
reaches the route.
- `TelegramWebhookSecretTokenTest`: the derived token is stable, differs for
another authorization token and uses only
the allowed characters. An invalid configured token is refused.
Registration sends the derived token, or the
configured one, as `secret_token`, and no `secret_token` when the secret
token is disabled; this is checked against
a mock Telegram API.
- `TelegramServiceRestBotAPIAdapterErrorTest`: the error of a failed
`setWebhook` (sync) and of a failed
`sendMessage` (async) shows the HTTP method and the method of the Bot API,
and neither the authorization token nor
the secret token.
- `camel-telegram`: 111 tests, 0 failures (1 skipped, as before), including
`TelegramProducerFailureTest` from CAMEL-25577, which this branch is rebased on.
- Full reactor `mvn clean install -DskipTests -DskipITs`: green; the
regenerated files are included.
_Claude Code 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]