Redact credentials before logging

Co-authored-by: Tom Moulard <tom.moulard@traefik.io>
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
This commit is contained in:
Ali 2022-01-24 05:08:05 -05:00 committed by GitHub
parent 3bd5fc0f90
commit a4b354b33f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 1007 additions and 262 deletions

View file

@ -22,7 +22,7 @@ find "${PATH_TO_SITE}" -type f -not -path "/app/site/theme/*" \
--alt_ignore="/traefikproxy-vertical-logo-color.svg/" \
--http_status_ignore="0,500,501,503" \
--file_ignore="/404.html/" \
--url_ignore="/https://groups.google.com/a/traefik.io/forum/#!forum/security/,/localhost:/,/127.0.0.1:/,/fonts.gstatic.com/,/.minikube/,/github.com\/traefik\/traefik\/*edit*/,/github.com\/traefik\/traefik/,/doc.traefik.io/,/github\.com\/golang\/oauth2\/blob\/36a7019397c4c86cf59eeab3bc0d188bac444277\/.+/,/www.akamai.com/,/pilot.traefik.io\/profile/,/traefik.io/,/doc.traefik.io\/traefik-mesh/,/www.mkdocs.org/,/squidfunk.github.io/,/ietf.org/,/www.namesilo.com/,/www.youtube.com/,/www.linode.com/,/www.alibabacloud.com/,/www.cloudxns.net/" \
--url_ignore="/https://groups.google.com/a/traefik.io/forum/#!forum/security/,/localhost:/,/127.0.0.1:/,/fonts.gstatic.com/,/.minikube/,/github.com\/traefik\/traefik\/*edit*/,/github.com\/traefik\/traefik/,/doc.traefik.io/,/github\.com\/golang\/oauth2\/blob\/36a7019397c4c86cf59eeab3bc0d188bac444277\/.+/,/www.akamai.com/,/pilot.traefik.io\/profile/,/traefik.io/,/doc.traefik.io\/traefik-mesh/,/www.mkdocs.org/,/squidfunk.github.io/,/ietf.org/,/www.namesilo.com/,/www.youtube.com/,/www.linode.com/,/www.alibabacloud.com/,/www.cloudxns.net/,/www.vultr.com/" \
'{}' 1>/dev/null
## HTML-proofer options at https://github.com/gjtorikian/html-proofer#configuration

View file

@ -1,177 +0,0 @@
package anonymize
import (
"reflect"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
type Courgette struct {
Ji string
Ho string
}
type Tomate struct {
Ji string
Ho string
}
type Carotte struct {
Name string
Value int
List []string
EList []string `export:"true"`
Courgette Courgette
ECourgette Courgette `export:"true"`
Pourgette *Courgette
EPourgette *Courgette `export:"true"`
Aubergine map[string]string
EAubergine map[string]string `export:"true"`
SAubergine map[string]Tomate
ESAubergine map[string]Tomate `export:"true"`
PSAubergine map[string]*Tomate
EPAubergine map[string]*Tomate `export:"true"`
}
func Test_doOnStruct(t *testing.T) {
testCase := []struct {
name string
base *Carotte
expected *Carotte
}{
{
name: "primitive",
base: &Carotte{
Name: "koko",
Value: 666,
List: []string{"test"},
EList: []string{"test"},
},
expected: &Carotte{
Name: "xxxx",
List: []string{"xxxx"},
EList: []string{"test"},
},
},
{
name: "struct",
base: &Carotte{
Name: "koko",
Courgette: Courgette{
Ji: "huu",
},
},
expected: &Carotte{
Name: "xxxx",
},
},
{
name: "pointer",
base: &Carotte{
Name: "koko",
Pourgette: &Courgette{
Ji: "hoo",
},
},
expected: &Carotte{
Name: "xxxx",
Pourgette: nil,
},
},
{
name: "export struct",
base: &Carotte{
Name: "koko",
ECourgette: Courgette{
Ji: "huu",
},
},
expected: &Carotte{
Name: "xxxx",
ECourgette: Courgette{
Ji: "xxxx",
},
},
},
{
name: "export pointer struct",
base: &Carotte{
Name: "koko",
ECourgette: Courgette{
Ji: "huu",
},
},
expected: &Carotte{
Name: "xxxx",
ECourgette: Courgette{
Ji: "xxxx",
},
},
},
{
name: "export map string/string",
base: &Carotte{
Name: "koko",
EAubergine: map[string]string{
"foo": "bar",
},
},
expected: &Carotte{
Name: "xxxx",
EAubergine: map[string]string{
"foo": "bar",
},
},
},
{
name: "export map string/pointer",
base: &Carotte{
Name: "koko",
EPAubergine: map[string]*Tomate{
"foo": {
Ji: "fdskljf",
},
},
},
expected: &Carotte{
Name: "xxxx",
EPAubergine: map[string]*Tomate{
"foo": {
Ji: "xxxx",
},
},
},
},
{
name: "export map string/struct",
base: &Carotte{
Name: "koko",
ESAubergine: map[string]Tomate{
"foo": {
Ji: "JiJiJi",
},
},
},
expected: &Carotte{
Name: "xxxx",
ESAubergine: map[string]Tomate{
"foo": {
Ji: "xxxx",
},
},
},
},
}
for _, test := range testCase {
t.Run(test.name, func(t *testing.T) {
val := reflect.ValueOf(test.base).Elem()
err := doOnStruct(val)
require.NoError(t, err)
assert.EqualValues(t, test.expected, test.base)
})
}
}

View file

@ -10,9 +10,9 @@ import (
"time"
"github.com/mitchellh/hashstructure"
"github.com/traefik/traefik/v2/pkg/anonymize"
"github.com/traefik/traefik/v2/pkg/config/static"
"github.com/traefik/traefik/v2/pkg/log"
"github.com/traefik/traefik/v2/pkg/redactor"
"github.com/traefik/traefik/v2/pkg/version"
)
@ -30,7 +30,7 @@ type data struct {
// Collect anonymous data.
func Collect(staticConfiguration *static.Configuration) error {
anonConfig, err := anonymize.Do(staticConfiguration, false)
anonConfig, err := redactor.Anonymize(staticConfiguration)
if err != nil {
return err
}

View file

@ -64,7 +64,7 @@ type AddPrefix struct {
// BasicAuth holds the HTTP basic authentication configuration.
type BasicAuth struct {
Users Users `json:"users,omitempty" toml:"users,omitempty" yaml:"users,omitempty"`
Users Users `json:"users,omitempty" toml:"users,omitempty" yaml:"users,omitempty" loggable:"false"`
UsersFile string `json:"usersFile,omitempty" toml:"usersFile,omitempty" yaml:"usersFile,omitempty"`
Realm string `json:"realm,omitempty" toml:"realm,omitempty" yaml:"realm,omitempty"`
RemoveHeader bool `json:"removeHeader,omitempty" toml:"removeHeader,omitempty" yaml:"removeHeader,omitempty" export:"true"`
@ -108,7 +108,7 @@ type Compress struct {
// DigestAuth holds the Digest HTTP authentication configuration.
type DigestAuth struct {
Users Users `json:"users,omitempty" toml:"users,omitempty" yaml:"users,omitempty"`
Users Users `json:"users,omitempty" toml:"users,omitempty" yaml:"users,omitempty" loggable:"false"`
UsersFile string `json:"usersFile,omitempty" toml:"usersFile,omitempty" yaml:"usersFile,omitempty"`
RemoveHeader bool `json:"removeHeader,omitempty" toml:"removeHeader,omitempty" yaml:"removeHeader,omitempty" export:"true"`
Realm string `json:"realm,omitempty" toml:"realm,omitempty" yaml:"realm,omitempty"`

View file

@ -2,7 +2,7 @@ package static
// Pilot Configuration related to Traefik Pilot.
type Pilot struct {
Token string `description:"Traefik Pilot token." json:"token,omitempty" toml:"token,omitempty" yaml:"token,omitempty"`
Token string `description:"Traefik Pilot token." json:"token,omitempty" toml:"token,omitempty" yaml:"token,omitempty" loggable:"false"`
Dashboard bool `description:"Enable Traefik Pilot in the dashboard." json:"dashboard,omitempty" toml:"dashboard,omitempty" yaml:"dashboard,omitempty"`
}

View file

@ -106,7 +106,7 @@ type API struct {
Dashboard bool `description:"Activate dashboard." json:"dashboard,omitempty" toml:"dashboard,omitempty" yaml:"dashboard,omitempty" export:"true"`
Debug bool `description:"Enable additional endpoints for debugging and profiling." json:"debug,omitempty" toml:"debug,omitempty" yaml:"debug,omitempty" export:"true"`
// TODO: Re-enable statistics
// Statistics *types.Statistics `description:"Enable more detailed statistics." json:"statistics,omitempty" toml:"statistics,omitempty" yaml:"statistics,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
// Statistics *types.Statistics `description:"Enable more detailed statistics." json:"statistics,omitempty" toml:"statistics,omitempty" yaml:"statistics,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
}
// SetDefaults sets the default values.

View file

@ -11,10 +11,10 @@ import (
"time"
"github.com/cenkalti/backoff/v4"
"github.com/traefik/traefik/v2/pkg/anonymize"
"github.com/traefik/traefik/v2/pkg/config/dynamic"
"github.com/traefik/traefik/v2/pkg/log"
"github.com/traefik/traefik/v2/pkg/metrics"
"github.com/traefik/traefik/v2/pkg/redactor"
"github.com/traefik/traefik/v2/pkg/safe"
"github.com/traefik/traefik/v2/pkg/version"
)
@ -173,7 +173,7 @@ func (c *client) createUUID() (string, error) {
// SendAnonDynConf sends anonymized dynamic configuration to Pilot.
func (c *client) SendAnonDynConf(ctx context.Context, config dynamic.Configuration) error {
anonConfig, err := anonymize.Do(&config, false)
anonConfig, err := redactor.Anonymize(&config)
if err != nil {
return fmt.Errorf("unable to anonymize dynamic configuration: %w", err)
}

View file

@ -8,7 +8,7 @@ import (
// Handler expose ping routes.
type Handler struct {
EntryPoint string `description:"EntryPoint" export:"true" json:"entryPoint,omitempty" toml:"entryPoint,omitempty" yaml:"entryPoint,omitempty"`
EntryPoint string `description:"EntryPoint" json:"entryPoint,omitempty" toml:"entryPoint,omitempty" yaml:"entryPoint,omitempty" export:"true"`
ManualRouting bool `description:"Manual routing" json:"manualRouting,omitempty" toml:"manualRouting,omitempty" yaml:"manualRouting,omitempty" export:"true"`
TerminatingStatusCode int `description:"Terminating status code" json:"terminatingStatusCode,omitempty" toml:"terminatingStatusCode,omitempty" yaml:"terminatingStatusCode,omitempty" export:"true"`
terminating bool

View file

@ -69,8 +69,8 @@ type Certificate struct {
// EAB contains External Account Binding configuration.
type EAB struct {
Kid string `description:"Key identifier from External CA." json:"kid,omitempty" toml:"kid,omitempty" yaml:"kid,omitempty"`
HmacEncoded string `description:"Base64 encoded HMAC key from External CA." json:"hmacEncoded,omitempty" toml:"hmacEncoded,omitempty" yaml:"hmacEncoded,omitempty"`
Kid string `description:"Key identifier from External CA." json:"kid,omitempty" toml:"kid,omitempty" yaml:"kid,omitempty" loggable:"false"`
HmacEncoded string `description:"Base64 encoded HMAC key from External CA." json:"hmacEncoded,omitempty" toml:"hmacEncoded,omitempty" yaml:"hmacEncoded,omitempty" loggable:"false"`
}
// DNSChallenge contains DNS challenge configuration.

View file

@ -1,14 +1,13 @@
package aggregator
import (
"encoding/json"
"github.com/traefik/traefik/v2/pkg/config/dynamic"
"github.com/traefik/traefik/v2/pkg/config/static"
"github.com/traefik/traefik/v2/pkg/log"
"github.com/traefik/traefik/v2/pkg/provider"
"github.com/traefik/traefik/v2/pkg/provider/file"
"github.com/traefik/traefik/v2/pkg/provider/traefik"
"github.com/traefik/traefik/v2/pkg/redactor"
"github.com/traefik/traefik/v2/pkg/safe"
)
@ -140,12 +139,13 @@ func (p ProviderAggregator) Provide(configurationChan chan<- dynamic.Message, po
}
func launchProvider(configurationChan chan<- dynamic.Message, pool *safe.Pool, prd provider.Provider) {
jsonConf, err := json.Marshal(prd)
jsonConf, err := redactor.RemoveCredentials(prd)
if err != nil {
log.WithoutContext().Debugf("Cannot marshal the provider configuration %T: %v", prd, err)
}
log.WithoutContext().Infof("Starting provider %T %s", prd, jsonConf)
log.WithoutContext().Infof("Starting provider %T", prd)
log.WithoutContext().Debugf("%T provider configuration: %s", prd, jsonConf)
currentProvider := prd
err = currentProvider.Provide(configurationChan, pool)

View file

@ -67,7 +67,7 @@ type EndpointConfig struct {
Address string `description:"The address of the Consul server" json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty"`
Scheme string `description:"The URI scheme for the Consul server" json:"scheme,omitempty" toml:"scheme,omitempty" yaml:"scheme,omitempty"`
DataCenter string `description:"Data center to use. If not provided, the default agent data center is used" json:"datacenter,omitempty" toml:"datacenter,omitempty" yaml:"datacenter,omitempty"`
Token string `description:"Token is used to provide a per-request ACL token which overrides the agent's default token" json:"token,omitempty" toml:"token,omitempty" yaml:"token,omitempty"`
Token string `description:"Token is used to provide a per-request ACL token which overrides the agent's default token" json:"token,omitempty" toml:"token,omitempty" yaml:"token,omitempty" loggable:"false"`
TLS *types.ClientTLS `description:"Enable TLS support." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" export:"true"`
HTTPAuth *EndpointHTTPAuthConfig `description:"Auth info to use for http access" json:"httpAuth,omitempty" toml:"httpAuth,omitempty" yaml:"httpAuth,omitempty" export:"true"`
EndpointWaitTime ptypes.Duration `description:"WaitTime limits how long a Watch will block. If not provided, the agent default values will be used" json:"endpointWaitTime,omitempty" toml:"endpointWaitTime,omitempty" yaml:"endpointWaitTime,omitempty" export:"true"`
@ -75,8 +75,8 @@ type EndpointConfig struct {
// EndpointHTTPAuthConfig holds configurations of the authentication.
type EndpointHTTPAuthConfig struct {
Username string `description:"Basic Auth username" json:"username,omitempty" toml:"username,omitempty" yaml:"username,omitempty"`
Password string `description:"Basic Auth password" json:"password,omitempty" toml:"password,omitempty" yaml:"password,omitempty"`
Username string `description:"Basic Auth username" json:"username,omitempty" toml:"username,omitempty" yaml:"username,omitempty" loggable:"false"`
Password string `description:"Basic Auth password" json:"password,omitempty" toml:"password,omitempty" yaml:"password,omitempty" loggable:"false"`
}
// SetDefaults sets the default values.

View file

@ -34,8 +34,8 @@ type Provider struct {
Clusters []string `description:"ECS Clusters name" json:"clusters,omitempty" toml:"clusters,omitempty" yaml:"clusters,omitempty" export:"true"`
AutoDiscoverClusters bool `description:"Auto discover cluster" json:"autoDiscoverClusters,omitempty" toml:"autoDiscoverClusters,omitempty" yaml:"autoDiscoverClusters,omitempty" export:"true"`
Region string `description:"The AWS region to use for requests" json:"region,omitempty" toml:"region,omitempty" yaml:"region,omitempty" export:"true"`
AccessKeyID string `description:"The AWS credentials access key to use for making requests" json:"accessKeyID,omitempty" toml:"accessKeyID,omitempty" yaml:"accessKeyID,omitempty"`
SecretAccessKey string `description:"The AWS credentials access key to use for making requests" json:"secretAccessKey,omitempty" toml:"secretAccessKey,omitempty" yaml:"secretAccessKey,omitempty"`
AccessKeyID string `description:"The AWS credentials access key to use for making requests" json:"accessKeyID,omitempty" toml:"accessKeyID,omitempty" yaml:"accessKeyID,omitempty" loggable:"false"`
SecretAccessKey string `description:"The AWS credentials access key to use for making requests" json:"secretAccessKey,omitempty" toml:"secretAccessKey,omitempty" yaml:"secretAccessKey,omitempty" loggable:"false"`
defaultRuleTpl *template.Template
}

View file

@ -45,7 +45,7 @@ const (
// Provider holds configurations of the provider.
type Provider struct {
Endpoint string `description:"Kubernetes server endpoint (required for external cluster client)." json:"endpoint,omitempty" toml:"endpoint,omitempty" yaml:"endpoint,omitempty"`
Token string `description:"Kubernetes bearer token (not needed for in-cluster client)." json:"token,omitempty" toml:"token,omitempty" yaml:"token,omitempty"`
Token string `description:"Kubernetes bearer token (not needed for in-cluster client)." json:"token,omitempty" toml:"token,omitempty" yaml:"token,omitempty" loggable:"false"`
CertAuthFilePath string `description:"Kubernetes certificate authority file path (not needed for in-cluster client)." json:"certAuthFilePath,omitempty" toml:"certAuthFilePath,omitempty" yaml:"certAuthFilePath,omitempty"`
Namespaces []string `description:"Kubernetes namespaces." json:"namespaces,omitempty" toml:"namespaces,omitempty" yaml:"namespaces,omitempty" export:"true"`
AllowCrossNamespace bool `description:"Allow cross namespace resource reference." json:"allowCrossNamespace,omitempty" toml:"allowCrossNamespace,omitempty" yaml:"allowCrossNamespace,omitempty" export:"true"`

View file

@ -44,7 +44,7 @@ const (
// Provider holds configurations of the provider.
type Provider struct {
Endpoint string `description:"Kubernetes server endpoint (required for external cluster client)." json:"endpoint,omitempty" toml:"endpoint,omitempty" yaml:"endpoint,omitempty"`
Token string `description:"Kubernetes bearer token (not needed for in-cluster client)." json:"token,omitempty" toml:"token,omitempty" yaml:"token,omitempty"`
Token string `description:"Kubernetes bearer token (not needed for in-cluster client)." json:"token,omitempty" toml:"token,omitempty" yaml:"token,omitempty" loggable:"false"`
CertAuthFilePath string `description:"Kubernetes certificate authority file path (not needed for in-cluster client)." json:"certAuthFilePath,omitempty" toml:"certAuthFilePath,omitempty" yaml:"certAuthFilePath,omitempty"`
Namespaces []string `description:"Kubernetes namespaces." json:"namespaces,omitempty" toml:"namespaces,omitempty" yaml:"namespaces,omitempty" export:"true"`
LabelSelector string `description:"Kubernetes label selector to select specific GatewayClasses." json:"labelSelector,omitempty" toml:"labelSelector,omitempty" yaml:"labelSelector,omitempty" export:"true"`

View file

@ -37,7 +37,7 @@ const (
// Provider holds configurations of the provider.
type Provider struct {
Endpoint string `description:"Kubernetes server endpoint (required for external cluster client)." json:"endpoint,omitempty" toml:"endpoint,omitempty" yaml:"endpoint,omitempty"`
Token string `description:"Kubernetes bearer token (not needed for in-cluster client)." json:"token,omitempty" toml:"token,omitempty" yaml:"token,omitempty"`
Token string `description:"Kubernetes bearer token (not needed for in-cluster client)." json:"token,omitempty" toml:"token,omitempty" yaml:"token,omitempty" loggable:"false"`
CertAuthFilePath string `description:"Kubernetes certificate authority file path (not needed for in-cluster client)." json:"certAuthFilePath,omitempty" toml:"certAuthFilePath,omitempty" yaml:"certAuthFilePath,omitempty"`
Namespaces []string `description:"Kubernetes namespaces." json:"namespaces,omitempty" toml:"namespaces,omitempty" yaml:"namespaces,omitempty" export:"true"`
LabelSelector string `description:"Kubernetes Ingress label selector to use." json:"labelSelector,omitempty" toml:"labelSelector,omitempty" yaml:"labelSelector,omitempty" export:"true"`

View file

@ -24,14 +24,14 @@ import (
// Provider holds configurations of the provider.
type Provider struct {
RootKey string `description:"Root key used for KV store" export:"true" json:"rootKey,omitempty" toml:"rootKey,omitempty" yaml:"rootKey,omitempty"`
RootKey string `description:"Root key used for KV store" json:"rootKey,omitempty" toml:"rootKey,omitempty" yaml:"rootKey,omitempty"`
Endpoints []string `description:"KV store endpoints" json:"endpoints,omitempty" toml:"endpoints,omitempty" yaml:"endpoints,omitempty"`
Username string `description:"KV Username" json:"username,omitempty" toml:"username,omitempty" yaml:"username,omitempty"`
Password string `description:"KV Password" json:"password,omitempty" toml:"password,omitempty" yaml:"password,omitempty"`
Token string `description:"KV Token" json:"token,omitempty" toml:"token,omitempty" yaml:"token,omitempty"`
Username string `description:"KV Username" json:"username,omitempty" toml:"username,omitempty" yaml:"username,omitempty" loggable:"false"`
Password string `description:"KV Password" json:"password,omitempty" toml:"password,omitempty" yaml:"password,omitempty" loggable:"false"`
Token string `description:"KV Token" json:"token,omitempty" toml:"token,omitempty" yaml:"token,omitempty" loggable:"false"`
Namespace string `description:"KV Namespace" json:"namespace,omitempty" toml:"namespace,omitempty" yaml:"namespace,omitempty"`
TLS *types.ClientTLS `description:"Enable TLS support" export:"true" json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty"`
TLS *types.ClientTLS `description:"Enable TLS support" json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" export:"true" `
storeType store.Backend
kvClient store.Store

View file

@ -52,7 +52,7 @@ type Provider struct {
Endpoint string `description:"Marathon server endpoint. You can also specify multiple endpoint for Marathon." json:"endpoint,omitempty" toml:"endpoint,omitempty" yaml:"endpoint,omitempty"`
DefaultRule string `description:"Default rule." json:"defaultRule,omitempty" toml:"defaultRule,omitempty" yaml:"defaultRule,omitempty"`
ExposedByDefault bool `description:"Expose Marathon apps by default." json:"exposedByDefault,omitempty" toml:"exposedByDefault,omitempty" yaml:"exposedByDefault,omitempty" export:"true"`
DCOSToken string `description:"DCOSToken for DCOS environment, This will override the Authorization header." json:"dcosToken,omitempty" toml:"dcosToken,omitempty" yaml:"dcosToken,omitempty"`
DCOSToken string `description:"DCOSToken for DCOS environment, This will override the Authorization header." json:"dcosToken,omitempty" toml:"dcosToken,omitempty" yaml:"dcosToken,omitempty" loggable:"false"`
TLS *types.ClientTLS `description:"Enable TLS support." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" export:"true"`
DialerTimeout ptypes.Duration `description:"Set a dialer timeout for Marathon." json:"dialerTimeout,omitempty" toml:"dialerTimeout,omitempty" yaml:"dialerTimeout,omitempty" export:"true"`
ResponseHeaderTimeout ptypes.Duration `description:"Set a response header timeout for Marathon." json:"responseHeaderTimeout,omitempty" toml:"responseHeaderTimeout,omitempty" yaml:"responseHeaderTimeout,omitempty" export:"true"`
@ -80,8 +80,8 @@ func (p *Provider) SetDefaults() {
// Basic holds basic authentication specific configurations.
type Basic struct {
HTTPBasicAuthUser string `description:"Basic authentication User." json:"httpBasicAuthUser,omitempty" toml:"httpBasicAuthUser,omitempty" yaml:"httpBasicAuthUser,omitempty"`
HTTPBasicPassword string `description:"Basic authentication Password." json:"httpBasicPassword,omitempty" toml:"httpBasicPassword,omitempty" yaml:"httpBasicPassword,omitempty"`
HTTPBasicAuthUser string `description:"Basic authentication User." json:"httpBasicAuthUser,omitempty" toml:"httpBasicAuthUser,omitempty" yaml:"httpBasicAuthUser,omitempty" loggable:"false"`
HTTPBasicPassword string `description:"Basic authentication Password." json:"httpBasicPassword,omitempty" toml:"httpBasicPassword,omitempty" yaml:"httpBasicPassword,omitempty" loggable:"false"`
}
// Init the provider.

View file

@ -1,4 +1,4 @@
package anonymize
package redactor
import (
"encoding/json"
@ -13,12 +13,39 @@ import (
)
const (
maskShort = "xxxx"
maskLarge = maskShort + maskShort + maskShort + maskShort + maskShort + maskShort + maskShort + maskShort
maskShort = "xxxx"
maskLarge = maskShort + maskShort + maskShort + maskShort + maskShort + maskShort + maskShort + maskShort
tagLoggable = "loggable"
tagExport = "export"
)
// Do sends configuration.
func Do(baseConfig interface{}, indent bool) (string, error) {
// Anonymize redacts the configuration fields that do not have an export=true struct tag.
// It returns the resulting marshaled configuration.
func Anonymize(baseConfig interface{}) (string, error) {
return anonymize(baseConfig, false)
}
func anonymize(baseConfig interface{}, indent bool) (string, error) {
conf, err := do(baseConfig, tagExport, true, indent)
if err != nil {
return "", err
}
return doOnJSON(conf), nil
}
// RemoveCredentials redacts the configuration fields that have a loggable=false struct tag.
// It returns the resulting marshaled configuration.
func RemoveCredentials(baseConfig interface{}) (string, error) {
return removeCredentials(baseConfig, false)
}
func removeCredentials(baseConfig interface{}, indent bool) (string, error) {
return do(baseConfig, tagLoggable, false, indent)
}
// do marshals the given configuration, while redacting some of the fields
// respectively to the given tag.
func do(baseConfig interface{}, tag string, redactByDefault, indent bool) (string, error) {
anomConfig, err := copystructure.Copy(baseConfig)
if err != nil {
return "", err
@ -26,7 +53,7 @@ func Do(baseConfig interface{}, indent bool) (string, error) {
val := reflect.ValueOf(anomConfig)
err = doOnStruct(val)
err = doOnStruct(val, tag, redactByDefault)
if err != nil {
return "", err
}
@ -36,7 +63,7 @@ func Do(baseConfig interface{}, indent bool) (string, error) {
return "", err
}
return doOnJSON(string(configJSON)), nil
return string(configJSON), nil
}
func doOnJSON(input string) string {
@ -44,7 +71,7 @@ func doOnJSON(input string) string {
return xurls.Relaxed().ReplaceAllString(mailExp.ReplaceAllString(input, maskLarge+"\""), maskLarge)
}
func doOnStruct(field reflect.Value) error {
func doOnStruct(field reflect.Value, tag string, redactByDefault bool) error {
if field.Type().AssignableTo(reflect.TypeOf(dynamic.PluginConf{})) {
resetPlugin(field)
return nil
@ -53,7 +80,7 @@ func doOnStruct(field reflect.Value) error {
switch field.Kind() {
case reflect.Ptr:
if !field.IsNil() {
if err := doOnStruct(field.Elem()); err != nil {
if err := doOnStruct(field.Elem(), tag, redactByDefault); err != nil {
return err
}
}
@ -65,25 +92,28 @@ func doOnStruct(field reflect.Value) error {
continue
}
if stField.Tag.Get("export") == "true" {
// A struct field cannot be set it must be filled as pointer.
if fld.Kind() == reflect.Struct {
fldPtr := reflect.New(fld.Type())
fldPtr.Elem().Set(fld)
if err := doOnStruct(fldPtr); err != nil {
return err
}
fld.Set(fldPtr.Elem())
continue
}
if err := doOnStruct(fld); err != nil {
if stField.Tag.Get(tag) == "false" || stField.Tag.Get(tag) != "true" && redactByDefault {
if err := reset(fld, stField.Name); err != nil {
return err
}
} else if err := reset(fld, stField.Name); err != nil {
continue
}
// A struct field cannot be set it must be filled as pointer.
if fld.Kind() == reflect.Struct {
fldPtr := reflect.New(fld.Type())
fldPtr.Elem().Set(fld)
if err := doOnStruct(fldPtr, tag, redactByDefault); err != nil {
return err
}
fld.Set(fldPtr.Elem())
continue
}
if err := doOnStruct(fld, tag, redactByDefault); err != nil {
return err
}
}
@ -96,7 +126,7 @@ func doOnStruct(field reflect.Value) error {
valPtr := reflect.New(val.Type())
valPtr.Elem().Set(val)
if err := doOnStruct(valPtr); err != nil {
if err := doOnStruct(valPtr, tag, redactByDefault); err != nil {
return err
}
@ -105,13 +135,13 @@ func doOnStruct(field reflect.Value) error {
continue
}
if err := doOnStruct(val); err != nil {
if err := doOnStruct(val, tag, redactByDefault); err != nil {
return err
}
}
case reflect.Slice:
for j := 0; j < field.Len(); j++ {
if err := doOnStruct(field.Index(j)); err != nil {
if err := doOnStruct(field.Index(j), tag, redactByDefault); err != nil {
return err
}
}

View file

@ -1,4 +1,4 @@
package anonymize
package redactor
import (
"flag"
@ -43,7 +43,9 @@ import (
var updateExpected = flag.Bool("update_expected", false, "Update expected files in fixtures")
func TestDo_dynamicConfiguration(t *testing.T) {
var fullDynConf *dynamic.Configuration
func init() {
config := &dynamic.Configuration{}
config.HTTP = &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
@ -242,7 +244,7 @@ func TestDo_dynamicConfiguration(t *testing.T) {
SourceCriterion: &dynamic.SourceCriterion{
IPStrategy: &dynamic.IPStrategy{
Depth: 42,
ExcludedIPs: []string{"foo"},
ExcludedIPs: []string{"127.0.0.1"},
},
RequestHeaderName: "foo",
RequestHost: true,
@ -291,7 +293,7 @@ func TestDo_dynamicConfiguration(t *testing.T) {
SourceCriterion: &dynamic.SourceCriterion{
IPStrategy: &dynamic.IPStrategy{
Depth: 42,
ExcludedIPs: []string{"foo"},
ExcludedIPs: []string{"127.0.0.1"},
},
RequestHeaderName: "foo",
RequestHost: true,
@ -463,10 +465,16 @@ func TestDo_dynamicConfiguration(t *testing.T) {
},
}
fullDynConf = config
}
func TestAnonymize_dynamicConfiguration(t *testing.T) {
config := fullDynConf
expectedConfiguration, err := os.ReadFile("./testdata/anonymized-dynamic-config.json")
require.NoError(t, err)
cleanJSON, err := Do(config, true)
cleanJSON, err := anonymize(config, true)
require.NoError(t, err)
if *updateExpected {
@ -477,6 +485,23 @@ func TestDo_dynamicConfiguration(t *testing.T) {
assert.Equal(t, expected, cleanJSON)
}
func TestSecure_dynamicConfiguration(t *testing.T) {
config := fullDynConf
expectedConfiguration, err := os.ReadFile("./testdata/secured-dynamic-config.json")
require.NoError(t, err)
cleanJSON, err := removeCredentials(config, true)
require.NoError(t, err)
if *updateExpected {
require.NoError(t, os.WriteFile("testdata/secured-dynamic-config.json", []byte(cleanJSON), 0o666))
}
expected := strings.TrimSuffix(string(expectedConfiguration), "\n")
assert.Equal(t, expected, cleanJSON)
}
func TestDo_staticConfiguration(t *testing.T) {
config := &static.Configuration{}
@ -962,7 +987,7 @@ func TestDo_staticConfiguration(t *testing.T) {
expectedConfiguration, err := os.ReadFile("./testdata/anonymized-static-config.json")
require.NoError(t, err)
cleanJSON, err := Do(config, true)
cleanJSON, err := anonymize(config, true)
require.NoError(t, err)
if *updateExpected {

View file

@ -1,4 +1,4 @@
package anonymize
package redactor
import (
"os"
@ -57,7 +57,9 @@ func Test_doOnJSON_simple(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()
output := doOnJSON(test.input)
assert.Equal(t, test.expectedOutput, output)
})

View file

@ -0,0 +1,382 @@
package redactor
import (
"reflect"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
type Courgette struct {
Ji string
Ho string
}
type Tomate struct {
Ji string
Ho string
}
type Carotte struct {
Name string
EName string `export:"true"`
EFName string `export:"false"`
Value int
EValue int `export:"true"`
EFValue int `export:"false"`
List []string
EList []string `export:"true"`
EFList []string `export:"false"`
Courgette Courgette
ECourgette Courgette `export:"true"`
EFCourgette Courgette `export:"false"`
Pourgette *Courgette
EPourgette *Courgette `export:"true"`
EFPourgette *Courgette `export:"false"`
Aubergine map[string]string
EAubergine map[string]string `export:"true"`
EFAubergine map[string]string `export:"false"`
SAubergine map[string]Tomate
ESAubergine map[string]Tomate `export:"true"`
EFSAubergine map[string]Tomate `export:"false"`
PSAubergine map[string]*Tomate
EPAubergine map[string]*Tomate `export:"true"`
EFPAubergine map[string]*Tomate `export:"false"`
}
func Test_doOnStruct(t *testing.T) {
testCase := []struct {
name string
base *Carotte
expected *Carotte
redactByDefault bool
}{
{
name: "primitive",
base: &Carotte{
Name: "koko",
EName: "kiki",
Value: 666,
EValue: 666,
List: []string{"test"},
EList: []string{"test"},
},
expected: &Carotte{
Name: "xxxx",
EName: "kiki",
EValue: 666,
List: []string{"xxxx"},
EList: []string{"test"},
},
redactByDefault: true,
},
{
name: "primitive2",
base: &Carotte{
Name: "koko",
EFName: "keke",
Value: 666,
EFValue: 777,
List: []string{"test"},
EFList: []string{"test"},
},
expected: &Carotte{
Name: "koko",
EFName: "xxxx",
Value: 666,
List: []string{"test"},
EFList: []string{"xxxx"},
},
redactByDefault: false,
},
{
name: "struct",
base: &Carotte{
Name: "koko",
Courgette: Courgette{
Ji: "huu",
},
},
expected: &Carotte{
Name: "xxxx",
},
redactByDefault: true,
},
{
name: "struct2",
base: &Carotte{
Name: "koko",
EFName: "keke",
Courgette: Courgette{
Ji: "huu",
},
EFCourgette: Courgette{
Ji: "huu",
},
},
expected: &Carotte{
Name: "koko",
EFName: "xxxx",
Courgette: Courgette{
Ji: "huu",
Ho: "",
},
},
redactByDefault: false,
},
{
name: "pointer",
base: &Carotte{
Name: "koko",
Pourgette: &Courgette{
Ji: "hoo",
},
},
expected: &Carotte{
Name: "xxxx",
Pourgette: nil,
},
redactByDefault: true,
},
{
name: "pointer2",
base: &Carotte{
Name: "koko",
EFName: "keke",
Pourgette: &Courgette{
Ji: "hoo",
},
EFPourgette: &Courgette{
Ji: "hoo",
},
},
expected: &Carotte{
Name: "koko",
EFName: "xxxx",
Pourgette: &Courgette{
Ji: "hoo",
},
EFPourgette: nil,
},
redactByDefault: false,
},
{
name: "export struct",
base: &Carotte{
Name: "koko",
ECourgette: Courgette{
Ji: "huu",
},
},
expected: &Carotte{
Name: "xxxx",
ECourgette: Courgette{
Ji: "xxxx",
},
},
redactByDefault: true,
},
{
name: "export struct 2",
base: &Carotte{
Name: "koko",
EFName: "keke",
ECourgette: Courgette{
Ji: "huu",
},
EFCourgette: Courgette{
Ji: "huu",
},
},
expected: &Carotte{
Name: "koko",
EFName: "xxxx",
ECourgette: Courgette{
Ji: "huu",
},
},
redactByDefault: false,
},
{
name: "export pointer struct",
base: &Carotte{
Name: "koko",
EPourgette: &Courgette{
Ji: "huu",
},
},
expected: &Carotte{
Name: "xxxx",
EPourgette: &Courgette{
Ji: "xxxx",
},
},
redactByDefault: true,
},
{
name: "export pointer struct 2",
base: &Carotte{
Name: "koko",
EFName: "keke",
EPourgette: &Courgette{
Ji: "huu",
},
EFPourgette: &Courgette{
Ji: "huu",
},
},
expected: &Carotte{
Name: "koko",
EFName: "xxxx",
EPourgette: &Courgette{
Ji: "huu",
},
EFPourgette: nil,
},
redactByDefault: false,
},
{
name: "export map string/string",
base: &Carotte{
Name: "koko",
EAubergine: map[string]string{
"foo": "bar",
},
},
expected: &Carotte{
Name: "xxxx",
EAubergine: map[string]string{
"foo": "bar",
},
},
redactByDefault: true,
},
{
name: "export map string/string 2",
base: &Carotte{
Name: "koko",
EFName: "keke",
EAubergine: map[string]string{
"foo": "bar",
},
EFAubergine: map[string]string{
"foo": "bar",
},
},
expected: &Carotte{
Name: "koko",
EFName: "xxxx",
EAubergine: map[string]string{
"foo": "bar",
},
EFAubergine: map[string]string{},
},
redactByDefault: false,
},
{
name: "export map string/pointer",
base: &Carotte{
Name: "koko",
EPAubergine: map[string]*Tomate{
"foo": {
Ji: "fdskljf",
},
},
},
expected: &Carotte{
Name: "xxxx",
EPAubergine: map[string]*Tomate{
"foo": {
Ji: "xxxx",
},
},
},
redactByDefault: true,
},
{
name: "export map string/pointer 2",
base: &Carotte{
Name: "koko",
EPAubergine: map[string]*Tomate{
"foo": {
Ji: "fdskljf",
},
},
EFPAubergine: map[string]*Tomate{
"foo": {
Ji: "fdskljf",
},
},
},
expected: &Carotte{
Name: "koko",
EPAubergine: map[string]*Tomate{
"foo": {
Ji: "fdskljf",
},
},
EFPAubergine: map[string]*Tomate{},
},
redactByDefault: false,
},
{
name: "export map string/struct",
base: &Carotte{
Name: "koko",
ESAubergine: map[string]Tomate{
"foo": {
Ji: "JiJiJi",
},
},
},
expected: &Carotte{
Name: "xxxx",
ESAubergine: map[string]Tomate{
"foo": {
Ji: "xxxx",
},
},
},
redactByDefault: true,
},
{
name: "export map string/struct 2",
base: &Carotte{
Name: "koko",
ESAubergine: map[string]Tomate{
"foo": {
Ji: "JiJiJi",
},
},
EFSAubergine: map[string]Tomate{
"foo": {
Ji: "JiJiJi",
},
},
},
expected: &Carotte{
Name: "koko",
ESAubergine: map[string]Tomate{
"foo": {
Ji: "JiJiJi",
},
},
EFSAubergine: map[string]Tomate{},
},
redactByDefault: false,
},
}
for _, test := range testCase {
test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()
val := reflect.ValueOf(test.base).Elem()
err := doOnStruct(val, tagExport, test.redactByDefault)
require.NoError(t, err)
assert.EqualValues(t, test.expected, test.base)
})
}
}

View file

@ -223,7 +223,7 @@
"secretAccessKey": "xxxx"
},
"consul": {
"rootKey": "RootKey",
"rootKey": "xxxx",
"username": "xxxx",
"password": "xxxx",
"tls": {
@ -235,7 +235,7 @@
}
},
"etcd": {
"rootKey": "RootKey",
"rootKey": "xxxx",
"username": "xxxx",
"password": "xxxx",
"tls": {
@ -247,7 +247,7 @@
}
},
"zooKeeper": {
"rootKey": "RootKey",
"rootKey": "xxxx",
"username": "xxxx",
"password": "xxxx",
"tls": {
@ -259,7 +259,7 @@
}
},
"redis": {
"rootKey": "RootKey",
"rootKey": "xxxx",
"username": "xxxx",
"password": "xxxx",
"tls": {

View file

@ -0,0 +1,487 @@
{
"http": {
"routers": {
"foo": {
"entryPoints": [
"foo"
],
"middlewares": [
"foo"
],
"service": "foo",
"rule": "foo",
"priority": 42,
"tls": {
"options": "foo",
"certResolver": "foo",
"domains": [
{
"main": "foo",
"sans": [
"foo"
]
}
]
}
}
},
"services": {
"bar": {
"weighted": {
"services": [
{
"name": "foo",
"weight": 42
}
],
"sticky": {
"cookie": {
"name": "foo",
"secure": true,
"httpOnly": true,
"sameSite": "foo"
}
}
}
},
"baz": {
"mirroring": {
"service": "foo",
"maxBodySize": 42,
"mirrors": [
{
"name": "foo",
"percent": 42
}
]
}
},
"foo": {
"loadBalancer": {
"sticky": {
"cookie": {
"name": "foo",
"secure": true,
"httpOnly": true,
"sameSite": "foo"
}
},
"servers": [
{
"url": "http://127.0.0.1:8080"
}
],
"healthCheck": {
"scheme": "foo",
"path": "foo",
"port": 42,
"interval": "foo",
"timeout": "foo",
"hostname": "foo",
"followRedirects": true,
"headers": {
"foo": "bar"
}
},
"passHostHeader": true,
"responseForwarding": {
"flushInterval": "foo"
},
"serversTransport": "foo"
}
}
},
"middlewares": {
"foo": {
"addPrefix": {
"prefix": "foo"
},
"stripPrefix": {
"prefixes": [
"foo"
],
"forceSlash": true
},
"stripPrefixRegex": {
"regex": [
"foo"
]
},
"replacePath": {
"path": "foo"
},
"replacePathRegex": {
"regex": "foo",
"replacement": "foo"
},
"chain": {
"middlewares": [
"foo"
]
},
"ipWhiteList": {
"sourceRange": [
"foo"
],
"ipStrategy": {
"depth": 42,
"excludedIPs": [
"127.0.0.1"
]
}
},
"headers": {
"customRequestHeaders": {
"foo": "bar"
},
"customResponseHeaders": {
"foo": "bar"
},
"accessControlAllowCredentials": true,
"accessControlAllowHeaders": [
"foo"
],
"accessControlAllowMethods": [
"foo"
],
"accessControlAllowOriginList": [
"foo"
],
"accessControlAllowOriginListRegex": [
"foo"
],
"accessControlExposeHeaders": [
"foo"
],
"accessControlMaxAge": 42,
"addVaryHeader": true,
"allowedHosts": [
"foo"
],
"hostsProxyHeaders": [
"foo"
],
"sslRedirect": true,
"sslTemporaryRedirect": true,
"sslHost": "foo",
"sslProxyHeaders": {
"foo": "bar"
},
"sslForceHost": true,
"stsSeconds": 42,
"stsIncludeSubdomains": true,
"stsPreload": true,
"forceSTSHeader": true,
"frameDeny": true,
"customFrameOptionsValue": "foo",
"contentTypeNosniff": true,
"browserXssFilter": true,
"customBrowserXSSValue": "foo",
"contentSecurityPolicy": "foo",
"publicKey": "foo",
"referrerPolicy": "foo",
"featurePolicy": "foo",
"permissionsPolicy": "foo",
"isDevelopment": true
},
"errors": {
"status": [
"foo"
],
"service": "foo",
"query": "foo"
},
"rateLimit": {
"average": 42,
"period": "42ns",
"burst": 42,
"sourceCriterion": {
"ipStrategy": {
"depth": 42,
"excludedIPs": [
"127.0.0.1"
]
},
"requestHeaderName": "foo",
"requestHost": true
}
},
"redirectRegex": {
"regex": "foo",
"replacement": "foo",
"permanent": true
},
"redirectScheme": {
"scheme": "foo",
"port": "foo",
"permanent": true
},
"basicAuth": {
"users": [
"xxxx"
],
"usersFile": "foo",
"realm": "foo",
"removeHeader": true,
"headerField": "foo"
},
"digestAuth": {
"users": [
"xxxx"
],
"usersFile": "foo",
"removeHeader": true,
"realm": "foo",
"headerField": "foo"
},
"forwardAuth": {
"address": "127.0.0.1",
"tls": {
"ca": "ca.pem",
"caOptional": true,
"cert": "cert.pem",
"key": "xxxx",
"insecureSkipVerify": true
},
"trustForwardHeader": true,
"authResponseHeaders": [
"foo"
],
"authResponseHeadersRegex": "foo",
"authRequestHeaders": [
"foo"
]
},
"inFlightReq": {
"amount": 42,
"sourceCriterion": {
"ipStrategy": {
"depth": 42,
"excludedIPs": [
"127.0.0.1"
]
},
"requestHeaderName": "foo",
"requestHost": true
}
},
"buffering": {
"maxRequestBodyBytes": 42,
"memRequestBodyBytes": 42,
"maxResponseBodyBytes": 42,
"memResponseBodyBytes": 42,
"retryExpression": "foo"
},
"circuitBreaker": {
"expression": "foo"
},
"compress": {
"excludedContentTypes": [
"foo"
]
},
"passTLSClientCert": {
"pem": true,
"info": {
"notAfter": true,
"notBefore": true,
"sans": true,
"subject": {
"country": true,
"province": true,
"locality": true,
"organization": true,
"organizationalUnit": true,
"commonName": true,
"serialNumber": true,
"domainComponent": true
},
"issuer": {
"country": true,
"province": true,
"locality": true,
"organization": true,
"commonName": true,
"serialNumber": true,
"domainComponent": true
},
"serialNumber": true
}
},
"retry": {
"attempts": 42,
"initialInterval": "42ns"
},
"contentType": {
"autoDetect": true
},
"plugin": {
"foo": {
"answer": {}
}
}
}
},
"models": {
"foo": {
"middlewares": [
"foo"
],
"tls": {
"options": "foo",
"certResolver": "foo",
"domains": [
{
"main": "foo",
"sans": [
"foo"
]
}
]
}
}
},
"serversTransports": {
"foo": {
"serverName": "foo",
"insecureSkipVerify": true,
"rootCAs": [
"rootca.pem"
],
"certificates": [
{
"certFile": "cert.pem",
"keyFile": "xxxx"
}
],
"maxIdleConnsPerHost": 42,
"forwardingTimeouts": {
"dialTimeout": "42ns",
"responseHeaderTimeout": "42ns",
"idleConnTimeout": "42ns",
"readIdleTimeout": "42ns",
"pingTimeout": "42ns"
}
}
}
},
"tcp": {
"routers": {
"foo": {
"entryPoints": [
"foo"
],
"service": "foo",
"rule": "foo",
"tls": {
"passthrough": true,
"options": "foo",
"certResolver": "foo",
"domains": [
{
"main": "foo",
"sans": [
"foo"
]
}
]
}
}
},
"services": {
"bar": {
"weighted": {
"services": [
{
"name": "foo",
"weight": 42
}
]
}
},
"foo": {
"loadBalancer": {
"terminationDelay": 42,
"proxyProtocol": {
"version": 42
},
"servers": [
{
"address": "127.0.0.1:8080"
}
]
}
}
}
},
"udp": {
"routers": {
"foo": {
"entryPoints": [
"foo"
],
"service": "foo"
}
},
"services": {
"bar": {
"weighted": {
"services": [
{
"name": "foo",
"weight": 42
}
]
}
},
"foo": {
"loadBalancer": {
"servers": [
{
"address": "127.0.0.1:8080"
}
]
}
}
}
},
"tls": {
"certificates": [
{
"certFile": "cert.pem",
"keyFile": "xxxx",
"stores": [
"foo"
]
}
],
"options": {
"foo": {
"minVersion": "foo",
"maxVersion": "foo",
"cipherSuites": [
"foo"
],
"curvePreferences": [
"foo"
],
"clientAuth": {
"caFiles": [
"ca.pem"
],
"clientAuthType": "RequireAndVerifyClientCert"
},
"sniStrict": true,
"preferServerCipherSuites": true
}
},
"stores": {
"foo": {
"defaultCertificate": {
"certFile": "cert.pem",
"keyFile": "xxxx"
}
}
}
}
}

View file

@ -84,12 +84,8 @@ func (c *ConfigurationWatcher) AddListener(listener func(dynamic.Configuration))
func (c *ConfigurationWatcher) startProvider() {
logger := log.WithoutContext()
jsonConf, err := json.Marshal(c.provider)
if err != nil {
logger.Debugf("Unable to marshal provider configuration %T: %v", c.provider, err)
}
logger.Infof("Starting provider %T", c.provider)
logger.Infof("Starting provider %T %s", c.provider, jsonConf)
currentProvider := c.provider
safe.Go(func() {

View file

@ -50,7 +50,7 @@ var (
// Certs and Key could be either a file path, or the file content itself.
type Certificate struct {
CertFile FileOrContent `json:"certFile,omitempty" toml:"certFile,omitempty" yaml:"certFile,omitempty"`
KeyFile FileOrContent `json:"keyFile,omitempty" toml:"keyFile,omitempty" yaml:"keyFile,omitempty"`
KeyFile FileOrContent `json:"keyFile,omitempty" toml:"keyFile,omitempty" yaml:"keyFile,omitempty" loggable:"false"`
}
// Certificates defines traefik certificates type

View file

@ -25,7 +25,7 @@ func init() {
// Config provides configuration settings for a elastic.co tracer.
type Config struct {
ServerURL string `description:"Sets the URL of the Elastic APM server." json:"serverURL,omitempty" toml:"serverURL,omitempty" yaml:"serverURL,omitempty"`
SecretToken string `description:"Sets the token used to connect to Elastic APM Server." json:"secretToken,omitempty" toml:"secretToken,omitempty" yaml:"secretToken,omitempty"`
SecretToken string `description:"Sets the token used to connect to Elastic APM Server." json:"secretToken,omitempty" toml:"secretToken,omitempty" yaml:"secretToken,omitempty" loggable:"false"`
ServiceEnvironment string `description:"Sets the name of the environment Traefik is deployed in, e.g. 'production' or 'staging'." json:"serviceEnvironment,omitempty" toml:"serviceEnvironment,omitempty" yaml:"serviceEnvironment,omitempty" export:"true"`
}

View file

@ -43,8 +43,8 @@ func (c *Config) SetDefaults() {
// Collector provides configuration settings for jaeger collector.
type Collector struct {
Endpoint string `description:"Instructs reporter to send spans to jaeger-collector at this URL." json:"endpoint,omitempty" toml:"endpoint,omitempty" yaml:"endpoint,omitempty"`
User string `description:"User for basic http authentication when sending spans to jaeger-collector." json:"user,omitempty" toml:"user,omitempty" yaml:"user,omitempty"`
Password string `description:"Password for basic http authentication when sending spans to jaeger-collector." json:"password,omitempty" toml:"password,omitempty" yaml:"password,omitempty"`
User string `description:"User for basic http authentication when sending spans to jaeger-collector." json:"user,omitempty" toml:"user,omitempty" yaml:"user,omitempty" loggable:"false"`
Password string `description:"Password for basic http authentication when sending spans to jaeger-collector." json:"password,omitempty" toml:"password,omitempty" yaml:"password,omitempty" loggable:"false"`
}
// SetDefaults sets the default values.

View file

@ -22,7 +22,7 @@ type Prometheus struct {
AddEntryPointsLabels bool `description:"Enable metrics on entry points." json:"addEntryPointsLabels,omitempty" toml:"addEntryPointsLabels,omitempty" yaml:"addEntryPointsLabels,omitempty" export:"true"`
AddRoutersLabels bool `description:"Enable metrics on routers." json:"addRoutersLabels,omitempty" toml:"addRoutersLabels,omitempty" yaml:"addRoutersLabels,omitempty" export:"true"`
AddServicesLabels bool `description:"Enable metrics on services." json:"addServicesLabels,omitempty" toml:"addServicesLabels,omitempty" yaml:"addServicesLabels,omitempty" export:"true"`
EntryPoint string `description:"EntryPoint" export:"true" json:"entryPoint,omitempty" toml:"entryPoint,omitempty" yaml:"entryPoint,omitempty"`
EntryPoint string `description:"EntryPoint" json:"entryPoint,omitempty" toml:"entryPoint,omitempty" yaml:"entryPoint,omitempty" export:"true"`
ManualRouting bool `description:"Manual routing" json:"manualRouting,omitempty" toml:"manualRouting,omitempty" yaml:"manualRouting,omitempty" export:"true"`
}
@ -88,8 +88,8 @@ type InfluxDB struct {
PushInterval types.Duration `description:"InfluxDB push interval." json:"pushInterval,omitempty" toml:"pushInterval,omitempty" yaml:"pushInterval,omitempty" export:"true"`
Database string `description:"InfluxDB database used when protocol is http." json:"database,omitempty" toml:"database,omitempty" yaml:"database,omitempty" export:"true"`
RetentionPolicy string `description:"InfluxDB retention policy used when protocol is http." json:"retentionPolicy,omitempty" toml:"retentionPolicy,omitempty" yaml:"retentionPolicy,omitempty" export:"true"`
Username string `description:"InfluxDB username (only with http)." json:"username,omitempty" toml:"username,omitempty" yaml:"username,omitempty"`
Password string `description:"InfluxDB password (only with http)." json:"password,omitempty" toml:"password,omitempty" yaml:"password,omitempty"`
Username string `description:"InfluxDB username (only with http)." json:"username,omitempty" toml:"username,omitempty" yaml:"username,omitempty" loggable:"false"`
Password string `description:"InfluxDB password (only with http)." json:"password,omitempty" toml:"password,omitempty" yaml:"password,omitempty" loggable:"false"`
AddEntryPointsLabels bool `description:"Enable metrics on entry points." json:"addEntryPointsLabels,omitempty" toml:"addEntryPointsLabels,omitempty" yaml:"addEntryPointsLabels,omitempty" export:"true"`
AddRoutersLabels bool `description:"Enable metrics on routers." json:"addRoutersLabels,omitempty" toml:"addRoutersLabels,omitempty" yaml:"addRoutersLabels,omitempty" export:"true"`
AddServicesLabels bool `description:"Enable metrics on services." json:"addServicesLabels,omitempty" toml:"addServicesLabels,omitempty" yaml:"addServicesLabels,omitempty" export:"true"`

View file

@ -19,7 +19,7 @@ type ClientTLS struct {
CA string `description:"TLS CA" json:"ca,omitempty" toml:"ca,omitempty" yaml:"ca,omitempty"`
CAOptional bool `description:"TLS CA.Optional" json:"caOptional,omitempty" toml:"caOptional,omitempty" yaml:"caOptional,omitempty" export:"true"`
Cert string `description:"TLS cert" json:"cert,omitempty" toml:"cert,omitempty" yaml:"cert,omitempty"`
Key string `description:"TLS key" json:"key,omitempty" toml:"key,omitempty" yaml:"key,omitempty"`
Key string `description:"TLS key" json:"key,omitempty" toml:"key,omitempty" yaml:"key,omitempty" loggable:"false"`
InsecureSkipVerify bool `description:"TLS insecure skip verify" json:"insecureSkipVerify,omitempty" toml:"insecureSkipVerify,omitempty" yaml:"insecureSkipVerify,omitempty" export:"true"`
}