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:
parent
3bd5fc0f90
commit
a4b354b33f
32 changed files with 1007 additions and 262 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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"`
|
||||
|
|
|
@ -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"`
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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"`
|
||||
|
|
|
@ -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"`
|
||||
|
|
|
@ -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"`
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package anonymize
|
||||
package redactor
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
@ -15,10 +15,37 @@ import (
|
|||
const (
|
||||
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,13 +92,19 @@ func doOnStruct(field reflect.Value) error {
|
|||
continue
|
||||
}
|
||||
|
||||
if stField.Tag.Get("export") == "true" {
|
||||
if stField.Tag.Get(tag) == "false" || stField.Tag.Get(tag) != "true" && redactByDefault {
|
||||
if err := reset(fld, stField.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
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); err != nil {
|
||||
if err := doOnStruct(fldPtr, tag, redactByDefault); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -80,10 +113,7 @@ func doOnStruct(field reflect.Value) error {
|
|||
continue
|
||||
}
|
||||
|
||||
if err := doOnStruct(fld); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if err := reset(fld, stField.Name); err != nil {
|
||||
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
|
||||
}
|
||||
}
|
|
@ -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 {
|
|
@ -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)
|
||||
})
|
382
pkg/redactor/redactor_doOnStruct_test.go
Normal file
382
pkg/redactor/redactor_doOnStruct_test.go
Normal 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)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -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": {
|
487
pkg/redactor/testdata/secured-dynamic-config.json
vendored
Normal file
487
pkg/redactor/testdata/secured-dynamic-config.json
vendored
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"`
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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"`
|
||||
|
|
|
@ -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"`
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue