proxy-pool/internal/config/redact.go

154 lines
4.8 KiB
Go

package config
import "encoding/json"
const redactedSecret = "[REDACTED]"
// Redacted returns a detached configuration view suitable for diagnostics.
func (c *Config) Redacted() Config {
if c == nil {
return Config{}
}
redacted := cloneConfig(*c)
redactAuth(&redacted.Gateway.Auth)
redactAuth(&redacted.Distribution.Auth)
redactAuth(&redacted.Admin.Auth)
for name, upstream := range redacted.Upstreams {
redactProviderAuth(&upstream.API.Auth)
upstream.ProxyAuth.Password = redact(upstream.ProxyAuth.Password)
redacted.Upstreams[name] = upstream
}
redacted.Storage.PostgresURL = redact(redacted.Storage.PostgresURL)
redacted.Storage.RedisURL = redact(redacted.Storage.RedisURL)
return redacted
}
func (c *Config) String() string {
if c == nil {
return "<nil>"
}
encoded, err := json.Marshal(c.Redacted())
if err != nil {
return `{"config":"[REDACTED]"}`
}
return string(encoded)
}
func (c *Config) GoString() string { return c.String() }
func redactAuth(auth *Auth) {
auth.Password = redact(auth.Password)
auth.Token = redact(auth.Token)
for index := range auth.Methods {
auth.Methods[index].Password = redact(auth.Methods[index].Password)
auth.Methods[index].Value = redact(auth.Methods[index].Value)
}
}
func redactProviderAuth(auth *ProviderAuth) {
auth.Password = redact(auth.Password)
auth.Token = redact(auth.Token)
auth.Value = redact(auth.Value)
}
func redact(value string) string {
if value == "" {
return ""
}
return redactedSecret
}
func cloneConfig(source Config) Config {
cloned := source
cloned.Defaults.Check.URLs = cloneStrings(source.Defaults.Check.URLs)
cloned.Gateway = cloneListener(source.Gateway)
cloned.Distribution.Listener = cloneListener(source.Distribution.Listener)
cloned.Admin = cloneListener(source.Admin)
cloned.Routing = make([]Routing, len(source.Routing))
for index, route := range source.Routing {
cloned.Routing[index] = cloneRouting(route)
}
cloned.Upstreams = make(map[string]Upstream, len(source.Upstreams))
for name, upstream := range source.Upstreams {
cloned.Upstreams[name] = cloneUpstream(upstream)
}
return cloned
}
func cloneListener(source Listener) Listener {
cloned := source
cloned.Access.AllowCIDRs = cloneStrings(source.Access.AllowCIDRs)
cloned.Access.TrustedProxies = cloneStrings(source.Access.TrustedProxies)
cloned.Auth.CIDRs = cloneStrings(source.Auth.CIDRs)
cloned.Auth.Permissions = cloneStrings(source.Auth.Permissions)
cloned.Auth.ClientPolicy = source.Auth.ClientPolicy.Clone()
cloned.Auth.Methods = append([]AuthMethod(nil), source.Auth.Methods...)
for index := range cloned.Auth.Methods {
cloned.Auth.Methods[index].CIDRs = cloneStrings(source.Auth.Methods[index].CIDRs)
cloned.Auth.Methods[index].Permissions = cloneStrings(source.Auth.Methods[index].Permissions)
cloned.Auth.Methods[index].ClientPolicy = source.Auth.Methods[index].ClientPolicy.Clone()
}
cloned.Retry.RetryMethods = cloneStrings(source.Retry.RetryMethods)
cloned.DestinationPolicy.DenyPrivateNetworks = cloneBool(source.DestinationPolicy.DenyPrivateNetworks)
cloned.DestinationPolicy.DenyLoopback = cloneBool(source.DestinationPolicy.DenyLoopback)
cloned.DestinationPolicy.DenyLinkLocal = cloneBool(source.DestinationPolicy.DenyLinkLocal)
cloned.DestinationPolicy.DenyCIDRs = cloneStrings(source.DestinationPolicy.DenyCIDRs)
cloned.DestinationPolicy.AllowedPorts = append([]uint16(nil), source.DestinationPolicy.AllowedPorts...)
return cloned
}
func cloneBool(source *bool) *bool {
if source == nil {
return nil
}
cloned := *source
return &cloned
}
func cloneRouting(source Routing) Routing {
cloned := source
cloned.Match.Methods = cloneStrings(source.Match.Methods)
cloned.Match.Headers = cloneStringMap(source.Match.Headers)
cloned.Upstreams = cloneStrings(source.Upstreams)
cloned.Strategy.Weights = cloneIntMap(source.Strategy.Weights)
cloned.Check.Targets = cloneStrings(source.Check.Targets)
return cloned
}
func cloneUpstream(source Upstream) Upstream {
cloned := source
cloned.Exposure = cloneStrings(source.Exposure)
cloned.Provider.Protocols = cloneStrings(source.Provider.Protocols)
cloned.API.Headers = cloneStringMap(source.API.Headers)
cloned.API.Query = cloneStringMap(source.API.Query)
cloned.API.Body.Value = cloneStringMap(source.API.Body.Value)
cloned.Check.URLs = cloneStrings(source.Check.URLs)
return cloned
}
func cloneStrings(source []string) []string {
return append([]string(nil), source...)
}
func cloneStringMap(source map[string]string) map[string]string {
if source == nil {
return nil
}
cloned := make(map[string]string, len(source))
for key, value := range source {
cloned[key] = value
}
return cloned
}
func cloneIntMap(source map[string]int) map[string]int {
if source == nil {
return nil
}
cloned := make(map[string]int, len(source))
for key, value := range source {
cloned[key] = value
}
return cloned
}