Skip to content

opentelemetry: add oauth2 + jwt support#11575

Merged
edsiper merged 8 commits intomasterfrom
oauth2-all
Mar 18, 2026
Merged

opentelemetry: add oauth2 + jwt support#11575
edsiper merged 8 commits intomasterfrom
oauth2-all

Conversation

@edsiper
Copy link
Copy Markdown
Member

@edsiper edsiper commented Mar 17, 2026


Fluent Bit is licensed under Apache 2.0, by submitting this pull request I understand that this code will be released under the terms of that license.

Summary by CodeRabbit

  • New Features

    • Incoming OpenTelemetry: optional OAuth2 JWT validation for requests.
    • Outgoing OpenTelemetry: optional OAuth2 client support with configurable auth methods.
  • Improvements

    • Token caching, refresh behavior and automatic acquisition.
    • Improved auth error handling: explicit 401s, token invalidation and retry (including gRPC paths).
    • Stronger config validation and clearer error messages for OAuth2 setup.

edsiper added 2 commits March 17, 2026 13:59
Signed-off-by: Eduardo Silva <eduardo@chronosphere.io>
Signed-off-by: Eduardo Silva <eduardo@chronosphere.io>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 17, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds OAuth2 and OAuth2-JWT support to OpenTelemetry plugins: input can validate incoming JWTs when enabled (requires issuer and JWKS URL); output can obtain, attach, and manage OAuth2 access tokens for outbound HTTP/gRPC requests, invalidating tokens on 401 or grpc-status=16 and retrying as needed.

Changes

Cohort / File(s) Summary
Input: header & struct
plugins/in_opentelemetry/opentelemetry.h
Added oauth2_cfg and oauth2_ctx fields to the input struct for JWT config and runtime context.
Input: config/init/destroy
plugins/in_opentelemetry/opentelemetry_config.c, plugins/in_opentelemetry/opentelemetry.c
Wired config map for OAuth2-JWT, defaulted JWKS refresh interval, validated oauth2.validate requires issuer and jwks_url, created JWT context during init and destroy it on shutdown.
Input: request handling
plugins/in_opentelemetry/opentelemetry_prot.c
Extract Authorization header and validate JWT via oauth2_ctx for gRPC and HTTP flows; return appropriate 401 (gRPC/HTTP) on validation failure.
Output: header & struct
plugins/out_opentelemetry/opentelemetry.h
Added OAuth2 client config and runtime pointers plus oauth2_auth_method to output context.
Output: config/init/destroy
plugins/out_opentelemetry/opentelemetry_conf.c
Added OAuth2 config_map wiring, auth_method handling, validation of required token_url/client_id/credentials, create oauth2_ctx when enabled, propagate connect_timeout, and destroy on cleanup.
Output: request/send & retry logic
plugins/out_opentelemetry/opentelemetry.c
Use OAuth2 token acquisition and flb_http_do_with_oauth2 / attach Bearer token; invalidate token and trigger retry on 401 or grpc-status=16; fall back to basic auth when OAuth2 disabled.

Sequence Diagrams

sequenceDiagram
    participant Client
    participant OTel_Input as OTel_Input
    participant JWKS as JWKS_Service
    participant Backend
    Client->>OTel_Input: HTTP/gRPC request + Authorization header
    OTel_Input->>JWKS: Validate JWT (issuer, jwks_url)
    alt JWT valid
        JWKS-->>OTel_Input: Valid
        OTel_Input->>Backend: Forward request
        Backend-->>Client: 200 OK
    else JWT invalid
        JWKS-->>OTel_Input: Invalid
        OTel_Input-->>Client: 401 Unauthorized (gRPC or HTTP)
    end
Loading
sequenceDiagram
    participant OTel_Output as OTel_Output
    participant OAuth2Svc as OAuth2_Client
    participant Remote as Remote_Endpoint
    OTel_Output->>OTel_Output: Check oauth2_config.enabled
    alt OAuth2 enabled
        OTel_Output->>OAuth2Svc: Acquire access token (token_url, client creds)
        OAuth2Svc-->>OTel_Output: Access token
        OTel_Output->>Remote: HTTP/gRPC request + Bearer token
        alt 401 or grpc-status=16
            Remote-->>OTel_Output: Unauthorized
            OTel_Output->>OAuth2Svc: Invalidate token
            OTel_Output->>OAuth2Svc: Re-acquire token / Retry
        else Success
            Remote-->>OTel_Output: 200 OK
        end
    else OAuth2 disabled
        OTel_Output->>Remote: HTTP request + Basic Auth
        Remote-->>OTel_Output: Response
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

opentelemetry

Suggested reviewers

  • cosmo0920
  • braydonk
  • fujimotos

Poem

🐰 I hopped through code with a token in paw,
JWKS and OAuth2 — I checked every law.
Input trusts JWTs, output fetches the key,
Bearer on the wire, telemetry hops free! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'opentelemetry: add oauth2 + jwt support' clearly and concisely summarizes the main change: adding OAuth2 and JWT authentication capabilities to the OpenTelemetry input and output plugins.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch oauth2-all
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5c0e2a7d2a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +619 to +620
if (ctx->oauth2_ctx != NULL && response->status == 401) {
flb_oauth2_invalidate_token(ctx->oauth2_ctx);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Retry OAuth2 401 responses before returning flush error

When OAuth2 is enabled on the HTTP/2 code path, a 401 only triggers flb_oauth2_invalidate_token() and then falls through to the existing status handling, which treats 401 as non-retryable and returns FLB_ERROR; this drops the current chunk instead of retrying with a refreshed token. This regression affects OAuth2 users whenever the collector rejects an expired/revoked token on first use, so the request should be retried once (or at least returned as FLB_RETRY) after invalidation.

Useful? React with 👍 / 👎.

Comment on lines +80 to +82
if (ctx->oauth2_cfg.issuer) {
flb_sds_destroy(ctx->oauth2_cfg.issuer);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Stop freeing OAuth2 JWT config strings owned by properties

The teardown path frees ctx->oauth2_cfg string pointers when oauth2_ctx is NULL, but these fields are populated via config-map property binding and are still owned by ins->oauth2_jwt_properties; they are released again later by input-instance cleanup. In configurations where validation is disabled (or init fails before context creation), this introduces a double-free/use-after-free risk during shutdown.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
plugins/out_opentelemetry/opentelemetry.h (1)

63-65: Use const char * for the borrowed oauth2_auth_method.

plugins/out_opentelemetry/opentelemetry_conf.c stores the raw flb_kv_get_key_value() result in this field without cloning it, so flb_sds_t overstates the ownership and mutability here.

♻️ Proposed fix
-    flb_sds_t oauth2_auth_method;
+    const char *oauth2_auth_method;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/out_opentelemetry/opentelemetry.h` around lines 63 - 65, The
oauth2_auth_method field currently declared as flb_sds_t in struct
flb_oauth2_config/oauth2_ctx should be changed to const char * because
opentelemetry_conf.c stores the borrowed pointer returned by
flb_kv_get_key_value() without cloning; update the declaration of
oauth2_auth_method in plugins/out_opentelemetry/opentelemetry.h to const char
*oauth2_auth_method and then adjust any code that assumed ownership/mutability
(e.g., remove any flb_sds_free or mutating calls and treat it as a borrowed C
string wherever oauth2_auth_method is read, and ensure opentelemetry_conf.c
assigns the flb_kv_get_key_value() result directly to this field).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/in_opentelemetry/opentelemetry_config.c`:
- Around line 72-91: The code currently destroys config-backed JWT strings
(ctx->oauth2_cfg.issuer, jwks_url, allowed_audience) only when ctx->oauth2_ctx
is NULL, which causes mismatched lifetimes and potential double-free; remove the
flb_sds_destroy calls in the else branch and stop freeing or resetting those
config-backed fields here so they remain managed by the input config teardown,
leaving the flb_oauth2_jwt_context_destroy call and any NULL assignments only
for oauth2_ctx-managed resources (refer to ctx->oauth2_ctx,
flb_oauth2_jwt_context_destroy, and ctx->oauth2_cfg.*).

In `@plugins/out_opentelemetry/opentelemetry.c`:
- Around line 619-621: The current code only invalidates the OAuth2 cache on
HTTP 401; extend this so when opentelemetry_check_grpc_status(...) returns GRPC
status 16 (UNAUTHENTICATED) you also call flb_oauth2_invalidate_token on
ctx->oauth2_ctx. Locate the place where
opentelemetry_check_grpc_status(response, ...) is used, and add a null-checked
call to flb_oauth2_invalidate_token(ctx->oauth2_ctx) when the function indicates
status 16, mirroring the existing invalidation logic that checks
response->status == 401.

---

Nitpick comments:
In `@plugins/out_opentelemetry/opentelemetry.h`:
- Around line 63-65: The oauth2_auth_method field currently declared as
flb_sds_t in struct flb_oauth2_config/oauth2_ctx should be changed to const char
* because opentelemetry_conf.c stores the borrowed pointer returned by
flb_kv_get_key_value() without cloning; update the declaration of
oauth2_auth_method in plugins/out_opentelemetry/opentelemetry.h to const char
*oauth2_auth_method and then adjust any code that assumed ownership/mutability
(e.g., remove any flb_sds_free or mutating calls and treat it as a borrowed C
string wherever oauth2_auth_method is read, and ensure opentelemetry_conf.c
assigns the flb_kv_get_key_value() result directly to this field).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e4ecce43-7305-44b0-84ba-f34fc4d87321

📥 Commits

Reviewing files that changed from the base of the PR and between 81eb49f and 5c0e2a7.

📒 Files selected for processing (7)
  • plugins/in_opentelemetry/opentelemetry.c
  • plugins/in_opentelemetry/opentelemetry.h
  • plugins/in_opentelemetry/opentelemetry_config.c
  • plugins/in_opentelemetry/opentelemetry_prot.c
  • plugins/out_opentelemetry/opentelemetry.c
  • plugins/out_opentelemetry/opentelemetry.h
  • plugins/out_opentelemetry/opentelemetry_conf.c

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/out_opentelemetry/opentelemetry.c`:
- Around line 170-172: The current logic invalidates the cached token
(flb_oauth2_invalidate_token(ctx->oauth2_ctx)) when grpc_status == 16 or HTTP
401 but then treats the response as non-retryable and returns FLB_ERROR; change
the control flow so that after invalidating ctx->oauth2_ctx you return a retry
signal (e.g., FLB_RETRY) so the chunk is resent with a fresh token instead of
being dropped. Locate the two spots referencing grpc_status == 16 and the HTTP
401 branch (the calls to flb_oauth2_invalidate_token) and replace the final
non-retry return with a retry return when ctx->oauth2_ctx was present and
invalidated. Ensure you keep the invalidation call and only adjust the return
value/path to trigger a retry.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cd33a1dc-1ec4-4820-8bc4-c3f278ca3ef7

📥 Commits

Reviewing files that changed from the base of the PR and between 5c0e2a7 and fd82d61.

📒 Files selected for processing (4)
  • plugins/in_opentelemetry/opentelemetry_config.c
  • plugins/out_opentelemetry/opentelemetry.c
  • plugins/out_opentelemetry/opentelemetry.h
  • plugins/out_opentelemetry/opentelemetry_conf.c
🚧 Files skipped from review as they are similar to previous changes (1)
  • plugins/out_opentelemetry/opentelemetry.h

edsiper added 3 commits March 18, 2026 08:56
Signed-off-by: Eduardo Silva <eduardo@chronosphere.io>
Signed-off-by: Eduardo Silva <eduardo@chronosphere.io>
Signed-off-by: Eduardo Silva <eduardo@chronosphere.io>
Signed-off-by: Eduardo Silva <eduardo@chronosphere.io>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/out_opentelemetry/opentelemetry_conf.c`:
- Around line 294-296: The early-return on oauth2 config-map parse failure
currently calls flb_free(ctx) and leaks ctx->oauth2_config; replace that direct
free with the structured teardown used elsewhere by calling
flb_opentelemetry_context_destroy(ctx) instead (the failure branch after
flb_config_map_set()/ret == -1 should invoke flb_opentelemetry_context_destroy
to free ctx->oauth2_config and other subfields before returning NULL).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 462e0bd0-765e-40d4-81a9-3c2f052aea43

📥 Commits

Reviewing files that changed from the base of the PR and between 570e573 and 8f29edf.

📒 Files selected for processing (2)
  • plugins/out_opentelemetry/opentelemetry.c
  • plugins/out_opentelemetry/opentelemetry_conf.c
🚧 Files skipped from review as they are similar to previous changes (1)
  • plugins/out_opentelemetry/opentelemetry.c

Signed-off-by: Eduardo Silva <eduardo@chronosphere.io>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/out_opentelemetry/opentelemetry_conf.c`:
- Around line 457-463: After successfully creating ctx->oauth2_ctx via
flb_oauth2_create_from_config, ensure any subsequent early returns (e.g., the
invalid-compression branch that currently returns directly) properly clean up
the OAuth2/upstream resources by calling flb_opentelemetry_context_destroy (or
the specific oauth2 cleanup routine) before returning; locate the
invalid-compression return and add a call to
flb_opentelemetry_context_destroy(ctx) (or ctx->oauth2_ctx destroy) so
ctx->oauth2_ctx and related resources are freed on all error paths.
- Around line 290-303: The oauth2 parsing path can allocate resources into
ctx->oauth2_config but later code frees ctx raw without running structured
cleanup, leaking memory; fix this by ensuring the upstream initialization
failure path invokes the structured teardown (call
flb_opentelemetry_context_destroy(ctx) or an equivalent cleanup that frees
ctx->oauth2_config) instead of doing a raw free, or explicitly release all
allocations inside ctx->oauth2_config before freeing ctx so that resources set
by flb_config_map_set are properly cleaned up.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8aeeb811-fb4a-409b-bcf9-dca222f2e7f4

📥 Commits

Reviewing files that changed from the base of the PR and between 8f29edf and 38290f9.

📒 Files selected for processing (1)
  • plugins/out_opentelemetry/opentelemetry_conf.c

Signed-off-by: Eduardo Silva <eduardo@chronosphere.io>
@edsiper edsiper merged commit 90ade36 into master Mar 18, 2026
47 of 49 checks passed
@edsiper edsiper deleted the oauth2-all branch March 18, 2026 20:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant