Skip to content

Commit 486a463

Browse files
authored
Merge pull request prometheus#4158 from wallee94/support-disable-marshal-secret-value
Update config to allow showing secret values when marshaled
2 parents ced7949 + 4f10742 commit 486a463

File tree

2 files changed

+90
-2
lines changed

2 files changed

+90
-2
lines changed

config/config.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ const secretToken = "<secret>"
3939

4040
var secretTokenJSON string
4141

42+
// MarshalSecretValue if set to true will expose Secret type
43+
// through the marshal interfaces. Useful for outside projects
44+
// that load and marshal the Alertmanager config.
45+
var MarshalSecretValue bool = commoncfg.MarshalSecretValue
46+
4247
func init() {
4348
b, err := json.Marshal(secretToken)
4449
if err != nil {
@@ -52,6 +57,9 @@ type Secret string
5257

5358
// MarshalYAML implements the yaml.Marshaler interface for Secret.
5459
func (s Secret) MarshalYAML() (interface{}, error) {
60+
if MarshalSecretValue {
61+
return string(s), nil
62+
}
5563
if s != "" {
5664
return secretToken, nil
5765
}
@@ -66,6 +74,12 @@ func (s *Secret) UnmarshalYAML(unmarshal func(interface{}) error) error {
6674

6775
// MarshalJSON implements the json.Marshaler interface for Secret.
6876
func (s Secret) MarshalJSON() ([]byte, error) {
77+
if MarshalSecretValue {
78+
return json.Marshal(string(s))
79+
}
80+
if len(s) == 0 {
81+
return json.Marshal("")
82+
}
6983
return json.Marshal(secretToken)
7084
}
7185

@@ -130,6 +144,9 @@ type SecretURL URL
130144
// MarshalYAML implements the yaml.Marshaler interface for SecretURL.
131145
func (s SecretURL) MarshalYAML() (interface{}, error) {
132146
if s.URL != nil {
147+
if MarshalSecretValue {
148+
return s.URL.String(), nil
149+
}
133150
return secretToken, nil
134151
}
135152
return nil, nil
@@ -153,6 +170,12 @@ func (s *SecretURL) UnmarshalYAML(unmarshal func(interface{}) error) error {
153170

154171
// MarshalJSON implements the json.Marshaler interface for SecretURL.
155172
func (s SecretURL) MarshalJSON() ([]byte, error) {
173+
if s.URL == nil {
174+
return json.Marshal("")
175+
}
176+
if MarshalSecretValue {
177+
return json.Marshal(s.URL.String())
178+
}
156179
return json.Marshal(secretToken)
157180
}
158181

@@ -167,6 +190,9 @@ func (s *SecretURL) UnmarshalJSON(data []byte) error {
167190
}
168191
// Redact the secret URL in case of errors
169192
if err := json.Unmarshal(data, (*URL)(s)); err != nil {
193+
if MarshalSecretValue {
194+
return err
195+
}
170196
return errors.New(strings.ReplaceAll(err.Error(), string(data), "[REDACTED]"))
171197
}
172198

config/config_test.go

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,22 @@ func TestHideConfigSecrets(t *testing.T) {
525525
}
526526
}
527527

528+
func TestShowMarshalSecretValues(t *testing.T) {
529+
MarshalSecretValue = true
530+
defer func() { MarshalSecretValue = false }()
531+
532+
c, err := LoadFile("testdata/conf.good.yml")
533+
if err != nil {
534+
t.Fatalf("Error parsing %s: %s", "testdata/conf.good.yml", err)
535+
}
536+
537+
// String method must reveal authentication credentials.
538+
s := c.String()
539+
if strings.Count(s, "<secret>") > 0 || !strings.Contains(s, "mysecret") {
540+
t.Fatal("config's String method must reveal authentication credentials when MarshalSecretValue = true.")
541+
}
542+
}
543+
528544
func TestJSONMarshal(t *testing.T) {
529545
c, err := LoadFile("testdata/conf.good.yml")
530546
if err != nil {
@@ -537,7 +553,7 @@ func TestJSONMarshal(t *testing.T) {
537553
}
538554
}
539555

540-
func TestJSONMarshalSecret(t *testing.T) {
556+
func TestJSONMarshalHideSecret(t *testing.T) {
541557
test := struct {
542558
S Secret
543559
}{
@@ -554,7 +570,24 @@ func TestJSONMarshalSecret(t *testing.T) {
554570
require.Equal(t, "{\"S\":\"\\u003csecret\\u003e\"}", string(c), "Secret not properly elided.")
555571
}
556572

557-
func TestMarshalSecretURL(t *testing.T) {
573+
func TestJSONMarshalShowSecret(t *testing.T) {
574+
MarshalSecretValue = true
575+
defer func() { MarshalSecretValue = false }()
576+
577+
test := struct {
578+
S Secret
579+
}{
580+
S: Secret("test"),
581+
}
582+
583+
c, err := json.Marshal(test)
584+
if err != nil {
585+
t.Fatal(err)
586+
}
587+
require.Equal(t, "{\"S\":\"test\"}", string(c), "config's String method must reveal authentication credentials when MarshalSecretValue = true.")
588+
}
589+
590+
func TestJSONMarshalHideSecretURL(t *testing.T) {
558591
urlp, err := url.Parse("http://example.com/")
559592
if err != nil {
560593
t.Fatal(err)
@@ -588,6 +621,23 @@ func TestMarshalSecretURL(t *testing.T) {
588621
}
589622
}
590623

624+
func TestJSONMarshalShowSecretURL(t *testing.T) {
625+
MarshalSecretValue = true
626+
defer func() { MarshalSecretValue = false }()
627+
628+
urlp, err := url.Parse("http://example.com/")
629+
if err != nil {
630+
t.Fatal(err)
631+
}
632+
u := &SecretURL{urlp}
633+
634+
c, err := json.Marshal(u)
635+
if err != nil {
636+
t.Fatal(err)
637+
}
638+
require.Equal(t, "\"http://example.com/\"", string(c), "config's String method must reveal authentication credentials when MarshalSecretValue = true.")
639+
}
640+
591641
func TestUnmarshalSecretURL(t *testing.T) {
592642
b := []byte(`"http://example.com/se cret"`)
593643
var u SecretURL
@@ -615,6 +665,18 @@ func TestHideSecretURL(t *testing.T) {
615665
require.NotContains(t, err.Error(), "wrongurl")
616666
}
617667

668+
func TestShowMarshalSecretURL(t *testing.T) {
669+
MarshalSecretValue = true
670+
defer func() { MarshalSecretValue = false }()
671+
672+
b := []byte(`"://wrongurl/"`)
673+
var u SecretURL
674+
675+
err := json.Unmarshal(b, &u)
676+
require.Error(t, err)
677+
require.Contains(t, err.Error(), "wrongurl")
678+
}
679+
618680
func TestMarshalURL(t *testing.T) {
619681
for name, tc := range map[string]struct {
620682
input *URL

0 commit comments

Comments
 (0)