Skip to content

Commit ab286db

Browse files
committed
[receiver/prometheusreceiver] fix prom receiver config reload
1 parent 65ad55c commit ab286db

File tree

2 files changed

+87
-0
lines changed

2 files changed

+87
-0
lines changed

receiver/prometheusreceiver/config.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ func (cfg *PromConfig) ContainsScrapeConfigs() bool {
7272
}
7373

7474
func (cfg *PromConfig) Reload() error {
75+
if cfg.ContainsScrapeConfigs() {
76+
return nil
77+
}
78+
79+
// only reload if there are no scrape configs, implying that there is a target_allocator.
80+
// reloading existing scrape configs corrupts authentication configurations
7581
return reloadPromConfig(cfg, cfg)
7682
}
7783

receiver/prometheusreceiver/config_test.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@ package prometheusreceiver
55

66
import (
77
"context"
8+
"log/slog"
9+
"os"
810
"path/filepath"
911
"strings"
1012
"testing"
1113
"time"
1214

1315
promConfig "github.com/prometheus/common/config"
1416
promModel "github.com/prometheus/common/model"
17+
promconfig "github.com/prometheus/prometheus/config"
1518
"github.com/stretchr/testify/assert"
1619
"github.com/stretchr/testify/require"
1720
"go.opentelemetry.io/collector/component"
@@ -399,3 +402,81 @@ func TestLoadPrometheusAPIServerExtensionConfig(t *testing.T) {
399402
require.NoError(t, sub.Unmarshal(cfg))
400403
require.Error(t, xconfmap.Validate(cfg))
401404
}
405+
406+
func TestReloadPromConfigSecretHandling(t *testing.T) {
407+
// This test verifies that the Reload() method preserves secrets instead of
408+
// corrupting them to "<secret>" placeholders. This is critical for authentication
409+
// to work properly when using configurations with basic auth or bearer tokens.
410+
411+
tests := []struct {
412+
name string
413+
configYAML string
414+
checkFn func(t *testing.T, dst *PromConfig)
415+
}{
416+
{
417+
name: "basic auth password preservation",
418+
configYAML: `
419+
scrape_configs:
420+
- job_name: "test-basic-auth"
421+
basic_auth:
422+
username: "testuser"
423+
password: "mysecretpassword"
424+
static_configs:
425+
- targets: ["localhost:8080"]
426+
`,
427+
checkFn: func(t *testing.T, dst *PromConfig) {
428+
require.Len(t, dst.ScrapeConfigs, 1)
429+
scrapeConfig := dst.ScrapeConfigs[0]
430+
assert.Equal(t, "test-basic-auth", scrapeConfig.JobName)
431+
432+
// The critical check: ensure the password is not "<secret>"
433+
require.NotNil(t, scrapeConfig.HTTPClientConfig.BasicAuth, "basic auth should be configured")
434+
password := string(scrapeConfig.HTTPClientConfig.BasicAuth.Password)
435+
assert.NotEqual(t, "<secret>", password, "password should not be marshaled as '<secret>'")
436+
assert.Equal(t, "mysecretpassword", password, "password should preserve original value")
437+
assert.Equal(t, "testuser", scrapeConfig.HTTPClientConfig.BasicAuth.Username)
438+
},
439+
},
440+
{
441+
name: "bearer token preservation",
442+
configYAML: `
443+
scrape_configs:
444+
- job_name: "test-bearer-token"
445+
authorization:
446+
type: "Bearer"
447+
credentials: "mySecretBearerToken123"
448+
static_configs:
449+
- targets: ["localhost:9090"]
450+
`,
451+
checkFn: func(t *testing.T, dst *PromConfig) {
452+
require.Len(t, dst.ScrapeConfigs, 1)
453+
scrapeConfig := dst.ScrapeConfigs[0]
454+
assert.Equal(t, "test-bearer-token", scrapeConfig.JobName)
455+
456+
// Check that bearer token is preserved
457+
require.NotNil(t, scrapeConfig.HTTPClientConfig.Authorization, "authorization should be configured")
458+
credentials := string(scrapeConfig.HTTPClientConfig.Authorization.Credentials)
459+
assert.NotEqual(t, "<secret>", credentials, "credentials should not be marshaled as '<secret>'")
460+
assert.Equal(t, "mySecretBearerToken123", credentials, "credentials should preserve original value")
461+
assert.Equal(t, "Bearer", scrapeConfig.HTTPClientConfig.Authorization.Type)
462+
},
463+
},
464+
}
465+
466+
for _, tt := range tests {
467+
t.Run(tt.name, func(t *testing.T) {
468+
// Load the config using promconfig.Load to simulate real usage
469+
initialCfg, err := promconfig.Load(tt.configYAML, slog.New(slog.NewTextHandler(os.Stderr, nil)))
470+
require.NoError(t, err)
471+
472+
// Convert to PromConfig and test the Reload method
473+
// The Reload method should preserve secrets and not corrupt them
474+
dst := (*PromConfig)(initialCfg)
475+
err = dst.Reload()
476+
require.NoError(t, err)
477+
478+
// Verify that secrets are preserved
479+
tt.checkFn(t, dst)
480+
})
481+
}
482+
}

0 commit comments

Comments
 (0)