Skip to content

Commit f5d2184

Browse files
committed
feat(secrets): add new package for managing secrets
Signed-off-by: Henrique Matulis <hmatulis@google.com>
1 parent 0b2fbf3 commit f5d2184

20 files changed

+2336
-1
lines changed

config/secrets.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package config
2+
3+
import (
4+
"github.com/prometheus/common/secrets"
5+
)
6+
7+
func init() {
8+
// Intermediate step in the migration to the new secrets API.
9+
secrets.SetVisibilityPolicy(func() bool { return MarshalSecretValue })
10+
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ require (
1010
github.com/julienschmidt/httprouter v1.3.0
1111
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822
1212
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f
13+
github.com/prometheus/client_golang v1.20.4
1314
github.com/prometheus/client_model v0.6.2
1415
github.com/stretchr/testify v1.11.1
1516
go.yaml.in/yaml/v2 v2.4.3
@@ -25,7 +26,6 @@ require (
2526
github.com/davecgh/go-spew v1.1.1 // indirect
2627
github.com/jpillora/backoff v1.0.0 // indirect
2728
github.com/pmezard/go-difflib v1.0.0 // indirect
28-
github.com/prometheus/client_golang v1.20.4 // indirect
2929
github.com/prometheus/procfs v0.15.1 // indirect
3030
github.com/rogpeppe/go-internal v1.10.0 // indirect
3131
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect

secrets/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Secret Management
2+
3+
The `secrets` package provides a unified way to handle secrets within configuration files for Prometheus and its ecosystem components. It allows secrets to be specified inline, loaded from files, or fetched from other sources through a pluggable provider mechanism.
4+
5+
See the rendered [GoDoc here](https://pkg.go.dev/github.com/prometheus/common/secrets) if on GitHub.
6+
7+
## How to Use
8+
9+
Using the `secrets` package involves three main steps: defining your configuration struct, initializing the secret manager, and accessing the secret values. Refer to the [package example GoDoc](https://pkg.go.dev/github.com/prometheus/common/secrets#example-package).
10+
11+
12+
## Built-in Providers
13+
14+
The `secrets` package comes with two built-in providers: `inline` and `file`. For more details, please refer to the [GoDoc](https://pkg.go.dev/github.com/prometheus/common/secrets#pkg-variables).
15+
16+
## Custom Providers
17+
18+
You can extend the functionality by creating your own custom secret providers. For a detailed guide on creating custom providers, please refer to the [GoDoc for the `Provider` and `ProviderConfig` interfaces](https://pkg.go.dev/github.com/prometheus/common/secrets#Provider).

secrets/doc.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2025 The Prometheus Authors
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
// Package secrets provides a unified way to handle secrets within
15+
// configuration files for Prometheus and its ecosystem components. It allows
16+
// secrets to be specified inline, loaded from files, or fetched from other
17+
// sources through a pluggable provider mechanism.
18+
package secrets

secrets/example_test.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// Copyright 2025 The Prometheus Authors
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
package secrets_test
15+
16+
import (
17+
"context"
18+
"fmt"
19+
"os"
20+
21+
"github.com/prometheus/client_golang/prometheus"
22+
"go.yaml.in/yaml/v2"
23+
24+
"github.com/prometheus/common/secrets"
25+
)
26+
27+
func Example() {
28+
// A Prometheus registry is needed to register the secret manager's metrics.
29+
promRegisterer := prometheus.NewRegistry()
30+
31+
// Create a temporary file to simulate a file-based secret (e.g., Kubernetes mount).
32+
passwordFile, err := os.CreateTemp("", "password_secret")
33+
if err != nil {
34+
panic(err)
35+
}
36+
defer os.Remove(passwordFile.Name())
37+
38+
if _, err := passwordFile.WriteString("my_super_secret_password"); err != nil {
39+
passwordFile.Close()
40+
panic(err)
41+
}
42+
passwordFile.Close()
43+
44+
// In your configuration struct, use the `secrets.Field` type for any fields
45+
// that should contain secrets.
46+
type MyConfig struct {
47+
APIKey secrets.Field `yaml:"api_key"`
48+
Password secrets.Field `yaml:"password"`
49+
}
50+
51+
// Users can then provide secrets in their YAML configuration file.
52+
// We inject the temporary file path created above.
53+
configData := []byte(fmt.Sprintf(`
54+
api_key: "my_super_secret_api_key"
55+
password:
56+
file:
57+
path: %s
58+
`, passwordFile.Name()))
59+
60+
var cfg MyConfig
61+
if err := yaml.Unmarshal(configData, &cfg); err != nil {
62+
panic(fmt.Errorf("error unmarshaling config: %w", err))
63+
}
64+
65+
// Create a secret manager. This discovers and manages all Fields in cfg.
66+
// The manager will handle refreshing secrets in the background.
67+
manager, err := secrets.NewManager(context.Background(), promRegisterer, secrets.Providers, &cfg)
68+
if err != nil {
69+
panic(fmt.Errorf("error creating secret manager: %w", err))
70+
}
71+
72+
// Start the manager's background refresh loop.
73+
manager.Start(context.Background())
74+
defer manager.Stop()
75+
76+
// Access the secret values.
77+
apiKey := cfg.APIKey.Value()
78+
password := cfg.Password.Value()
79+
80+
fmt.Printf("API Key: %s\n", apiKey)
81+
fmt.Printf("Password: %s\n", password)
82+
83+
// Output:
84+
// API Key: my_super_secret_api_key
85+
// Password: my_super_secret_password
86+
}

0 commit comments

Comments
 (0)