From 1c31d5ac538931e0e5d55ff4967a585d356c4385 Mon Sep 17 00:00:00 2001 From: Scott Miller Date: Thu, 17 Jun 2021 13:09:37 -0500 Subject: [PATCH] Wire configuration checks into diagnose and fix resulting bugs. (#11854) * Actually call config.Validate in diagnose * Wire configuration checks into diagnose and fix resulting bugs. * go mod vendor * Merge to vendorless version * Remove sentinel section to allow diagnose_ok to pass * Fix unit tests --- command/agent/config/config.go | 2 ++ command/operator_diagnose.go | 26 +++++++++++------ command/operator_diagnose_test.go | 2 +- command/server.go | 13 +++++---- command/server/config.go | 12 +++++++- command/server/config_test_helpers.go | 12 +++++--- command/server/test-fixtures/config.hcl | 1 - command/server/test-fixtures/config5.hcl | 2 +- .../test-fixtures/config_diagnose_ok.hcl | 4 --- go.mod | 4 +-- go.sum | 23 +++++++++++---- internalshared/configutil/config.go | 11 +++++++ internalshared/configutil/lint.go | 5 +--- internalshared/configutil/listener.go | 29 ++++++++++++------- internalshared/configutil/telemetry.go | 2 +- vault/diagnose/output.go | 13 +++++---- 16 files changed, 105 insertions(+), 56 deletions(-) diff --git a/command/agent/config/config.go b/command/agent/config/config.go index aa0647bd66..deceeb9f05 100644 --- a/command/agent/config/config.go +++ b/command/agent/config/config.go @@ -32,6 +32,8 @@ type Config struct { func (c *Config) Prune() { for _, l := range c.Listeners { l.RawConfig = nil + l.Profiling.UnusedKeys = nil + l.Telemetry.UnusedKeys = nil } c.FoundKeys = nil c.UnusedKeys = nil diff --git a/command/operator_diagnose.go b/command/operator_diagnose.go index a06b9fe08f..dd816cb82d 100644 --- a/command/operator_diagnose.go +++ b/command/operator_diagnose.go @@ -16,6 +16,7 @@ import ( "github.com/hashicorp/consul/api" log "github.com/hashicorp/go-hclog" uuid "github.com/hashicorp/go-uuid" + cserver "github.com/hashicorp/vault/command/server" "github.com/hashicorp/vault/helper/metricsutil" "github.com/hashicorp/vault/internalshared/configutil" "github.com/hashicorp/vault/internalshared/listenerutil" @@ -227,13 +228,20 @@ func (c *OperatorDiagnoseCommand) offlineDiagnostics(ctx context.Context) error // OS Specific checks diagnose.OSChecks(ctx) - server.flagConfigs = c.flagConfigs - config, err := server.parseConfig() - if err != nil { - return diagnose.SpotError(ctx, "parse-config", err) - } else { - diagnose.SpotOk(ctx, "parse-config", "") - } + var config *cserver.Config + + diagnose.Test(ctx, "Parse configuration", func(ctx context.Context) (err error) { + server.flagConfigs = c.flagConfigs + var configErrors []configutil.ConfigError + config, configErrors, err = server.parseConfig() + if err != nil { + return err + } + for _, ce := range configErrors { + diagnose.Warn(ctx, ce.String()) + } + return nil + }) var metricSink *metricsutil.ClusterMetricSink var metricsHelper *metricsutil.MetricsHelper @@ -278,7 +286,7 @@ func (c *OperatorDiagnoseCommand) offlineDiagnostics(ctx context.Context) error // Consul storage checks if config.Storage != nil && config.Storage.Type == storageTypeConsul { diagnose.Test(ctx, "test-storage-tls-consul", func(ctx context.Context) error { - err = physconsul.SetupSecureTLS(ctx, api.DefaultConfig(), config.Storage.Config, server.logger, true) + err := physconsul.SetupSecureTLS(ctx, api.DefaultConfig(), config.Storage.Config, server.logger, true) if err != nil { return err } @@ -346,7 +354,7 @@ func (c *OperatorDiagnoseCommand) offlineDiagnostics(ctx context.Context) error diagnose.Test(ctx, "test-serviceregistration-tls-consul", func(ctx context.Context) error { // SetupSecureTLS for service discovery uses the same cert and key to set up physical // storage. See the consul package in physical for details. - err = srconsul.SetupSecureTLS(ctx, api.DefaultConfig(), srConfig, server.logger, true) + err := srconsul.SetupSecureTLS(ctx, api.DefaultConfig(), srConfig, server.logger, true) if err != nil { return err } diff --git a/command/operator_diagnose_test.go b/command/operator_diagnose_test.go index bdaf54f908..3be7ba0a1a 100644 --- a/command/operator_diagnose_test.go +++ b/command/operator_diagnose_test.go @@ -40,7 +40,7 @@ func TestOperatorDiagnoseCommand_Run(t *testing.T) { }, []*diagnose.Result{ { - Name: "parse-config", + Name: "Parse configuration", Status: diagnose.OkStatus, }, { diff --git a/command/server.go b/command/server.go index 7669f2d8be..050e3f8079 100644 --- a/command/server.go +++ b/command/server.go @@ -405,26 +405,29 @@ func (c *ServerCommand) flushLog() { }, c.gatedWriter) } -func (c *ServerCommand) parseConfig() (*server.Config, error) { +func (c *ServerCommand) parseConfig() (*server.Config, []configutil.ConfigError, error) { + var configErrors []configutil.ConfigError // Load the configuration var config *server.Config for _, path := range c.flagConfigs { current, err := server.LoadConfig(path) if err != nil { - return nil, fmt.Errorf("error loading configuration from %s: %w", path, err) + return nil, nil, fmt.Errorf("error loading configuration from %s: %w", path, err) } + configErrors = append(configErrors, current.Validate(path)...) + if config == nil { config = current } else { config = config.Merge(current) } } - return config, nil + return config, configErrors, nil } func (c *ServerCommand) runRecoveryMode() int { - config, err := c.parseConfig() + config, _, err := c.parseConfig() if err != nil { c.UI.Error(err.Error()) return 1 @@ -1063,7 +1066,7 @@ func (c *ServerCommand) Run(args []string) int { config.Listeners[0].Telemetry.UnauthenticatedMetricsAccess = true } - parsedConfig, err := c.parseConfig() + parsedConfig, _, err := c.parseConfig() if err != nil { c.UI.Error(err.Error()) return 1 diff --git a/command/server/config.go b/command/server/config.go index 2626d249b9..914e5b7210 100644 --- a/command/server/config.go +++ b/command/server/config.go @@ -22,6 +22,7 @@ import ( // Config is the configuration for the vault server. type Config struct { UnusedKeys configutil.UnusedKeyMap `hcl:",unusedKeyPositions"` + FoundKeys []string `hcl:",decodedFields"` entConfig *configutil.SharedConfig `hcl:"-"` @@ -87,6 +88,9 @@ func (c *Config) Validate(sourceFilePath string) []configutil.ConfigError { results := configutil.ValidateUnusedFields(c.UnusedKeys, sourceFilePath) if c.Telemetry != nil { results = append(results, c.Telemetry.Validate(sourceFilePath)...) + for _, l := range c.Listeners { + results = append(results, l.Validate(sourceFilePath)...) + } } return results } @@ -462,10 +466,12 @@ func ParseConfig(d, source string) (*Config, error) { // Look for storage but still support old backend if o := list.Filter("storage"); len(o.Items) > 0 { + delete(result.UnusedKeys, "storage") if err := ParseStorage(result, o, "storage"); err != nil { return nil, fmt.Errorf("error parsing 'storage': %w", err) } } else { + delete(result.UnusedKeys, "backend") if o := list.Filter("backend"); len(o.Items) > 0 { if err := ParseStorage(result, o, "backend"); err != nil { return nil, fmt.Errorf("error parsing 'backend': %w", err) @@ -474,11 +480,13 @@ func ParseConfig(d, source string) (*Config, error) { } if o := list.Filter("ha_storage"); len(o.Items) > 0 { + delete(result.UnusedKeys, "ha_storage") if err := parseHAStorage(result, o, "ha_storage"); err != nil { return nil, fmt.Errorf("error parsing 'ha_storage': %w", err) } } else { if o := list.Filter("ha_backend"); len(o.Items) > 0 { + delete(result.UnusedKeys, "ha_backend") if err := parseHAStorage(result, o, "ha_backend"); err != nil { return nil, fmt.Errorf("error parsing 'ha_backend': %w", err) } @@ -487,6 +495,7 @@ func ParseConfig(d, source string) (*Config, error) { // Parse service discovery if o := list.Filter("service_registration"); len(o.Items) > 0 { + delete(result.UnusedKeys, "service_registration") if err := parseServiceRegistration(result, o, "service_registration"); err != nil { return nil, fmt.Errorf("error parsing 'service_registration': %w", err) } @@ -498,7 +507,7 @@ func ParseConfig(d, source string) (*Config, error) { } // Remove all unused keys from Config that were satisfied by SharedConfig. - result.UnusedKeys = configutil.UnusedFieldDifference(result.UnusedKeys, sharedConfig.UnusedKeys, append(result.FoundKeys, sharedConfig.FoundKeys...)) + result.UnusedKeys = configutil.UnusedFieldDifference(result.UnusedKeys, nil, append(result.FoundKeys, sharedConfig.FoundKeys...)) // Assign file info for _, v := range result.UnusedKeys { for _, p := range v { @@ -850,6 +859,7 @@ func (c *Config) Sanitized() map[string]interface{} { func (c *Config) Prune() { for _, l := range c.Listeners { l.RawConfig = nil + l.UnusedKeys = nil } c.FoundKeys = nil c.UnusedKeys = nil diff --git a/command/server/config_test_helpers.go b/command/server/config_test_helpers.go index 1f3a4dfd5f..fc7fc910a7 100644 --- a/command/server/config_test_helpers.go +++ b/command/server/config_test_helpers.go @@ -468,11 +468,11 @@ func testUnknownFieldValidation(t *testing.T) { expected := []configutil.ConfigError{ { - Problem: "unknown field bad_value found in configuration", + Problem: "unknown or unsupported field bad_value found in configuration", Position: token.Pos{ Filename: "./test-fixtures/config.hcl", - Offset: 603, - Line: 35, + Offset: 583, + Line: 34, Column: 5, }, }, @@ -481,8 +481,12 @@ func testUnknownFieldValidation(t *testing.T) { for _, er1 := range errors { found := false + if strings.Contains(er1.String(), "sentinel") { + //This happens on OSS, and is fine + continue + } for _, ex := range expected { - // Only test the string, pos may change + // TODO: Only test the string, pos may change if ex.Problem == er1.Problem && reflect.DeepEqual(ex.Position, er1.Position) { found = true break diff --git a/command/server/test-fixtures/config.hcl b/command/server/test-fixtures/config.hcl index 271291f1eb..3b4123faea 100644 --- a/command/server/test-fixtures/config.hcl +++ b/command/server/test-fixtures/config.hcl @@ -5,7 +5,6 @@ ui = true listener "tcp" { address = "127.0.0.1:443" - allow_stuff = true } backend "consul" { diff --git a/command/server/test-fixtures/config5.hcl b/command/server/test-fixtures/config5.hcl index acf58a8978..3b3c64c7e0 100644 --- a/command/server/test-fixtures/config5.hcl +++ b/command/server/test-fixtures/config5.hcl @@ -5,7 +5,7 @@ disable_cache = true listener "tcp" { address = "127.0.0.1:443" - allow_stuff = true + allow_stuff = true } backend "consul" { diff --git a/command/server/test-fixtures/config_diagnose_ok.hcl b/command/server/test-fixtures/config_diagnose_ok.hcl index 9287bc2540..c4044c94a6 100644 --- a/command/server/test-fixtures/config_diagnose_ok.hcl +++ b/command/server/test-fixtures/config_diagnose_ok.hcl @@ -37,10 +37,6 @@ telemetry { metrics_prefix = "myprefix" } -sentinel { - additional_enabled_modules = [] -} - max_lease_ttl = "10h" default_lease_ttl = "10h" cluster_name = "testcluster" diff --git a/go.mod b/go.mod index 3e39c7437e..84c7d21d43 100644 --- a/go.mod +++ b/go.mod @@ -74,7 +74,7 @@ require ( github.com/hashicorp/go-syslog v1.0.0 github.com/hashicorp/go-uuid v1.0.2 github.com/hashicorp/golang-lru v0.5.4 - github.com/hashicorp/hcl v1.0.1-vault-2 + github.com/hashicorp/hcl v1.0.1-vault-3 github.com/hashicorp/nomad/api v0.0.0-20191220223628-edc62acd919d github.com/hashicorp/raft v1.3.0 github.com/hashicorp/raft-autopilot v0.1.3 @@ -119,7 +119,7 @@ require ( github.com/mholt/archiver v3.1.1+incompatible github.com/michaelklishin/rabbit-hole v0.0.0-20191008194146-93d9988f0cd5 github.com/miekg/dns v1.1.40 // indirect - github.com/mitchellh/cli v1.1.1 + github.com/mitchellh/cli v1.1.2 github.com/mitchellh/copystructure v1.0.0 github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/go-testing-interface v1.14.0 diff --git a/go.sum b/go.sum index 57ff4f2246..d1b9adb741 100644 --- a/go.sum +++ b/go.sum @@ -111,8 +111,14 @@ github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3 github.com/Jeffail/gabs v1.1.1 h1:V0uzR08Hj22EX8+8QMhyI9sX2hwRu+/RJhJUmnwda/E= github.com/Jeffail/gabs v1.1.1/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= +github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITgsTc= github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= +github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/Microsoft/go-winio v0.4.13/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= @@ -513,6 +519,8 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= @@ -556,8 +564,6 @@ github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= github.com/hashicorp/cap v0.1.0 h1:uBDfu9NDvmotza/mJW6vtQId+VYid9ztlTnDCW6YUWU= github.com/hashicorp/cap v0.1.0/go.mod h1:VfBvK2ULRyqsuqAnjgZl7HJ7/CGMC7ro4H5eXiZuun8= -github.com/hashicorp/consul-template v0.25.2 h1:4xTeLZR/pWX2mESkXSvriOy+eI5vp9z3p7DF5wBlch0= -github.com/hashicorp/consul-template v0.25.2/go.mod h1:5kVbPpbJvxZl3r9aV1Plqur9bszus668jkx6z2umb6o= github.com/hashicorp/consul-template v0.26.0 h1:sLjsLZI4oMUNcvcV376F6OhJHWwWRlZ8hjfyPujEMm4= github.com/hashicorp/consul-template v0.26.0/go.mod h1:HoNM2jHenwY2bqNHn5yYoMSAtHEFhbUDHYf1ZwTBOmg= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= @@ -648,8 +654,8 @@ github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uG github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/hcl v1.0.1-vault-2 h1:j0lTHGBdaU13Pc3GaTCdWjmsT22X98bsHnA+ShzIOtg= -github.com/hashicorp/hcl v1.0.1-vault-2/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= +github.com/hashicorp/hcl v1.0.1-vault-3 h1:V95v5KSTu6DB5huDSKiq4uAfILEuNigK/+qPET6H/Mg= +github.com/hashicorp/hcl v1.0.1-vault-3/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= @@ -732,12 +738,16 @@ github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1 github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= +github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huaweicloud/golangsdk v0.0.0-20200304081349-45ec0797f2a4/go.mod h1:WQBcHRNX9shz3928lWEvstQJtAtYI7ks6XlgtRT9Tcw= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb v0.0.0-20190411212539-d24b7ba8c4c4 h1:3K3KcD4S6/Y2hevi70EzUTNKOS3cryQyhUnkjE6Tz0w= github.com/influxdata/influxdb v0.0.0-20190411212539-d24b7ba8c4c4/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= @@ -858,8 +868,6 @@ github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHX github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-shellwords v1.0.10 h1:Y7Xqm8piKOO3v10Thp7Z36h4FYFjt5xB//6XvOrs2Gw= -github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= @@ -876,6 +884,8 @@ github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceT github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/cli v1.1.1 h1:J64v/xD7Clql+JVKSvkYojLOXu1ibnY9ZjGLwSt/89w= github.com/mitchellh/cli v1.1.1/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/mitchellh/cli v1.1.2 h1:PvH+lL2B7IQ101xQL63Of8yFS2y+aDlsFcsqNc+u/Kw= +github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4= github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -1286,6 +1296,7 @@ golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= diff --git a/internalshared/configutil/config.go b/internalshared/configutil/config.go index 54a02c8780..81d13aed1a 100644 --- a/internalshared/configutil/config.go +++ b/internalshared/configutil/config.go @@ -98,36 +98,42 @@ func ParseConfig(d string) (*SharedConfig, error) { } if o := list.Filter("hsm"); len(o.Items) > 0 { + result.found("hsm", "hsm") if err := parseKMS(&result.Seals, o, "hsm", 2); err != nil { return nil, fmt.Errorf("error parsing 'hsm': %w", err) } } if o := list.Filter("seal"); len(o.Items) > 0 { + result.found("seal", "Seal") if err := parseKMS(&result.Seals, o, "seal", 3); err != nil { return nil, fmt.Errorf("error parsing 'seal': %w", err) } } if o := list.Filter("kms"); len(o.Items) > 0 { + result.found("kms", "Seal") if err := parseKMS(&result.Seals, o, "kms", 3); err != nil { return nil, fmt.Errorf("error parsing 'kms': %w", err) } } if o := list.Filter("entropy"); len(o.Items) > 0 { + result.found("entropy", "Entropy") if err := ParseEntropy(&result, o, "entropy"); err != nil { return nil, fmt.Errorf("error parsing 'entropy': %w", err) } } if o := list.Filter("listener"); len(o.Items) > 0 { + result.found("listener", "Listener") if err := ParseListeners(&result, o); err != nil { return nil, fmt.Errorf("error parsing 'listener': %w", err) } } if o := list.Filter("telemetry"); len(o.Items) > 0 { + result.found("telemetry", "Telemetry") if err := parseTelemetry(&result, o); err != nil { return nil, fmt.Errorf("error parsing 'telemetry': %w", err) } @@ -230,3 +236,8 @@ func (c *SharedConfig) Sanitized() map[string]interface{} { return result } + +func (c *SharedConfig) found(s, k string) { + delete(c.UnusedKeys, s) + c.FoundKeys = append(c.FoundKeys, k) +} diff --git a/internalshared/configutil/lint.go b/internalshared/configutil/lint.go index 943c5287f8..1e773312e9 100644 --- a/internalshared/configutil/lint.go +++ b/internalshared/configutil/lint.go @@ -29,7 +29,7 @@ func ValidateUnusedFields(unusedKeyPositions UnusedKeyMap, sourceFilePath string } var errors []ConfigError for field, positions := range unusedKeyPositions { - problem := fmt.Sprintf("unknown field %s found in configuration", field) + problem := fmt.Sprintf("unknown or unsupported field %s found in configuration", field) for _, pos := range positions { if pos.Filename == "" && sourceFilePath != "" { pos.Filename = sourceFilePath @@ -48,9 +48,6 @@ func UnusedFieldDifference(a, b UnusedKeyMap, foundKeys []string) UnusedKeyMap { if a == nil { return nil } - if b == nil { - return a - } res := make(UnusedKeyMap) for k, v := range a { if _, ok := b[k]; !ok && !strutil.StrListContainsCaseInsensitive(foundKeys, govalidator.UnderscoreToCamelCase(k)) { diff --git a/internalshared/configutil/listener.go b/internalshared/configutil/listener.go index cbb1194e33..21c351e20e 100644 --- a/internalshared/configutil/listener.go +++ b/internalshared/configutil/listener.go @@ -17,18 +17,20 @@ import ( ) type ListenerTelemetry struct { - UnauthenticatedMetricsAccess bool `hcl:"-"` - UnauthenticatedMetricsAccessRaw interface{} `hcl:"unauthenticated_metrics_access"` + UnusedKeys UnusedKeyMap `hcl:",unusedKeyPositions"` + UnauthenticatedMetricsAccess bool `hcl:"-"` + UnauthenticatedMetricsAccessRaw interface{} `hcl:"unauthenticated_metrics_access,alias:UnauthenticatedMetricsAccess"` } type ListenerProfiling struct { - UnauthenticatedPProfAccess bool `hcl:"-"` - UnauthenticatedPProfAccessRaw interface{} `hcl:"unauthenticated_pprof_access"` + UnusedKeys UnusedKeyMap `hcl:",unusedKeyPositions"` + UnauthenticatedPProfAccess bool `hcl:"-"` + UnauthenticatedPProfAccessRaw interface{} `hcl:"unauthenticated_pprof_access,alias:UnauthenticatedPProfAccessRaw"` } // Listener is the listener configuration for the server. type Listener struct { - UnusedKeys []string `hcl:",unusedKeys"` + UnusedKeys UnusedKeyMap `hcl:",unusedKeyPositions"` RawConfig map[string]interface{} Type string @@ -71,16 +73,16 @@ type Listener struct { ProxyProtocolBehavior string `hcl:"proxy_protocol_behavior"` ProxyProtocolAuthorizedAddrs []*sockaddr.SockAddrMarshaler `hcl:"-"` - ProxyProtocolAuthorizedAddrsRaw interface{} `hcl:"proxy_protocol_authorized_addrs"` + ProxyProtocolAuthorizedAddrsRaw interface{} `hcl:"proxy_protocol_authorized_addrs,alias:ProxyProtocolAuthorizedAddrs"` XForwardedForAuthorizedAddrs []*sockaddr.SockAddrMarshaler `hcl:"-"` - XForwardedForAuthorizedAddrsRaw interface{} `hcl:"x_forwarded_for_authorized_addrs"` + XForwardedForAuthorizedAddrsRaw interface{} `hcl:"x_forwarded_for_authorized_addrs,alias:XForwardedForAuthorizedAddrs"` XForwardedForHopSkips int64 `hcl:"-"` - XForwardedForHopSkipsRaw interface{} `hcl:"x_forwarded_for_hop_skips"` + XForwardedForHopSkipsRaw interface{} `hcl:"x_forwarded_for_hop_skips,alias:XForwardedForHopSkips"` XForwardedForRejectNotPresent bool `hcl:"-"` - XForwardedForRejectNotPresentRaw interface{} `hcl:"x_forwarded_for_reject_not_present"` + XForwardedForRejectNotPresentRaw interface{} `hcl:"x_forwarded_for_reject_not_present,alias:XForwardedForRejectNotPresent"` XForwardedForRejectNotAuthorized bool `hcl:"-"` - XForwardedForRejectNotAuthorizedRaw interface{} `hcl:"x_forwarded_for_reject_not_authorized"` + XForwardedForRejectNotAuthorizedRaw interface{} `hcl:"x_forwarded_for_reject_not_authorized,alias:XForwardedForRejectNotAuthorized"` SocketMode string `hcl:"socket_mode"` SocketUser string `hcl:"socket_user"` @@ -96,13 +98,18 @@ type Listener struct { CorsEnabled bool `hcl:"-"` CorsAllowedOrigins []string `hcl:"cors_allowed_origins"` CorsAllowedHeaders []string `hcl:"-"` - CorsAllowedHeadersRaw []string `hcl:"cors_allowed_headers"` + CorsAllowedHeadersRaw []string `hcl:"cors_allowed_headers,alias:cors_allowed_headers"` } func (l *Listener) GoString() string { return fmt.Sprintf("*%#v", *l) } +func (l *Listener) Validate(path string) []ConfigError { + results := append(ValidateUnusedFields(l.UnusedKeys, path), ValidateUnusedFields(l.Telemetry.UnusedKeys, path)...) + return append(results, ValidateUnusedFields(l.Profiling.UnusedKeys, path)...) +} + func ParseListeners(result *SharedConfig, list *ast.ObjectList) error { var err error result.Listeners = make([]*Listener, 0, len(list.Items)) diff --git a/internalshared/configutil/telemetry.go b/internalshared/configutil/telemetry.go index ab5254c058..3fd42aa609 100644 --- a/internalshared/configutil/telemetry.go +++ b/internalshared/configutil/telemetry.go @@ -41,7 +41,7 @@ type Telemetry struct { EnableHostnameLabel bool `hcl:"enable_hostname_label"` MetricsPrefix string `hcl:"metrics_prefix"` UsageGaugePeriod time.Duration - UsageGaugePeriodRaw interface{} `hcl:"usage_gauge_period"` + UsageGaugePeriodRaw interface{} `hcl:"usage_gauge_period,alias:UsageGaugePeriod"` MaximumGaugeCardinality int `hcl:"maximum_gauge_cardinality"` diff --git a/vault/diagnose/output.go b/vault/diagnose/output.go index 2a11cef200..963fece8ab 100644 --- a/vault/diagnose/output.go +++ b/vault/diagnose/output.go @@ -337,17 +337,18 @@ func (r *Result) write(sb *strings.Builder, depth int, limit int) { } warnings := r.Warnings if r.Message == "" && len(warnings) > 0 { - prelude = status_warn + r.Name + ": " + warnings[0] - warnings = warnings[1:] + prelude = status_warn + r.Name + ": " + if len(warnings) == 1 { + prelude = prelude + warnings[0] + warnings = warnings[1:] + } } writeWrapped(sb, prelude, depth+1, limit) for _, w := range warnings { sb.WriteRune('\n') - indent(sb, depth) + indent(sb, depth+1) sb.WriteString(status_warn) - sb.WriteString(r.Name) - sb.WriteString(": ") - writeWrapped(sb, w, depth+1, limit) + writeWrapped(sb, w, depth+2, limit) } if r.Advice != "" {