Skip to content

Commit 1bc7111

Browse files
committed
feat: add first-class Basic Auth support to OTEL config
1 parent ae4bdb0 commit 1bc7111

File tree

4 files changed

+70
-1
lines changed

4 files changed

+70
-1
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ cfg := ion.Config{
9292
Enabled: true,
9393
Endpoint: "otel-collector:4317", // gRPC by default
9494
Protocol: "grpc",
95+
Username: "admin", // Optional Basic Auth
96+
Password: "supersecret", // Optional Basic Auth
97+
Headers: map[string]string{ // Optional custom headers
98+
"X-Custom-Token": "value",
99+
},
95100
BatchSize: 1000,
96101
Attributes: map[string]string{
97102
"env": "production",

config.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,12 @@ type OTELConfig struct {
9595
// Default: false
9696
Insecure bool `yaml:"insecure" json:"insecure"`
9797

98+
// Username for Basic Authentication (optional).
99+
Username string `yaml:"username" json:"username" env:"OTEL_USERNAME"`
100+
101+
// Password for Basic Authentication (optional).
102+
Password string `yaml:"password" json:"password" env:"OTEL_PASSWORD"`
103+
98104
// Headers are additional headers to send (e.g., auth tokens).
99105
Headers map[string]string `yaml:"headers" json:"headers"`
100106

ion_auth_analysis.md.resolved

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Ion Library OTel Authentication Analysis
2+
3+
## Current Status
4+
The [ion](file:///Users/naman/JM/repos/JMDT-Sequencer-Orchestrator/internal/config/config.go#154-164) library's `OTELConfig` struct currently lacks explicit fields for authentication credentials (e.g., `Username` and `Password`). However, it exposes a `Headers` field (`map[string]string`) which is passed to the underlying OpenTelemetry exporter.
5+
6+
## Authentication Implementation
7+
To support Basic Authentication (commonly used with OTel collectors/receivers):
8+
1. **Manual Header Construction**: Users must manually construct the `Authorization` header.
9+
- Format: `Basic <base64(username:password)>`
10+
2. **Configuration**: This header key-value pair is then added to `ion.OTELConfig.Headers`.
11+
12+
## Implementation in Orchestrator
13+
We have successfully implemented this pattern in [cmd/orchestrator/main.go](file:///Users/naman/JM/repos/JMDT-Sequencer-Orchestrator/cmd/orchestrator/main.go):
14+
```go
15+
// Construct Basic Auth header manually
16+
if cfg.OTelUsername != "" && cfg.OTelPassword != "" {
17+
auth := fmt.Sprintf("%s:%s", cfg.OTelUsername, cfg.OTelPassword)
18+
encodedAuth := base64.StdEncoding.EncodeToString([]byte(auth))
19+
otelHeaders["Authorization"] = "Basic " + encodedAuth
20+
}
21+
```
22+
23+
## Recommendations for Ion Library Improvements
24+
To improve Developer Experience (DX) and reduce boilerplate code for consumers:
25+
26+
1. **Add First-Class Auth Fields**:
27+
Extend `ion.OTELConfig` to include `Username` and `Password` fields.
28+
```go
29+
type OTELConfig struct {
30+
// ... existing fields
31+
Username string
32+
Password string
33+
}
34+
```
35+
36+
2. **Internal Handling**:
37+
Update `ion.NewWithOTEL` (or internal exporter setup) to automatically detect these fields.
38+
- If `Username` and `Password` are set, the library should generate the `Authorization` header internally.
39+
- This abstract away the base64 encoding requirement from the user.
40+
41+
3. **Documentation**:
42+
Explicitly document that `Headers` can be used for custom auth tokens (e.g., Bearer tokens) if strict Basic Auth fields are not added.

zap.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package ion
22

33
import (
44
"context"
5+
"encoding/base64"
6+
"fmt"
57
"os"
68
"strings"
79
"sync"
@@ -29,14 +31,28 @@ func New(cfg Config) Logger {
2931
// NewWithOTEL creates a logger with OTEL export enabled.
3032
// This wires Zap logs to the OpenTelemetry log pipeline.
3133
func NewWithOTEL(cfg Config) (Logger, error) {
34+
// 1. Handle Basic Auth Wrapper
35+
// If Username/Password are provided, inject the Authorization header.
36+
// This improves DX by removing the need for users to base64 encode manually.
37+
headers := cfg.OTEL.Headers
38+
if headers == nil {
39+
headers = make(map[string]string)
40+
}
41+
42+
if cfg.OTEL.Username != "" && cfg.OTEL.Password != "" {
43+
auth := fmt.Sprintf("%s:%s", cfg.OTEL.Username, cfg.OTEL.Password)
44+
encodedAuth := base64.StdEncoding.EncodeToString([]byte(auth))
45+
headers["Authorization"] = "Basic " + encodedAuth
46+
}
47+
3248
// Map config to internal OTEL config
3349
otelCfg := otel.Config{
3450
Enabled: cfg.OTEL.Enabled,
3551
Endpoint: cfg.OTEL.Endpoint,
3652
Protocol: cfg.OTEL.Protocol,
3753
Insecure: cfg.OTEL.Insecure,
3854
Timeout: cfg.OTEL.Timeout,
39-
Headers: cfg.OTEL.Headers,
55+
Headers: headers,
4056
Attributes: cfg.OTEL.Attributes,
4157
BatchSize: cfg.OTEL.BatchSize,
4258
ExportInterval: cfg.OTEL.ExportInterval,

0 commit comments

Comments
 (0)