From c46768686fea34eafcb33a10c3e1c90a326e88c8 Mon Sep 17 00:00:00 2001 From: arj22 Date: Mon, 3 Aug 2026 21:15:11 -0500 Subject: [PATCH 1/2] feat(otel-collector): add OIDC bearer token auth for the OTLP receiver Adds oidcauthextension as an alternative to the existing static bearer token auth (config.standalone.auth.yaml / OTLP_AUTH_TOKEN) in standalone mode. This lets self-hosters authenticate OTLP producers with per-client, short-lived, centrally-issued JWTs (validated against a provider's published JWKS) instead of a single long-lived shared secret -- useful for large/untrusted fleets where a leaked static token would otherwise compromise every sender indefinitely. - packages/otel-collector/builder-config.yaml: add oidcauthextension to the OCB build manifest - docker/otel-collector/config.standalone.oidc.yaml: new, mirrors config.standalone.auth.yaml's pattern -- OIDC_ISSUER_URL/OIDC_AUDIENCE env vars configure the extension on both OTLP protocols - docker/otel-collector/entrypoint.sh: include the new config when OIDC_ISSUER_URL is set, otherwise fall back to OTLP_AUTH_TOKEN as before (the two are mutually exclusive, since both configure the same receiver's auth.authenticator) - docker/otel-collector/Dockerfile: copy the new config file into both the dev and prod image stages Validated with a local `docker build --target ocb-builder` -- the extension compiles into otelcol-hyperdx and shows up in `components` output. Not yet covered by an automated test; happy to add one if there's a preferred pattern for extension-config integration tests in this repo. This was drafted with Claude Code assistance and reviewed/tested by me before opening. Co-Authored-By: Claude Sonnet 5 --- docker/otel-collector/Dockerfile | 2 ++ .../config.standalone.oidc.yaml | 27 +++++++++++++++++++ docker/otel-collector/entrypoint.sh | 11 ++++++-- packages/otel-collector/builder-config.yaml | 3 +++ 4 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 docker/otel-collector/config.standalone.oidc.yaml diff --git a/docker/otel-collector/Dockerfile b/docker/otel-collector/Dockerfile index f3aaf44853..e57f018422 100644 --- a/docker/otel-collector/Dockerfile +++ b/docker/otel-collector/Dockerfile @@ -75,6 +75,7 @@ LABEL org.opencontainers.image.vendor="HyperDX" \ COPY --chown=10001:10001 docker/otel-collector/config.yaml /etc/otelcol-contrib/config.yaml COPY --chown=10001:10001 docker/otel-collector/config.standalone.yaml /etc/otelcol-contrib/standalone-config.yaml COPY --chown=10001:10001 docker/otel-collector/config.standalone.auth.yaml /etc/otelcol-contrib/standalone-auth-config.yaml +COPY --chown=10001:10001 docker/otel-collector/config.standalone.oidc.yaml /etc/otelcol-contrib/standalone-oidc-config.yaml COPY --chown=10001:10001 docker/otel-collector/config.standalone.promql.yaml /etc/otelcol-contrib/standalone-promql-config.yaml COPY --chown=10001:10001 docker/otel-collector/supervisor_docker.yaml.tmpl /etc/otel/supervisor.yaml.tmpl COPY --chown=10001:10001 docker/otel-collector/schema /etc/otel/schema @@ -98,6 +99,7 @@ LABEL org.opencontainers.image.vendor="HyperDX" \ COPY --chown=10001:10001 docker/otel-collector/config.yaml /etc/otelcol-contrib/config.yaml COPY --chown=10001:10001 docker/otel-collector/config.standalone.yaml /etc/otelcol-contrib/standalone-config.yaml COPY --chown=10001:10001 docker/otel-collector/config.standalone.auth.yaml /etc/otelcol-contrib/standalone-auth-config.yaml +COPY --chown=10001:10001 docker/otel-collector/config.standalone.oidc.yaml /etc/otelcol-contrib/standalone-oidc-config.yaml COPY --chown=10001:10001 docker/otel-collector/config.standalone.promql.yaml /etc/otelcol-contrib/standalone-promql-config.yaml COPY --chown=10001:10001 docker/otel-collector/supervisor_docker.yaml.tmpl /etc/otel/supervisor.yaml.tmpl COPY --chown=10001:10001 docker/otel-collector/schema /etc/otel/schema diff --git a/docker/otel-collector/config.standalone.oidc.yaml b/docker/otel-collector/config.standalone.oidc.yaml new file mode 100644 index 0000000000..1df6484311 --- /dev/null +++ b/docker/otel-collector/config.standalone.oidc.yaml @@ -0,0 +1,27 @@ +# This configuration enables OIDC-based bearer token authentication for the +# OTLP receiver. Only included when OIDC_ISSUER_URL environment variable is set. +# +# Clients must present a JWT as a bearer token (Authorization: Bearer ). +# The collector verifies the token's signature against the issuer's published +# JWKS (fetched from {issuer_url}/.well-known/openid-configuration), and +# validates the issuer and audience claims. This is intended for deployments +# that want short-lived, centrally-issued tokens instead of (or in addition +# to) a long-lived static token -- see config.standalone.auth.yaml. + +extensions: + oidc/hyperdx: + issuer_url: ${env:OIDC_ISSUER_URL} + audience: ${env:OIDC_AUDIENCE} + +receivers: + otlp/hyperdx: + protocols: + grpc: + auth: + authenticator: oidc/hyperdx + http: + auth: + authenticator: oidc/hyperdx + +service: + extensions: [health_check, oidc/hyperdx] diff --git a/docker/otel-collector/entrypoint.sh b/docker/otel-collector/entrypoint.sh index ca05993b29..6dc7311555 100644 --- a/docker/otel-collector/entrypoint.sh +++ b/docker/otel-collector/entrypoint.sh @@ -45,8 +45,15 @@ if [ -z "$OPAMP_SERVER_URL" ]; then # Build collector arguments with multiple config files COLLECTOR_ARGS="--config /etc/otelcol-contrib/config.yaml --config /etc/otelcol-contrib/standalone-config.yaml" - # Add bearer token auth config if OTLP_AUTH_TOKEN is specified (only used in standalone mode) - if [ -n "$OTLP_AUTH_TOKEN" ]; then + # Add OIDC-based bearer token auth config if OIDC_ISSUER_URL is specified, + # otherwise fall back to static bearer token auth if OTLP_AUTH_TOKEN is + # specified (only used in standalone mode). These are mutually exclusive: + # both configure the same receiver's auth.authenticator, so enabling both + # would just make whichever config file is loaded last win. + if [ -n "$OIDC_ISSUER_URL" ]; then + echo "OIDC_ISSUER_URL is configured, enabling OIDC-based bearer token authentication" + COLLECTOR_ARGS="$COLLECTOR_ARGS --config /etc/otelcol-contrib/standalone-oidc-config.yaml" + elif [ -n "$OTLP_AUTH_TOKEN" ]; then echo "OTLP_AUTH_TOKEN is configured, enabling bearer token authentication" COLLECTOR_ARGS="$COLLECTOR_ARGS --config /etc/otelcol-contrib/standalone-auth-config.yaml" fi diff --git a/packages/otel-collector/builder-config.yaml b/packages/otel-collector/builder-config.yaml index ecd794a456..2577afaaf6 100644 --- a/packages/otel-collector/builder-config.yaml +++ b/packages/otel-collector/builder-config.yaml @@ -148,6 +148,9 @@ extensions: - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/extension/bearertokenauthextension v__OTEL_COLLECTOR_VERSION__ + - gomod: + github.com/open-telemetry/opentelemetry-collector-contrib/extension/oidcauthextension + v__OTEL_COLLECTOR_VERSION__ - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage/filestorage v__OTEL_COLLECTOR_VERSION__ From e5d148f65da42553b5b943fc656bb0ab456f2639 Mon Sep 17 00:00:00 2001 From: arj22 Date: Mon, 3 Aug 2026 21:23:26 -0500 Subject: [PATCH 2/2] fix: fail fast when OIDC_AUDIENCE is missing; add changeset Addresses review feedback on #2788: - entrypoint.sh: oidcauthextension requires a non-empty audience unless ignore_audience is set. Previously, setting OIDC_ISSUER_URL without OIDC_AUDIENCE would load a config that fails the extension's own validation, crashing the collector with a less obvious error. Now checked explicitly with a clear message before that happens. - .changeset/add-oidc-otlp-auth.md: this is a user-facing change to a published package (@hyperdx/otel-collector), which AGENTS.md requires a changeset for. Missed in the initial commit. Co-Authored-By: Claude Sonnet 5 --- .changeset/add-oidc-otlp-auth.md | 5 +++++ docker/otel-collector/entrypoint.sh | 9 +++++++++ 2 files changed, 14 insertions(+) create mode 100644 .changeset/add-oidc-otlp-auth.md diff --git a/.changeset/add-oidc-otlp-auth.md b/.changeset/add-oidc-otlp-auth.md new file mode 100644 index 0000000000..bc564645e3 --- /dev/null +++ b/.changeset/add-oidc-otlp-auth.md @@ -0,0 +1,5 @@ +--- +'@hyperdx/otel-collector': minor +--- + +Add OIDC-based bearer token authentication for the OTLP receiver in standalone mode, as an alternative to the existing static `OTLP_AUTH_TOKEN`. Set `OIDC_ISSUER_URL` and `OIDC_AUDIENCE` to validate incoming OTLP requests against an OIDC provider's published JWKS instead of a single long-lived shared secret. diff --git a/docker/otel-collector/entrypoint.sh b/docker/otel-collector/entrypoint.sh index 6dc7311555..91e84e1659 100644 --- a/docker/otel-collector/entrypoint.sh +++ b/docker/otel-collector/entrypoint.sh @@ -51,6 +51,15 @@ if [ -z "$OPAMP_SERVER_URL" ]; then # both configure the same receiver's auth.authenticator, so enabling both # would just make whichever config file is loaded last win. if [ -n "$OIDC_ISSUER_URL" ]; then + # oidcauthextension requires a non-empty audience unless ignore_audience + # is set (which we don't expose here, since silently skipping the + # audience check would weaken the auth rather than just fail loudly). + # Fail fast with a clear message instead of letting the collector crash + # on the extension's own less obvious "no audience provided" error. + if [ -z "$OIDC_AUDIENCE" ]; then + echo "ERROR: OIDC_ISSUER_URL is set but OIDC_AUDIENCE is not. Both are required to enable OIDC authentication." >&2 + exit 1 + fi echo "OIDC_ISSUER_URL is configured, enabling OIDC-based bearer token authentication" COLLECTOR_ARGS="$COLLECTOR_ARGS --config /etc/otelcol-contrib/standalone-oidc-config.yaml" elif [ -n "$OTLP_AUTH_TOKEN" ]; then