Skip to content

Commit

Permalink
Expose unknown fields and duplicate sections as diagnose warnings (ha…
Browse files Browse the repository at this point in the history
…shicorp#11455)

* Expose unknown fields and duplicate sections as diagnose warnings

* section counts not needed, already handled

* Address PR feedback

* Prune more of the new fields before tests call deep.Equals

* Update go.mod
  • Loading branch information
sgmiller authored May 4, 2021
1 parent 03c9933 commit 2feeb39
Show file tree
Hide file tree
Showing 19 changed files with 300 additions and 56 deletions.
22 changes: 22 additions & 0 deletions command/agent/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,20 @@ type Config struct {
Templates []*ctconfig.TemplateConfig `hcl:"templates"`
}

func (c *Config) Prune() {
for _, l := range c.Listeners {
l.RawConfig = nil
}
c.FoundKeys = nil
c.UnusedKeys = nil
c.SharedConfig.FoundKeys = nil
c.SharedConfig.UnusedKeys = nil
if c.Telemetry != nil {
c.Telemetry.FoundKeys = nil
c.Telemetry.UnusedKeys = nil
}
}

type Retry struct {
NumRetries int `hcl:"num_retries"`
}
Expand Down Expand Up @@ -131,6 +145,14 @@ func LoadConfig(path string) (*Config, error) {
return nil, err
}

// Attribute
ast.Walk(obj, func(n ast.Node) (ast.Node, bool) {
if k, ok := n.(*ast.ObjectKey); ok {
k.Token.Pos.Filename = path
}
return n, true
})

// Start building the result
result := NewConfig()
if err := hcl.DecodeObject(result, obj); err != nil {
Expand Down
34 changes: 16 additions & 18 deletions command/agent/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,7 @@ func TestLoadConfigFile_AgentCache(t *testing.T) {
},
}

config.Listeners[0].RawConfig = nil
config.Listeners[1].RawConfig = nil
config.Listeners[2].RawConfig = nil
config.Prune()
if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
Expand All @@ -101,9 +99,7 @@ func TestLoadConfigFile_AgentCache(t *testing.T) {
}
expected.Vault.TLSSkipVerifyRaw = interface{}(true)

config.Listeners[0].RawConfig = nil
config.Listeners[1].RawConfig = nil
config.Listeners[2].RawConfig = nil
config.Prune()
if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
Expand Down Expand Up @@ -168,6 +164,7 @@ func TestLoadConfigFile(t *testing.T) {
},
}

config.Prune()
if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
Expand All @@ -177,6 +174,7 @@ func TestLoadConfigFile(t *testing.T) {
t.Fatalf("err: %s", err)
}

config.Prune()
if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
Expand Down Expand Up @@ -218,6 +216,7 @@ func TestLoadConfigFile_Method_Wrapping(t *testing.T) {
},
}

config.Prune()
if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
Expand Down Expand Up @@ -248,7 +247,7 @@ func TestLoadConfigFile_AgentCache_NoAutoAuth(t *testing.T) {
},
}

config.Listeners[0].RawConfig = nil
config.Prune()
if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
Expand Down Expand Up @@ -341,7 +340,7 @@ func TestLoadConfigFile_AgentCache_AutoAuth_NoSink(t *testing.T) {
},
}

config.Listeners[0].RawConfig = nil
config.Prune()
if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
Expand Down Expand Up @@ -385,7 +384,7 @@ func TestLoadConfigFile_AgentCache_AutoAuth_Force(t *testing.T) {
},
}

config.Listeners[0].RawConfig = nil
config.Prune()
if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
Expand Down Expand Up @@ -429,7 +428,7 @@ func TestLoadConfigFile_AgentCache_AutoAuth_True(t *testing.T) {
},
}

config.Listeners[0].RawConfig = nil
config.Prune()
if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
Expand Down Expand Up @@ -484,7 +483,7 @@ func TestLoadConfigFile_AgentCache_AutoAuth_False(t *testing.T) {
},
}

config.Listeners[0].RawConfig = nil
config.Prune()
if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
Expand Down Expand Up @@ -523,12 +522,7 @@ func TestLoadConfigFile_AgentCache_Persist(t *testing.T) {
},
}

config.Listeners[0].RawConfig = nil
if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}

config.Listeners[0].RawConfig = nil
config.Prune()
if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
Expand Down Expand Up @@ -644,6 +638,7 @@ func TestLoadConfigFile_Template(t *testing.T) {
Templates: tc.expectedTemplates,
}

config.Prune()
if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
Expand Down Expand Up @@ -744,6 +739,7 @@ func TestLoadConfigFile_Template_NoSinks(t *testing.T) {
},
}

config.Prune()
if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
Expand Down Expand Up @@ -790,6 +786,7 @@ func TestLoadConfigFile_Vault_Retry(t *testing.T) {
},
}

config.Prune()
if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
Expand Down Expand Up @@ -834,6 +831,7 @@ func TestLoadConfigFile_Vault_Retry_Empty(t *testing.T) {
},
}

config.Prune()
if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
Expand Down Expand Up @@ -867,7 +865,7 @@ func TestLoadConfigFile_EnforceConsistency(t *testing.T) {
},
}

config.Listeners[0].RawConfig = nil
config.Prune()
if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
Expand Down
5 changes: 5 additions & 0 deletions command/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,11 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
BaseCommand: getBaseCommand(),
}, nil
},
"operator diagnose": func() (cli.Command, error) {
return &OperatorDiagnoseCommand{
BaseCommand: getBaseCommand(),
}, nil
},
"operator generate-root": func() (cli.Command, error) {
return &OperatorGenerateRootCommand{
BaseCommand: getBaseCommand(),
Expand Down
60 changes: 49 additions & 11 deletions command/server/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/hashicorp/hcl/hcl/token"
"io"
"io/ioutil"
"os"
Expand All @@ -22,6 +23,7 @@ import (

// Config is the configuration for the vault server.
type Config struct {
UnusedKeys map[string][]token.Pos `hcl:",unusedKeyPositions"`
entConfig

*configutil.SharedConfig `hcl:"-"`
Expand All @@ -41,33 +43,33 @@ type Config struct {
EnableUIRaw interface{} `hcl:"ui"`

MaxLeaseTTL time.Duration `hcl:"-"`
MaxLeaseTTLRaw interface{} `hcl:"max_lease_ttl"`
MaxLeaseTTLRaw interface{} `hcl:"max_lease_ttl,alias:MaxLeaseTTL"`
DefaultLeaseTTL time.Duration `hcl:"-"`
DefaultLeaseTTLRaw interface{} `hcl:"default_lease_ttl"`
DefaultLeaseTTLRaw interface{} `hcl:"default_lease_ttl,alias:DefaultLeaseTTL"`

ClusterCipherSuites string `hcl:"cluster_cipher_suites"`

PluginDirectory string `hcl:"plugin_directory"`

EnableRawEndpoint bool `hcl:"-"`
EnableRawEndpointRaw interface{} `hcl:"raw_storage_endpoint"`
EnableRawEndpointRaw interface{} `hcl:"raw_storage_endpoint,alias:EnableRawEndpoint"`

APIAddr string `hcl:"api_addr"`
ClusterAddr string `hcl:"cluster_addr"`
DisableClustering bool `hcl:"-"`
DisableClusteringRaw interface{} `hcl:"disable_clustering"`
DisableClusteringRaw interface{} `hcl:"disable_clustering,alias:DisableClustering"`

DisablePerformanceStandby bool `hcl:"-"`
DisablePerformanceStandbyRaw interface{} `hcl:"disable_performance_standby"`
DisablePerformanceStandbyRaw interface{} `hcl:"disable_performance_standby,alias:DisablePerformanceStandby"`

DisableSealWrap bool `hcl:"-"`
DisableSealWrapRaw interface{} `hcl:"disable_sealwrap"`
DisableSealWrapRaw interface{} `hcl:"disable_sealwrap,alias:DisableSealWrap"`

DisableIndexing bool `hcl:"-"`
DisableIndexingRaw interface{} `hcl:"disable_indexing"`
DisableIndexingRaw interface{} `hcl:"disable_indexing,alias:DisableIndexing"`

DisableSentinelTrace bool `hcl:"-"`
DisableSentinelTraceRaw interface{} `hcl:"disable_sentinel_trace"`
DisableSentinelTraceRaw interface{} `hcl:"disable_sentinel_trace,alias:DisableSentinelTrace"`

EnableResponseHeaderHostname bool `hcl:"-"`
EnableResponseHeaderHostnameRaw interface{} `hcl:"enable_response_header_hostname"`
Expand All @@ -76,6 +78,18 @@ type Config struct {
EnableResponseHeaderRaftNodeIDRaw interface{} `hcl:"enable_response_header_raft_node_id"`
}

const (
sectionSeal = "Seal"
)

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)...)
}
return results
}

// DevConfig is a Config that is used for dev mode of Vault.
func DevConfig(storageType string) (*Config, error) {
hclStr := `
Expand All @@ -102,7 +116,7 @@ ui = true
`

hclStr = fmt.Sprintf(hclStr, storageType)
parsed, err := ParseConfig(hclStr)
parsed, err := ParseConfig(hclStr, "")
if err != nil {
return nil, fmt.Errorf("error parsing dev config: %w", err)
}
Expand All @@ -111,6 +125,7 @@ ui = true

// Storage is the underlying storage configuration for the server.
type Storage struct {
UnusedKeys []string `hcl:",unusedKeys"`
Type string
RedirectAddr string
ClusterAddr string
Expand Down Expand Up @@ -330,15 +345,15 @@ func LoadConfigFile(path string) (*Config, error) {
return nil, err
}

conf, err := ParseConfig(string(d))
conf, err := ParseConfig(string(d), path)
if err != nil {
return nil, err
}

return conf, nil
}

func ParseConfig(d string) (*Config, error) {
func ParseConfig(d, source string) (*Config, error) {
// Parse!
obj, err := hcl.Parse(d)
if err != nil {
Expand Down Expand Up @@ -476,6 +491,15 @@ func ParseConfig(d string) (*Config, error) {
return nil, errwrap.Wrapf("error parsing enterprise config: {{err}}", err)
}

// Remove all unused keys from Config that were satisfied by SharedConfig.
result.UnusedKeys = configutil.UnusedFieldDifference(result.UnusedKeys, sharedConfig.UnusedKeys, append(result.FoundKeys, sharedConfig.FoundKeys...))
// Assign file info
for _, v := range result.UnusedKeys {
for _, p := range v {
p.Filename = source
}
}

return result, nil
}

Expand Down Expand Up @@ -816,3 +840,17 @@ func (c *Config) Sanitized() map[string]interface{} {

return result
}

func (c *Config) Prune() {
for _, l := range c.Listeners {
l.RawConfig = nil
}
c.FoundKeys = nil
c.UnusedKeys = nil
c.SharedConfig.FoundKeys = nil
c.SharedConfig.UnusedKeys = nil
if c.Telemetry != nil {
c.Telemetry.FoundKeys = nil
c.Telemetry.UnusedKeys = nil
}
}
4 changes: 4 additions & 0 deletions command/server/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,7 @@ func TestConfigRaftRetryJoin(t *testing.T) {
func TestParseSeals(t *testing.T) {
testParseSeals(t)
}

func TestUnknownFieldValidation(t *testing.T) {
testUnknownFieldValidation(t)
}
Loading

0 comments on commit 2feeb39

Please sign in to comment.