Skip to content

Conversation

danish9039
Copy link
Contributor

@danish9039 danish9039 commented Jul 21, 2025

Which problem is this PR solving?

part of

Description of the changes

It is part of the planned work to add support for API authentication, as discussed in #7230 (comment)

  • Refactors Jaeger's authentication system from hardcoded bearer token implementation to a generic, extensible multi-authentication framework with full backward compatibility.
  • Adds Dynamic Reloading Functionality For Authentication Tokens from Files

Key Changes

Generic Authentication Framework

  • Before: Hardcoded StaticToken and OverrideFromCtx fields in RoundTripper
  • After: Generic Config struct supporting multiple authentication schemes
  • Benefit: Easy to add new auth methods ( for adding API keys )

Token File Loading

  • New: TokenProvider with interval-based caching and graceful error handling
  • Features: Thread-safe file reading, configurable reload intervals, fallback to cached tokens

Context-Based Token Override

  • Context tokens take precedence over file tokens when both are configured
  • Per-authentication-method context extraction

Files Changes

New

  • internal/auth/tokenloader.go - Cached token file loading
  • internal/auth/tokenloader_test.go - Token loader tests

Refactored

  • internal/auth/transport.go - Generic multi-auth transport
  • internal/auth/transport_test.go - Transport tests (12 scenarios)
  • internal/storage/elasticsearch/config/auth_helper.go - Auth config helper
  • internal/storage/metricstore/prometheus/reader.go - Prometheus integration

How was this change tested?

Checklist

Copy link

codecov bot commented Jul 21, 2025

Codecov Report

Attention: Patch coverage is 97.69231% with 3 lines in your changes missing coverage. Please review.

Project coverage is 96.44%. Comparing base (37bc7e8) to head (bf69525).

Files with missing lines Patch % Lines
internal/storage/v1/elasticsearch/options.go 70.00% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7360      +/-   ##
==========================================
- Coverage   96.47%   96.44%   -0.04%     
==========================================
  Files         374      376       +2     
  Lines       22865    22957      +92     
==========================================
+ Hits        22060    22140      +80     
- Misses        609      618       +9     
- Partials      196      199       +3     
Flag Coverage Δ
badger_v1 9.14% <0.00%> (-0.08%) ⬇️
badger_v2 1.72% <0.00%> (-0.02%) ⬇️
cassandra-4.x-v1-manual 11.86% <0.00%> (-0.10%) ⬇️
cassandra-4.x-v2-auto 1.71% <0.00%> (-0.02%) ⬇️
cassandra-4.x-v2-manual 1.71% <0.00%> (-0.02%) ⬇️
cassandra-5.x-v1-manual 11.86% <0.00%> (-0.10%) ⬇️
cassandra-5.x-v2-auto 1.71% <0.00%> (-0.02%) ⬇️
cassandra-5.x-v2-manual 1.71% <0.00%> (-0.02%) ⬇️
elasticsearch-6.x-v1 ?
elasticsearch-7.x-v1 16.74% <2.70%> (-0.12%) ⬇️
elasticsearch-8.x-v1 16.88% <2.70%> (-0.12%) ⬇️
elasticsearch-8.x-v2 ?
grpc_v1 10.38% <0.00%> (-0.08%) ⬇️
grpc_v2 1.72% <0.00%> (-0.02%) ⬇️
kafka-3.x-v1 9.30% <0.00%> (-0.08%) ⬇️
kafka-3.x-v2 1.72% <0.00%> (-0.02%) ⬇️
memory_v2 1.72% <0.00%> (-0.02%) ⬇️
opensearch-1.x-v1 16.78% <2.70%> (-0.12%) ⬇️
opensearch-2.x-v1 16.78% <2.70%> (-0.12%) ⬇️
opensearch-2.x-v2 1.72% <0.00%> (-0.02%) ⬇️
opensearch-3.x-v2 1.72% <0.00%> (-0.02%) ⬇️
query 1.72% <0.00%> (-0.02%) ⬇️
tailsampling-processor 0.47% <0.00%> (-0.01%) ⬇️
unittests 95.42% <97.69%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

require.NoError(t, err)
assert.Equal(t, token, t1, "expected %q, got %q")

// Change the file, but within cache interval
Copy link
Member

Choose a reason for hiding this comment

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

there is no way to guarantee that in CI environment this will be within the cache interval. You need to test with a mock time.Now function and advance the time manually.

@@ -219,6 +219,8 @@ type BearerTokenAuthentication struct {
FilePath string `mapstructure:"file_path"`
// AllowTokenFromContext, if set to true, enables reading bearer token from the context.
AllowFromContext bool `mapstructure:"from_context"`
// ReloadInterval contains the interval at which the bearer token is reloaded.
ReloadInterval configoptional.Optional[time.Duration] `mapstructure:"reload_interval"`
Copy link
Member

Choose a reason for hiding this comment

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

what is the meaning of this being None? No reload? Why can't we use 0 for that?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@yurishkuro If its none , it default to 10 seconds . Setting Reload interval 0 mean no caching , file is checked for token on every request

Copy link
Member

Choose a reason for hiding this comment

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

Defaulting is a different process - after defaulting applies this won't be None, so not what I asked. This field treats 0 as "don't reload", which is semantically the same as None. There's no need for Optional here.

@@ -219,6 +219,8 @@ type BearerTokenAuthentication struct {
FilePath string `mapstructure:"file_path"`
// AllowTokenFromContext, if set to true, enables reading bearer token from the context.
AllowFromContext bool `mapstructure:"from_context"`
// ReloadInterval contains the interval at which the bearer token is reloaded.
ReloadInterval configoptional.Optional[time.Duration] `mapstructure:"reload_interval"`
Copy link
Member

Choose a reason for hiding this comment

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

Defaulting is a different process - after defaulting applies this won't be None, so not what I asked. This field treats 0 as "don't reload", which is semantically the same as None. There's no need for Optional here.

if err != nil {
return nil, err
}
if len(authMethods) > 0 {
Copy link
Member

Choose a reason for hiding this comment

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

how is basic auth handled?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

how is basic auth handled?

@yurishkuro basic authentication is currently being handled at the Elasticsearch client level using client options. You can see it here:

options = append(options, elastic.SetBasicAuth(username, password))

using the olivere/elastic client, which has built-in support for basic auth through the SetBasicAuth() method.

I’m wondering if it might make sense to move the basic auth logic to the HTTP layer as well. That way, if we ever decide to switch away from olivere/elastic, we won’t have to rewrite the auth logic it would already be handled at the transport layer. am i correct ?

Copy link
Member

Choose a reason for hiding this comment

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

I think it does make sense to move it here, doesn't look like it will make much difference and we will have everything in on place. Separate PR please.

…Multi-Auth Framework + Dynamic Token Reloading

Signed-off-by: danish9039 <danishsiddiqui040@gmail.com>
@danish9039 danish9039 force-pushed the authrefactor+dynamic-reloading branch from 619e4a6 to c8deb4f Compare July 23, 2025 19:43
danish9039 and others added 2 commits July 24, 2025 01:13
Signed-off-by: danish9039 <danishsiddiqui040@gmail.com>
@danish9039 danish9039 changed the title Refactor Authentication System: From Bearer-Token-Specific to Generi Multi-Auth Framework + Dynamic Token Reloading Refactor Authentication System: From Bearer-Token-Specific to Generic Multi-Auth Framework + Dynamic Token Reloading Jul 23, 2025
@yurishkuro yurishkuro added changelog:refactoring Internal code refactoring without functional changes changelog:bugfix-or-minor-feature and removed changelog:refactoring Internal code refactoring without functional changes labels Jul 23, 2025
@yurishkuro yurishkuro changed the title Refactor Authentication System: From Bearer-Token-Specific to Generic Multi-Auth Framework + Dynamic Token Reloading Add bearer token reloading and reuse in multiple storage backends Jul 23, 2025
@yurishkuro yurishkuro added this pull request to the merge queue Jul 23, 2025
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to no response for status checks Jul 23, 2025
@yurishkuro yurishkuro merged commit b407a8d into jaegertracing:main Jul 23, 2025
64 of 65 checks passed
github-merge-queue bot pushed a commit that referenced this pull request Jul 29, 2025
<!--
!! Please DELETE this comment before posting.
We appreciate your contribution to the Jaeger project! 👋🎉
-->

## Which problem is this PR solving?
part of 
- #7225

## Description of the changes
- Refactors Elasticsearch basic authentication from client-level
initialization to HTTP transport layer, enabling hot password reloading
and consistent authentication patterns.
#7360 (comment)

- It is part of the planned work to add support for API authentication,
as discussed in
#7230 (comment)
### Chnages
- Moved basic auth from` elastic.SetBasicAuth()` to HTTP transport layer

- Pre-encodes credentials as base64 in `TokenFn `for performance

- Reuses existing` TokenProvider `infrastructure for file-based password
reloading

- Added `ReloadInterval` field to `BasicAuthentication` struct

- New CLI flag: ` --es.password-reload-interval ` (default: 10s)


## How was this change tested?
- 

## Checklist
- [ ] I have read
https://github.com/jaegertracing/jaeger/blob/master/CONTRIBUTING_GUIDELINES.md
- [ ] I have signed all commits
- [ ] I have added unit tests for the new functionality
- [ ] I have run lint and test steps successfully
  - for `jaeger`: `make lint test`
  - for `jaeger-ui`: `npm run lint` and `npm run test`

---------

Signed-off-by: danish9039 <danishsiddiqui040@gmail.com>
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.

2 participants