types: omit secret fields from JSON marshalling
Add json:"-" to PostgresConfig.Pass, OIDCConfig.ClientSecret, and CLIConfig.APIKey so they are excluded from json.Marshal output (e.g. the /debug/config endpoint).
This commit is contained in:
parent
0641771128
commit
a3c4ad2ca3
@ -148,7 +148,7 @@ type PostgresConfig struct {
|
|||||||
Port int
|
Port int
|
||||||
Name string
|
Name string
|
||||||
User string
|
User string
|
||||||
Pass string
|
Pass string `json:"-"` // never serialise the database password
|
||||||
Ssl string
|
Ssl string
|
||||||
MaxOpenConnections int
|
MaxOpenConnections int
|
||||||
MaxIdleConnections int
|
MaxIdleConnections int
|
||||||
@ -198,7 +198,7 @@ type OIDCConfig struct {
|
|||||||
OnlyStartIfOIDCIsAvailable bool
|
OnlyStartIfOIDCIsAvailable bool
|
||||||
Issuer string
|
Issuer string
|
||||||
ClientID string
|
ClientID string
|
||||||
ClientSecret string
|
ClientSecret string `json:"-"` // never serialise the OIDC client secret
|
||||||
Scope []string
|
Scope []string
|
||||||
ExtraParams map[string]string
|
ExtraParams map[string]string
|
||||||
AllowedDomains []string
|
AllowedDomains []string
|
||||||
@ -237,7 +237,7 @@ type TaildropConfig struct {
|
|||||||
|
|
||||||
type CLIConfig struct {
|
type CLIConfig struct {
|
||||||
Address string
|
Address string
|
||||||
APIKey string
|
APIKey string `json:"-"` // never serialise the headscale admin API key
|
||||||
Timeout time.Duration
|
Timeout time.Duration
|
||||||
Insecure bool
|
Insecure bool
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -472,3 +473,40 @@ func TestSafeServerURL(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestConfigJSONOmitsSecrets verifies that marshalling a Config to JSON
|
||||||
|
// (as /debug/config does via state.DebugConfig) does not leak the
|
||||||
|
// Postgres password, the OIDC client secret, or the headscale admin
|
||||||
|
// API key. Operators who widen metrics_listen_addr to 0.0.0.0 should
|
||||||
|
// not be able to read these back via debug endpoints reachable over
|
||||||
|
// CGNAT/loopback.
|
||||||
|
func TestConfigJSONOmitsSecrets(t *testing.T) {
|
||||||
|
const (
|
||||||
|
secretPostgresPass = "p0stgres-secret-marker"
|
||||||
|
secretClientSecret = "oidc-client-secret-marker" //nolint:gosec // test marker, not a real credential
|
||||||
|
secretAPIKey = "headscale-cli-api-key-marker" //nolint:gosec // test marker, not a real credential
|
||||||
|
)
|
||||||
|
|
||||||
|
cfg := &Config{
|
||||||
|
Database: DatabaseConfig{
|
||||||
|
Postgres: PostgresConfig{
|
||||||
|
Pass: secretPostgresPass,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
OIDC: OIDCConfig{
|
||||||
|
ClientSecret: secretClientSecret,
|
||||||
|
},
|
||||||
|
CLI: CLIConfig{
|
||||||
|
APIKey: secretAPIKey,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
out, err := json.Marshal(cfg)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
body := string(out)
|
||||||
|
for _, secret := range []string{secretPostgresPass, secretClientSecret, secretAPIKey} {
|
||||||
|
assert.NotContains(t, body, secret,
|
||||||
|
"marshalled Config must not contain secret %q", secret)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user