feat(tracing): add bearer token authentication for OTLP exporters
Add BearerTokenFunc to support dynamic bearer token authentication for OTLP exporters. Tokens are injected per-request via gRPC PerRPCCredentials and HTTP custom RoundTripper. - Add BearerTokenFunc type and Config field in tracerconfig - Implement bearerCredentials (gRPC) and bearerRoundTripper (HTTP) - Wire bearer auth into all exporter creation functions - Add getHTTPClient helper for DRY HTTP client configuration - Upgrade OpenTelemetry SDK to v1.39.0 for WithHTTPClient support
This commit is contained in:
52
internal/tracerconfig/auth.go
Normal file
52
internal/tracerconfig/auth.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package tracerconfig
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// bearerCredentials implements gRPC PerRPCCredentials for bearer token authentication.
|
||||
// It is safe for concurrent use as required by the gRPC PerRPCCredentials interface.
|
||||
type bearerCredentials struct {
|
||||
tokenFunc BearerTokenFunc
|
||||
}
|
||||
|
||||
// GetRequestMetadata returns authorization metadata for each RPC call.
|
||||
// It calls the token function to retrieve the current token.
|
||||
func (c *bearerCredentials) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
|
||||
token, err := c.tokenFunc(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if token == "" {
|
||||
return nil, nil // Omit header for empty token
|
||||
}
|
||||
return map[string]string{"authorization": "Bearer " + token}, nil
|
||||
}
|
||||
|
||||
// RequireTransportSecurity returns true because bearer tokens require TLS.
|
||||
func (c *bearerCredentials) RequireTransportSecurity() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// bearerRoundTripper wraps an http.RoundTripper to add bearer token authentication.
|
||||
// It is safe for concurrent use as required by the http.RoundTripper interface.
|
||||
type bearerRoundTripper struct {
|
||||
base http.RoundTripper
|
||||
tokenFunc BearerTokenFunc
|
||||
}
|
||||
|
||||
// RoundTrip adds the Authorization header with the bearer token.
|
||||
func (rt *bearerRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
token, err := rt.tokenFunc(req.Context())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if token == "" {
|
||||
return rt.base.RoundTrip(req)
|
||||
}
|
||||
// Clone only when adding a header to preserve the original request
|
||||
req = req.Clone(req.Context())
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
return rt.base.RoundTrip(req)
|
||||
}
|
||||
Reference in New Issue
Block a user