Redact all secrets from config viewing APIs (#17380)

This change adds a `Secret` property to `HelpKV` to identify secrets
like passwords and auth tokens that should not be revealed by the server
in its configuration fetching APIs. Configuration reporting APIs now do
not return secrets.
This commit is contained in:
Aditya Manthramurthy
2023-06-23 07:45:27 -07:00
committed by GitHub
parent d315d012a4
commit f3248a4b37
15 changed files with 119 additions and 44 deletions

View File

@@ -221,13 +221,12 @@ const (
)
// DefaultKVS - default kvs for all sub-systems
var DefaultKVS map[string]KVS
var DefaultKVS = map[string]KVS{}
// RegisterDefaultKVS - this function saves input kvsMap
// globally, this should be called only once preferably
// during `init()`.
func RegisterDefaultKVS(kvsMap map[string]KVS) {
DefaultKVS = map[string]KVS{}
for subSys, kvs := range kvsMap {
DefaultKVS[subSys] = kvs
}
@@ -236,14 +235,13 @@ func RegisterDefaultKVS(kvsMap map[string]KVS) {
// HelpSubSysMap - help for all individual KVS for each sub-systems
// also carries a special empty sub-system which dumps
// help for each sub-system key.
var HelpSubSysMap map[string]HelpKVS
var HelpSubSysMap = map[string]HelpKVS{}
// RegisterHelpSubSys - this function saves
// input help KVS for each sub-system globally,
// this function should be called only once
// preferably in during `init()`.
func RegisterHelpSubSys(helpKVSMap map[string]HelpKVS) {
HelpSubSysMap = map[string]HelpKVS{}
for subSys, hkvs := range helpKVSMap {
HelpSubSysMap[subSys] = hkvs
}
@@ -251,12 +249,11 @@ func RegisterHelpSubSys(helpKVSMap map[string]HelpKVS) {
// HelpDeprecatedSubSysMap - help for all deprecated sub-systems, that may be
// removed in the future.
var HelpDeprecatedSubSysMap map[string]HelpKV
var HelpDeprecatedSubSysMap = map[string]HelpKV{}
// RegisterHelpDeprecatedSubSys - saves input help KVS for deprecated
// sub-systems globally. Should be called only once at init.
func RegisterHelpDeprecatedSubSys(helpDeprecatedKVMap map[string]HelpKV) {
HelpDeprecatedSubSysMap = map[string]HelpKV{}
for k, v := range helpDeprecatedKVMap {
HelpDeprecatedSubSysMap[k] = v
}
@@ -1147,7 +1144,11 @@ const (
// This function only works for a subset of sub-systems, others return
// `ValueSourceAbsent`. FIXME: some parameters have custom environment
// variables for which support needs to be added.
func (c Config) ResolveConfigParam(subSys, target, cfgParam string) (value string, cs ValueSource) {
//
// When redactSecrets is true, the returned value is empty if the configuration
// parameter is a secret, and the returned isRedacted flag is set.
func (c Config) ResolveConfigParam(subSys, target, cfgParam string, redactSecrets bool,
) (value string, cs ValueSource, isRedacted bool) {
// cs = ValueSourceAbsent initially as it is iota by default.
// Initially only support OpenID
@@ -1174,6 +1175,18 @@ func (c Config) ResolveConfigParam(subSys, target, cfgParam string) (value strin
target = Default
}
if redactSecrets {
// If the configuration parameter is a secret, make sure to redact it when
// we return.
helpKV, _ := HelpSubSysMap[subSys].Lookup(cfgParam)
if helpKV.Secret {
defer func() {
value = ""
isRedacted = true
}()
}
}
envVar := getEnvVarName(subSys, target, cfgParam)
// Lookup Env var.
@@ -1211,8 +1224,7 @@ type KVSrc struct {
// GetResolvedConfigParams returns all applicable config parameters with their
// value sources.
func (c Config) GetResolvedConfigParams(subSys, target string) ([]KVSrc, error) {
// Initially only support OpenID
func (c Config) GetResolvedConfigParams(subSys, target string, redactSecrets bool) ([]KVSrc, error) {
if !resolvableSubsystems.Contains(subSys) {
return nil, Errorf("unsupported subsystem: %s", subSys)
}
@@ -1225,13 +1237,18 @@ func (c Config) GetResolvedConfigParams(subSys, target string) ([]KVSrc, error)
r := make([]KVSrc, 0, len(defKVS)+1)
for _, kv := range defKVS {
v, vs := c.ResolveConfigParam(subSys, target, kv.Key)
v, vs, isRedacted := c.ResolveConfigParam(subSys, target, kv.Key, redactSecrets)
// Fix `vs` when default.
if v == kv.Value {
vs = ValueSourceDef
}
if redactSecrets && isRedacted {
// Skip adding redacted secrets to the output.
continue
}
r = append(r, KVSrc{
Key: kv.Key,
Value: v,
@@ -1239,8 +1256,9 @@ func (c Config) GetResolvedConfigParams(subSys, target string) ([]KVSrc, error)
})
}
// Add the comment key as well if non-empty.
v, vs := c.ResolveConfigParam(subSys, target, Comment)
// Add the comment key as well if non-empty (and comments are never
// redacted).
v, vs, _ := c.ResolveConfigParam(subSys, target, Comment, redactSecrets)
if vs != ValueSourceDef {
r = append(r, KVSrc{
Key: Comment,
@@ -1252,12 +1270,59 @@ func (c Config) GetResolvedConfigParams(subSys, target string) ([]KVSrc, error)
return r, nil
}
func (c Config) getTargetKVS(subSys, target string) KVS {
// getTargetKVS returns configuration KVs for the given subsystem and target. It
// does not return any secrets in the configuration values when `redactSecrets`
// is set.
func (c Config) getTargetKVS(subSys, target string, redactSecrets bool) KVS {
store, ok := c[subSys]
if !ok {
return nil
}
return store[target]
// Lookup will succeed, because this function only works with valid subSys
// values.
resultKVS := make([]KV, 0, len(store[target]))
hkvs := HelpSubSysMap[subSys]
for _, kv := range store[target] {
hkv, _ := hkvs.Lookup(kv.Key)
if hkv.Secret && redactSecrets && kv.Value != "" {
// Skip returning secrets.
continue
// clonedKV := kv
// clonedKV.Value = redactedSecret
// resultKVS = append(resultKVS, clonedKV)
} else {
resultKVS = append(resultKVS, kv)
}
}
return resultKVS
}
// getTargetEnvs returns configured environment variable settings for the given
// subsystem and target.
func (c Config) getTargetEnvs(subSys, target string, defKVS KVS, redactSecrets bool) map[string]EnvPair {
hkvs := HelpSubSysMap[subSys]
envMap := make(map[string]EnvPair)
// Add all env vars that are set.
for _, kv := range defKVS {
envName := getEnvVarName(subSys, target, kv.Key)
envPair := EnvPair{
Name: envName,
Value: env.Get(envName, ""),
}
if envPair.Value != "" {
hkv, _ := hkvs.Lookup(kv.Key)
if hkv.Secret && redactSecrets {
// Skip adding any secret to the returned value.
continue
// envPair.Value = redactedSecret
}
envMap[kv.Key] = envPair
}
}
return envMap
}
// EnvPair represents an environment variable and its value.
@@ -1278,7 +1343,7 @@ type SubsysInfo struct {
// GetSubsysInfo returns `SubsysInfo`s for all targets for the subsystem, when
// target is empty. Otherwise returns `SubsysInfo` for the desired target only.
// To request the default target only, target must be set to `Default`.
func (c Config) GetSubsysInfo(subSys, target string) ([]SubsysInfo, error) {
func (c Config) GetSubsysInfo(subSys, target string, redactSecrets bool) ([]SubsysInfo, error) {
// Check if config param requested is valid.
defKVS1, ok := DefaultKVS[subSys]
if !ok {
@@ -1314,28 +1379,13 @@ func (c Config) GetSubsysInfo(subSys, target string) ([]SubsysInfo, error) {
r := make([]SubsysInfo, 0, len(targets))
for _, target := range targets {
kvs := c.getTargetKVS(subSys, target)
cs := SubsysInfo{
r = append(r, SubsysInfo{
SubSys: subSys,
Target: target,
Defaults: defKVS,
Config: kvs,
EnvMap: make(map[string]EnvPair),
}
// Add all env vars that are set.
for _, kv := range defKVS {
envName := getEnvVarName(subSys, target, kv.Key)
envPair := EnvPair{
Name: envName,
Value: env.Get(envName, ""),
}
if envPair.Value != "" {
cs.EnvMap[kv.Key] = envPair
}
}
r = append(r, cs)
Config: c.getTargetKVS(subSys, target, redactSecrets),
EnvMap: c.getTargetEnvs(subSys, target, defKVS, redactSecrets),
})
}
return r, nil