diff --git a/changelog/18403.txt b/changelog/18403.txt new file mode 100644 index 000000000..458f6c926 --- /dev/null +++ b/changelog/18403.txt @@ -0,0 +1,3 @@ +```release-note:improvement +agent/config: Allow config directories to be specified with -config, and allow multiple -configs to be supplied. +``` diff --git a/command/agent.go b/command/agent.go index 0edd96eb9..9a7aa1192 100644 --- a/command/agent.go +++ b/command/agent.go @@ -16,6 +16,8 @@ import ( "sync" "time" + ctconfig "github.com/hashicorp/consul-template/config" + "github.com/hashicorp/vault/command/agent/sink/inmem" systemd "github.com/coreos/go-systemd/daemon" @@ -186,32 +188,30 @@ func (c *AgentCommand) Run(args []string) int { } // Validation - if len(c.flagConfigs) != 1 { - c.UI.Error("Must specify exactly one config path using -config") + if len(c.flagConfigs) < 1 { + c.UI.Error("Must specify exactly at least one config path using -config") return 1 } - // Load the configuration file - config, err := agentConfig.LoadConfig(c.flagConfigs[0]) + config := agentConfig.NewConfig() + + for _, configPath := range c.flagConfigs { + configFromPath, err := agentConfig.LoadConfig(configPath) + if err != nil { + c.UI.Error(fmt.Sprintf("Error loading configuration from %s: %s", configPath, err)) + return 1 + } + config = config.Merge(configFromPath) + } + + err := config.ValidateConfig() if err != nil { - c.UI.Error(fmt.Sprintf("Error loading configuration from %s: %s", c.flagConfigs[0], err)) + c.UI.Error(fmt.Sprintf("Error loading configuration: %s", err)) return 1 } - // Ensure at least one config was found. - if config == nil { - c.UI.Output(wrapAtLength( - "No configuration read. Please provide the configuration with the " + - "-config flag.")) - return 1 - } - - if config.AutoAuth == nil && config.Cache == nil { - c.UI.Error("No auto_auth or cache block found in config file") - return 1 - } if config.AutoAuth == nil { - c.UI.Info("No auto_auth block found in config file, not starting automatic authentication feature") + c.UI.Info("No auto_auth block found in config, not starting automatic authentication feature") } c.updateConfig(f, config) @@ -417,7 +417,12 @@ func (c *AgentCommand) Run(args []string) int { // confuse the issue of retries for auth failures which have their own // config and are handled a bit differently. if os.Getenv(api.EnvVaultMaxRetries) == "" { - client.SetMaxRetries(config.Vault.Retry.NumRetries) + client.SetMaxRetries(ctconfig.DefaultRetryAttempts) + if config.Vault != nil { + if config.Vault.Retry != nil { + client.SetMaxRetries(config.Vault.Retry.NumRetries) + } + } } enforceConsistency := cache.EnforceConsistencyNever @@ -977,6 +982,10 @@ func (c *AgentCommand) Run(args []string) int { // on the precedence (env var overrides file config, cli overrides env var). // It mutates the config object supplied. func (c *AgentCommand) updateConfig(f *FlagSets, config *agentConfig.Config) { + if config.Vault == nil { + config.Vault = &agentConfig.Vault{} + } + f.updateLogConfig(config.SharedConfig) f.Visit(func(fl *flag.Flag) { diff --git a/command/agent/config/config.go b/command/agent/config/config.go index 820a37c8b..230a2dddf 100644 --- a/command/agent/config/config.go +++ b/command/agent/config/config.go @@ -4,8 +4,10 @@ import ( "context" "errors" "fmt" + "io" "net" "os" + "path/filepath" "strings" "time" @@ -169,14 +171,253 @@ func NewConfig() *Config { } } +// Merge merges two Agent configurations. +func (c *Config) Merge(c2 *Config) *Config { + if c2 == nil { + return c + } + + result := NewConfig() + + result.SharedConfig = c.SharedConfig + if c2.SharedConfig != nil { + result.SharedConfig = c.SharedConfig.Merge(c2.SharedConfig) + } + + result.AutoAuth = c.AutoAuth + if c2.AutoAuth != nil { + result.AutoAuth = c2.AutoAuth + } + + result.Cache = c.Cache + if c2.Cache != nil { + result.Cache = c2.Cache + } + + result.APIProxy = c.APIProxy + if c2.APIProxy != nil { + result.APIProxy = c2.APIProxy + } + + result.DisableMlock = c.DisableMlock + if c2.DisableMlock { + result.DisableMlock = c2.DisableMlock + } + + // For these, ignore the non-specific one and overwrite them all + result.DisableIdleConnsAutoAuth = c.DisableIdleConnsAutoAuth + if c2.DisableIdleConnsAutoAuth { + result.DisableIdleConnsAutoAuth = c2.DisableIdleConnsAutoAuth + } + + result.DisableIdleConnsAPIProxy = c.DisableIdleConnsAPIProxy + if c2.DisableIdleConnsAPIProxy { + result.DisableIdleConnsAPIProxy = c2.DisableIdleConnsAPIProxy + } + + result.DisableIdleConnsTemplating = c.DisableIdleConnsTemplating + if c2.DisableIdleConnsTemplating { + result.DisableIdleConnsTemplating = c2.DisableIdleConnsTemplating + } + + result.DisableKeepAlivesAutoAuth = c.DisableKeepAlivesAutoAuth + if c2.DisableKeepAlivesAutoAuth { + result.DisableKeepAlivesAutoAuth = c2.DisableKeepAlivesAutoAuth + } + + result.DisableKeepAlivesAPIProxy = c.DisableKeepAlivesAPIProxy + if c2.DisableKeepAlivesAPIProxy { + result.DisableKeepAlivesAPIProxy = c2.DisableKeepAlivesAPIProxy + } + + result.DisableKeepAlivesTemplating = c.DisableKeepAlivesTemplating + if c2.DisableKeepAlivesTemplating { + result.DisableKeepAlivesTemplating = c2.DisableKeepAlivesTemplating + } + + result.TemplateConfig = c.TemplateConfig + if c2.TemplateConfig != nil { + result.TemplateConfig = c2.TemplateConfig + } + + for _, l := range c.Templates { + result.Templates = append(result.Templates, l) + } + for _, l := range c2.Templates { + result.Templates = append(result.Templates, l) + } + + result.ExitAfterAuth = c.ExitAfterAuth + if c2.ExitAfterAuth { + result.ExitAfterAuth = c2.ExitAfterAuth + } + + result.Vault = c.Vault + if c2.Vault != nil { + result.Vault = c2.Vault + } + + result.PidFile = c.PidFile + if c2.PidFile != "" { + result.PidFile = c2.PidFile + } + + return result +} + +// ValidateConfig validates an Agent configuration after it has been fully merged together, to +// ensure that required combinations of configs are there +func (c *Config) ValidateConfig() error { + if c.APIProxy != nil && c.Cache != nil { + if c.Cache.UseAutoAuthTokenRaw != nil { + if c.APIProxy.UseAutoAuthTokenRaw != nil { + return fmt.Errorf("use_auto_auth_token defined in both api_proxy and cache config. Please remove this configuration from the cache block") + } else { + c.APIProxy.ForceAutoAuthToken = c.Cache.ForceAutoAuthToken + } + } + } + + if c.Cache != nil { + if len(c.Listeners) < 1 && len(c.Templates) < 1 { + return fmt.Errorf("enabling the cache requires at least 1 template or 1 listener to be defined") + } + + if c.Cache.UseAutoAuthToken { + if c.AutoAuth == nil { + return fmt.Errorf("cache.use_auto_auth_token is true but auto_auth not configured") + } + if c.AutoAuth != nil && c.AutoAuth.Method != nil && c.AutoAuth.Method.WrapTTL > 0 { + return fmt.Errorf("cache.use_auto_auth_token is true and auto_auth uses wrapping") + } + } + } + + if c.APIProxy != nil { + if len(c.Listeners) < 1 { + return fmt.Errorf("configuring the api_proxy requires at least 1 listener to be defined") + } + + if c.APIProxy.UseAutoAuthToken { + if c.AutoAuth == nil { + return fmt.Errorf("api_proxy.use_auto_auth_token is true but auto_auth not configured") + } + if c.AutoAuth != nil && c.AutoAuth.Method != nil && c.AutoAuth.Method.WrapTTL > 0 { + return fmt.Errorf("api_proxy.use_auto_auth_token is true and auto_auth uses wrapping") + } + } + } + + if c.AutoAuth != nil { + if len(c.AutoAuth.Sinks) == 0 && + (c.APIProxy == nil || !c.APIProxy.UseAutoAuthToken) && + len(c.Templates) == 0 { + return fmt.Errorf("auto_auth requires at least one sink or at least one template or api_proxy.use_auto_auth_token=true") + } + } + + if c.AutoAuth == nil && c.Cache == nil && len(c.Listeners) == 0 { + return fmt.Errorf("no auto_auth, cache, or listener block found in config") + } + + return nil +} + // LoadConfig loads the configuration at the given path, regardless if -// its a file or directory. +// it's a file or directory. func LoadConfig(path string) (*Config, error) { fi, err := os.Stat(path) if err != nil { return nil, err } + if fi.IsDir() { + return LoadConfigDir(path) + } + return LoadConfigFile(path) +} + +// LoadConfigDir loads the configuration at the given path if it's a directory +func LoadConfigDir(dir string) (*Config, error) { + f, err := os.Open(dir) + if err != nil { + return nil, err + } + defer f.Close() + + fi, err := f.Stat() + if err != nil { + return nil, err + } + if !fi.IsDir() { + return nil, fmt.Errorf("configuration path must be a directory: %q", dir) + } + + var files []string + err = nil + for err != io.EOF { + var fis []os.FileInfo + fis, err = f.Readdir(128) + if err != nil && err != io.EOF { + return nil, err + } + + for _, fi := range fis { + // Ignore directories + if fi.IsDir() { + continue + } + + // Only care about files that are valid to load. + name := fi.Name() + skip := true + if strings.HasSuffix(name, ".hcl") { + skip = false + } else if strings.HasSuffix(name, ".json") { + skip = false + } + if skip || isTemporaryFile(name) { + continue + } + + path := filepath.Join(dir, name) + files = append(files, path) + } + } + + result := NewConfig() + for _, f := range files { + config, err := LoadConfigFile(f) + if err != nil { + return nil, fmt.Errorf("error loading %q: %w", f, err) + } + + if result == nil { + result = config + } else { + result = result.Merge(config) + } + } + + return result, nil +} + +// isTemporaryFile returns true or false depending on whether the +// provided file name is a temporary file for the following editors: +// emacs or vim. +func isTemporaryFile(name string) bool { + return strings.HasSuffix(name, "~") || // vim + strings.HasPrefix(name, ".#") || // emacs + (strings.HasPrefix(name, "#") && strings.HasSuffix(name, "#")) // emacs +} + +// LoadConfigFile loads the configuration at the given path if it's a file +func LoadConfigFile(path string) (*Config, error) { + fi, err := os.Stat(path) + if err != nil { + return nil, err + } + if fi.IsDir() { return nil, fmt.Errorf("location is a directory, not a file") } @@ -236,16 +477,6 @@ func LoadConfig(path string) (*Config, error) { return nil, fmt.Errorf("error parsing 'api_proxy':%w", err) } - if result.APIProxy != nil && result.Cache != nil { - if result.Cache.UseAutoAuthTokenRaw != nil { - if result.APIProxy.UseAutoAuthTokenRaw != nil { - return nil, fmt.Errorf("use_auto_auth_token defined in both api_proxy and cache config. Please remove this configuration from the cache block") - } else { - result.APIProxy.ForceAutoAuthToken = result.Cache.ForceAutoAuthToken - } - } - } - if err := parseTemplateConfig(result, list); err != nil { return nil, fmt.Errorf("error parsing 'template_config': %w", err) } @@ -254,69 +485,29 @@ func LoadConfig(path string) (*Config, error) { return nil, fmt.Errorf("error parsing 'template': %w", err) } - if result.Cache != nil && result.APIProxy == nil && len(result.Listeners) > 0 { + if result.Cache != nil && result.APIProxy == nil { result.APIProxy = &APIProxy{ UseAutoAuthToken: result.Cache.UseAutoAuthToken, ForceAutoAuthToken: result.Cache.ForceAutoAuthToken, } } - if result.Cache != nil { - if len(result.Listeners) < 1 && len(result.Templates) < 1 { - return nil, fmt.Errorf("enabling the cache requires at least 1 template or 1 listener to be defined") - } - - if result.Cache.UseAutoAuthToken { - if result.AutoAuth == nil { - return nil, fmt.Errorf("cache.use_auto_auth_token is true but auto_auth not configured") - } - if result.AutoAuth != nil && result.AutoAuth.Method != nil && result.AutoAuth.Method.WrapTTL > 0 { - return nil, fmt.Errorf("cache.use_auto_auth_token is true and auto_auth uses wrapping") - } - } - } - - if result.APIProxy != nil { - if len(result.Listeners) < 1 { - return nil, fmt.Errorf("configuring the api_proxy requires at least 1 listener to be defined") - } - - if result.APIProxy.UseAutoAuthToken { - if result.AutoAuth == nil { - return nil, fmt.Errorf("api_proxy.use_auto_auth_token is true but auto_auth not configured") - } - if result.AutoAuth != nil && result.AutoAuth.Method != nil && result.AutoAuth.Method.WrapTTL > 0 { - return nil, fmt.Errorf("api_proxy.use_auto_auth_token is true and auto_auth uses wrapping") - } - } - } - - if result.AutoAuth != nil { - if len(result.AutoAuth.Sinks) == 0 && - (result.APIProxy == nil || !result.APIProxy.UseAutoAuthToken) && - len(result.Templates) == 0 { - return nil, fmt.Errorf("auto_auth requires at least one sink or at least one template or api_proxy.use_auto_auth_token=true") - } - } - err = parseVault(result, list) if err != nil { return nil, fmt.Errorf("error parsing 'vault':%w", err) } - if result.Vault == nil { - result.Vault = &Vault{} - } - - // Set defaults - if result.Vault.Retry == nil { - result.Vault.Retry = &Retry{} - } - switch result.Vault.Retry.NumRetries { - case 0: - result.Vault.Retry.NumRetries = ctconfig.DefaultRetryAttempts - case -1: - result.Vault.Retry.NumRetries = 0 + if result.Vault != nil { + // Set defaults + if result.Vault.Retry == nil { + result.Vault.Retry = &Retry{} + } + switch result.Vault.Retry.NumRetries { + case 0: + result.Vault.Retry.NumRetries = ctconfig.DefaultRetryAttempts + case -1: + result.Vault.Retry.NumRetries = 0 + } } if disableIdleConnsEnv := os.Getenv(DisableIdleConnsEnv); disableIdleConnsEnv != "" { diff --git a/command/agent/config/config_test.go b/command/agent/config/config_test.go index ba601e56b..e8cdc2473 100644 --- a/command/agent/config/config_test.go +++ b/command/agent/config/config_test.go @@ -12,7 +12,7 @@ import ( ) func TestLoadConfigFile_AgentCache(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-cache.hcl") + config, err := LoadConfigFile("./test-fixtures/config-cache.hcl") if err != nil { t.Fatal(err) } @@ -104,7 +104,7 @@ func TestLoadConfigFile_AgentCache(t *testing.T) { t.Fatal(diff) } - config, err = LoadConfig("./test-fixtures/config-cache-embedded-type.hcl") + config, err = LoadConfigFile("./test-fixtures/config-cache-embedded-type.hcl") if err != nil { t.Fatal(err) } @@ -116,8 +116,236 @@ func TestLoadConfigFile_AgentCache(t *testing.T) { } } +func TestLoadConfigDir_AgentCache(t *testing.T) { + config, err := LoadConfig("./test-fixtures/config-dir-cache/") + if err != nil { + t.Fatal(err) + } + + expected := &Config{ + SharedConfig: &configutil.SharedConfig{ + PidFile: "./pidfile", + Listeners: []*configutil.Listener{ + { + Type: "unix", + Address: "/path/to/socket", + TLSDisable: true, + SocketMode: "configmode", + SocketUser: "configuser", + SocketGroup: "configgroup", + }, + { + Type: "tcp", + Address: "127.0.0.1:8300", + TLSDisable: true, + }, + { + Type: "tcp", + Address: "127.0.0.1:3000", + Role: "metrics_only", + TLSDisable: true, + }, + { + Type: "tcp", + Role: "default", + Address: "127.0.0.1:8400", + TLSKeyFile: "/path/to/cakey.pem", + TLSCertFile: "/path/to/cacert.pem", + }, + }, + }, + AutoAuth: &AutoAuth{ + Method: &Method{ + Type: "aws", + MountPath: "auth/aws", + Config: map[string]interface{}{ + "role": "foobar", + }, + }, + Sinks: []*Sink{ + { + Type: "file", + DHType: "curve25519", + DHPath: "/tmp/file-foo-dhpath", + AAD: "foobar", + Config: map[string]interface{}{ + "path": "/tmp/file-foo", + }, + }, + }, + }, + APIProxy: &APIProxy{ + UseAutoAuthToken: true, + ForceAutoAuthToken: false, + }, + Cache: &Cache{ + UseAutoAuthToken: true, + UseAutoAuthTokenRaw: true, + ForceAutoAuthToken: false, + Persist: &Persist{ + Type: "kubernetes", + Path: "/vault/agent-cache/", + KeepAfterImport: true, + ExitOnErr: true, + ServiceAccountTokenFile: "/tmp/serviceaccount/token", + }, + }, + Vault: &Vault{ + Address: "http://127.0.0.1:1111", + CACert: "config_ca_cert", + CAPath: "config_ca_path", + TLSSkipVerifyRaw: interface{}("true"), + TLSSkipVerify: true, + ClientCert: "config_client_cert", + ClientKey: "config_client_key", + Retry: &Retry{ + NumRetries: 12, + }, + }, + } + + config.Prune() + if diff := deep.Equal(config, expected); diff != nil { + t.Fatal(diff) + } + + config, err = LoadConfigFile("./test-fixtures/config-dir-cache/config-cache1.hcl") + if err != nil { + t.Fatal(err) + } + config2, err := LoadConfigFile("./test-fixtures/config-dir-cache/config-cache2.hcl") + + mergedConfig := config.Merge(config2) + + mergedConfig.Prune() + if diff := deep.Equal(mergedConfig, expected); diff != nil { + t.Fatal(diff) + } +} + +func TestLoadConfigDir_AutoAuthAndListener(t *testing.T) { + config, err := LoadConfig("./test-fixtures/config-dir-auto-auth-and-listener/") + if err != nil { + t.Fatal(err) + } + + expected := &Config{ + SharedConfig: &configutil.SharedConfig{ + PidFile: "./pidfile", + Listeners: []*configutil.Listener{ + { + Type: "tcp", + Address: "127.0.0.1:8300", + TLSDisable: true, + }, + }, + }, + AutoAuth: &AutoAuth{ + Method: &Method{ + Type: "aws", + MountPath: "auth/aws", + Config: map[string]interface{}{ + "role": "foobar", + }, + }, + Sinks: []*Sink{ + { + Type: "file", + DHType: "curve25519", + DHPath: "/tmp/file-foo-dhpath", + AAD: "foobar", + Config: map[string]interface{}{ + "path": "/tmp/file-foo", + }, + }, + }, + }, + } + + config.Prune() + if diff := deep.Equal(config, expected); diff != nil { + t.Fatal(diff) + } + + config, err = LoadConfigFile("./test-fixtures/config-dir-auto-auth-and-listener/config1.hcl") + if err != nil { + t.Fatal(err) + } + config2, err := LoadConfigFile("./test-fixtures/config-dir-auto-auth-and-listener/config2.hcl") + + mergedConfig := config.Merge(config2) + + mergedConfig.Prune() + if diff := deep.Equal(mergedConfig, expected); diff != nil { + t.Fatal(diff) + } +} + +func TestLoadConfigDir_VaultBlock(t *testing.T) { + config, err := LoadConfig("./test-fixtures/config-dir-vault-block/") + if err != nil { + t.Fatal(err) + } + + expected := &Config{ + SharedConfig: &configutil.SharedConfig{ + PidFile: "./pidfile", + }, + Vault: &Vault{ + Address: "http://127.0.0.1:1111", + CACert: "config_ca_cert", + CAPath: "config_ca_path", + TLSSkipVerifyRaw: interface{}("true"), + TLSSkipVerify: true, + ClientCert: "config_client_cert", + ClientKey: "config_client_key", + Retry: &Retry{ + NumRetries: 12, + }, + }, + AutoAuth: &AutoAuth{ + Method: &Method{ + Type: "aws", + MountPath: "auth/aws", + Config: map[string]interface{}{ + "role": "foobar", + }, + }, + Sinks: []*Sink{ + { + Type: "file", + DHType: "curve25519", + DHPath: "/tmp/file-foo-dhpath", + AAD: "foobar", + Config: map[string]interface{}{ + "path": "/tmp/file-foo", + }, + }, + }, + }, + } + + config.Prune() + if diff := deep.Equal(config, expected); diff != nil { + t.Fatal(diff) + } + + config, err = LoadConfigFile("./test-fixtures/config-dir-vault-block/config1.hcl") + if err != nil { + t.Fatal(err) + } + config2, err := LoadConfigFile("./test-fixtures/config-dir-vault-block/config2.hcl") + + mergedConfig := config.Merge(config2) + + mergedConfig.Prune() + if diff := deep.Equal(mergedConfig, expected); diff != nil { + t.Fatal(diff) + } +} + func TestLoadConfigFile_AgentCache_NoListeners(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-cache-no-listeners.hcl") + config, err := LoadConfigFile("./test-fixtures/config-cache-no-listeners.hcl") if err != nil { t.Fatal(err) } @@ -146,6 +374,10 @@ func TestLoadConfigFile_AgentCache_NoListeners(t *testing.T) { }, }, }, + APIProxy: &APIProxy{ + UseAutoAuthToken: true, + ForceAutoAuthToken: false, + }, Cache: &Cache{ UseAutoAuthToken: true, UseAutoAuthTokenRaw: true, @@ -194,7 +426,7 @@ func TestLoadConfigFile(t *testing.T) { } }() - config, err := LoadConfig("./test-fixtures/config.hcl") + config, err := LoadConfigFile("./test-fixtures/config.hcl") if err != nil { t.Fatalf("err: %s", err) } @@ -237,11 +469,6 @@ func TestLoadConfigFile(t *testing.T) { }, }, }, - Vault: &Vault{ - Retry: &Retry{ - NumRetries: 12, - }, - }, } config.Prune() @@ -249,7 +476,7 @@ func TestLoadConfigFile(t *testing.T) { t.Fatal(diff) } - config, err = LoadConfig("./test-fixtures/config-embedded-type.hcl") + config, err = LoadConfigFile("./test-fixtures/config-embedded-type.hcl") if err != nil { t.Fatalf("err: %s", err) } @@ -261,7 +488,7 @@ func TestLoadConfigFile(t *testing.T) { } func TestLoadConfigFile_Method_Wrapping(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-method-wrapping.hcl") + config, err := LoadConfigFile("./test-fixtures/config-method-wrapping.hcl") if err != nil { t.Fatalf("err: %s", err) } @@ -290,11 +517,6 @@ func TestLoadConfigFile_Method_Wrapping(t *testing.T) { }, }, }, - Vault: &Vault{ - Retry: &Retry{ - NumRetries: 12, - }, - }, } config.Prune() @@ -304,7 +526,7 @@ func TestLoadConfigFile_Method_Wrapping(t *testing.T) { } func TestLoadConfigFile_Method_InitialBackoff(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-method-initial-backoff.hcl") + config, err := LoadConfigFile("./test-fixtures/config-method-initial-backoff.hcl") if err != nil { t.Fatalf("err: %s", err) } @@ -334,11 +556,6 @@ func TestLoadConfigFile_Method_InitialBackoff(t *testing.T) { }, }, }, - Vault: &Vault{ - Retry: &Retry{ - NumRetries: 12, - }, - }, } config.Prune() @@ -348,7 +565,7 @@ func TestLoadConfigFile_Method_InitialBackoff(t *testing.T) { } func TestLoadConfigFile_Method_ExitOnErr(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-method-exit-on-err.hcl") + config, err := LoadConfigFile("./test-fixtures/config-method-exit-on-err.hcl") if err != nil { t.Fatalf("err: %s", err) } @@ -378,11 +595,6 @@ func TestLoadConfigFile_Method_ExitOnErr(t *testing.T) { }, }, }, - Vault: &Vault{ - Retry: &Retry{ - NumRetries: 12, - }, - }, } config.Prune() @@ -392,7 +604,7 @@ func TestLoadConfigFile_Method_ExitOnErr(t *testing.T) { } func TestLoadConfigFile_AgentCache_NoAutoAuth(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-cache-no-auto_auth.hcl") + config, err := LoadConfigFile("./test-fixtures/config-cache-no-auto_auth.hcl") if err != nil { t.Fatalf("err: %s", err) } @@ -410,11 +622,6 @@ func TestLoadConfigFile_AgentCache_NoAutoAuth(t *testing.T) { }, }, }, - Vault: &Vault{ - Retry: &Retry{ - NumRetries: 12, - }, - }, } config.Prune() @@ -424,63 +631,98 @@ func TestLoadConfigFile_AgentCache_NoAutoAuth(t *testing.T) { } func TestLoadConfigFile_Bad_AgentCache_InconsisentAutoAuth(t *testing.T) { - _, err := LoadConfig("./test-fixtures/bad-config-cache-inconsistent-auto_auth.hcl") + config, err := LoadConfigFile("./test-fixtures/bad-config-cache-inconsistent-auto_auth.hcl") + if err != nil { + t.Fatalf("LoadConfigFile should not return an error for this config, err: %v", err) + } + if config == nil { + t.Fatal("config was nil") + } + err = config.ValidateConfig() if err == nil { - t.Fatal("LoadConfig should return an error when use_auto_auth_token=true and no auto_auth section present") + t.Fatal("ValidateConfig should return an error when use_auto_auth_token=true and no auto_auth section present") } } func TestLoadConfigFile_Bad_AgentCache_ForceAutoAuthNoMethod(t *testing.T) { - _, err := LoadConfig("./test-fixtures/bad-config-cache-force-auto_auth.hcl") + config, err := LoadConfigFile("./test-fixtures/bad-config-cache-force-token-no-auth-method.hcl") + if err != nil { + t.Fatalf("LoadConfigFile should not return an error for this config, err: %v", err) + } + if config == nil { + t.Fatal("config was nil") + } + err = config.ValidateConfig() if err == nil { - t.Fatal("LoadConfig should return an error when use_auto_auth_token=force and no auto_auth section present") + t.Fatal("ValidateConfig should return an error when use_auto_auth_token=force and no auto_auth section present") } } func TestLoadConfigFile_Bad_AgentCache_NoListeners(t *testing.T) { - _, err := LoadConfig("./test-fixtures/bad-config-cache-no-listeners.hcl") - if err == nil { - t.Fatal("LoadConfig should return an error when cache section present and no listeners present and no templates defined") + _, err := LoadConfigFile("./test-fixtures/bad-config-cache-no-listeners.hcl") + if err != nil { + t.Fatalf("LoadConfigFile should return an error for this config") } } func TestLoadConfigFile_Bad_AutoAuth_Wrapped_Multiple_Sinks(t *testing.T) { - _, err := LoadConfig("./test-fixtures/bad-config-auto_auth-wrapped-multiple-sinks.hcl") + _, err := LoadConfigFile("./test-fixtures/bad-config-auto_auth-wrapped-multiple-sinks.hcl") if err == nil { - t.Fatal("LoadConfig should return an error when auth_auth.method.wrap_ttl nonzero and multiple sinks defined") + t.Fatalf("LoadConfigFile should return an error for this config, err: %v", err) } } func TestLoadConfigFile_Bad_AutoAuth_Nosinks_Nocache_Notemplates(t *testing.T) { - _, err := LoadConfig("./test-fixtures/bad-config-auto_auth-nosinks-nocache-notemplates.hcl") + config, err := LoadConfigFile("./test-fixtures/bad-config-auto_auth-nosinks-nocache-notemplates.hcl") + if err != nil { + t.Fatalf("LoadConfigFile should not return an error for this config, err: %v", err) + } + if config == nil { + t.Fatal("config was nil") + } + err = config.ValidateConfig() if err == nil { - t.Fatal("LoadConfig should return an error when auto_auth configured and there are no sinks, caches or templates") + t.Fatal("ValidateConfig should return an error when auto_auth configured and there are no sinks, caches or templates") } } func TestLoadConfigFile_Bad_AutoAuth_Both_Wrapping_Types(t *testing.T) { - _, err := LoadConfig("./test-fixtures/bad-config-method-wrapping-and-sink-wrapping.hcl") + _, err := LoadConfigFile("./test-fixtures/bad-config-method-wrapping-and-sink-wrapping.hcl") if err == nil { - t.Fatal("LoadConfig should return an error when auth_auth.method.wrap_ttl nonzero and sinks.wrap_ttl nonzero") + t.Fatalf("LoadConfigFile should return an error for this config") } } func TestLoadConfigFile_Bad_AgentCache_AutoAuth_Method_wrapping(t *testing.T) { - _, err := LoadConfig("./test-fixtures/bad-config-cache-auto_auth-method-wrapping.hcl") + config, err := LoadConfigFile("./test-fixtures/bad-config-cache-auto_auth-method-wrapping.hcl") + if err != nil { + t.Fatalf("LoadConfigFile should not return an error for this config, err: %v", err) + } + if config == nil { + t.Fatal("config was nil") + } + err = config.ValidateConfig() if err == nil { - t.Fatal("LoadConfig should return an error when auth_auth.method.wrap_ttl nonzero and cache.use_auto_auth_token=true") + t.Fatal("ValidateConfig should return an error when auth_auth.method.wrap_ttl nonzero and cache.use_auto_auth_token=true") } } func TestLoadConfigFile_Bad_APIProxy_And_Cache_Same_Config(t *testing.T) { - _, err := LoadConfig("./test-fixtures/bad-config-api_proxy-cache.hcl") + config, err := LoadConfigFile("./test-fixtures/bad-config-api_proxy-cache.hcl") + if err != nil { + t.Fatalf("LoadConfigFile should not return an error for this config, err: %v", err) + } + if config == nil { + t.Fatal("config was nil") + } + err = config.ValidateConfig() if err == nil { - t.Fatal("LoadConfig should return an error when cache and api_proxy try and configure the same value") + t.Fatal("ValidateConfig should return an error when cache and api_proxy try and configure the same value") } } func TestLoadConfigFile_AgentCache_AutoAuth_NoSink(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-cache-auto_auth-no-sink.hcl") + config, err := LoadConfigFile("./test-fixtures/config-cache-auto_auth-no-sink.hcl") if err != nil { t.Fatalf("err: %s", err) } @@ -514,11 +756,6 @@ func TestLoadConfigFile_AgentCache_AutoAuth_NoSink(t *testing.T) { UseAutoAuthTokenRaw: true, ForceAutoAuthToken: false, }, - Vault: &Vault{ - Retry: &Retry{ - NumRetries: 12, - }, - }, } config.Prune() @@ -528,7 +765,7 @@ func TestLoadConfigFile_AgentCache_AutoAuth_NoSink(t *testing.T) { } func TestLoadConfigFile_AgentCache_AutoAuth_Force(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-cache-auto_auth-force.hcl") + config, err := LoadConfigFile("./test-fixtures/config-cache-auto_auth-force.hcl") if err != nil { t.Fatalf("err: %s", err) } @@ -562,11 +799,6 @@ func TestLoadConfigFile_AgentCache_AutoAuth_Force(t *testing.T) { UseAutoAuthTokenRaw: "force", ForceAutoAuthToken: true, }, - Vault: &Vault{ - Retry: &Retry{ - NumRetries: 12, - }, - }, } config.Prune() @@ -576,7 +808,7 @@ func TestLoadConfigFile_AgentCache_AutoAuth_Force(t *testing.T) { } func TestLoadConfigFile_AgentCache_AutoAuth_True(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-cache-auto_auth-true.hcl") + config, err := LoadConfigFile("./test-fixtures/config-cache-auto_auth-true.hcl") if err != nil { t.Fatalf("err: %s", err) } @@ -610,11 +842,6 @@ func TestLoadConfigFile_AgentCache_AutoAuth_True(t *testing.T) { UseAutoAuthTokenRaw: "true", ForceAutoAuthToken: false, }, - Vault: &Vault{ - Retry: &Retry{ - NumRetries: 12, - }, - }, } config.Prune() @@ -624,7 +851,7 @@ func TestLoadConfigFile_AgentCache_AutoAuth_True(t *testing.T) { } func TestLoadConfigFile_Agent_AutoAuth_APIProxyAllConfig(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-api_proxy-auto_auth-all-api_proxy-config.hcl") + config, err := LoadConfigFile("./test-fixtures/config-api_proxy-auto_auth-all-api_proxy-config.hcl") if err != nil { t.Fatalf("err: %s", err) } @@ -656,11 +883,6 @@ func TestLoadConfigFile_Agent_AutoAuth_APIProxyAllConfig(t *testing.T) { EnforceConsistency: "always", WhenInconsistent: "forward", }, - Vault: &Vault{ - Retry: &Retry{ - NumRetries: 12, - }, - }, } config.Prune() @@ -670,7 +892,7 @@ func TestLoadConfigFile_Agent_AutoAuth_APIProxyAllConfig(t *testing.T) { } func TestLoadConfigFile_AgentCache_AutoAuth_False(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-cache-auto_auth-false.hcl") + config, err := LoadConfigFile("./test-fixtures/config-cache-auto_auth-false.hcl") if err != nil { t.Fatalf("err: %s", err) } @@ -715,11 +937,6 @@ func TestLoadConfigFile_AgentCache_AutoAuth_False(t *testing.T) { UseAutoAuthTokenRaw: "false", ForceAutoAuthToken: false, }, - Vault: &Vault{ - Retry: &Retry{ - NumRetries: 12, - }, - }, } config.Prune() @@ -729,7 +946,7 @@ func TestLoadConfigFile_AgentCache_AutoAuth_False(t *testing.T) { } func TestLoadConfigFile_AgentCache_Persist(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-cache-persist-false.hcl") + config, err := LoadConfigFile("./test-fixtures/config-cache-persist-false.hcl") if err != nil { t.Fatalf("err: %s", err) } @@ -755,11 +972,6 @@ func TestLoadConfigFile_AgentCache_Persist(t *testing.T) { }, }, }, - Vault: &Vault{ - Retry: &Retry{ - NumRetries: 12, - }, - }, } config.Prune() @@ -769,7 +981,7 @@ func TestLoadConfigFile_AgentCache_Persist(t *testing.T) { } func TestLoadConfigFile_AgentCache_PersistMissingType(t *testing.T) { - _, err := LoadConfig("./test-fixtures/config-cache-persist-empty-type.hcl") + _, err := LoadConfigFile("./test-fixtures/config-cache-persist-empty-type.hcl") if err == nil || os.IsNotExist(err) { t.Fatal("expected error or file is missing") } @@ -797,7 +1009,7 @@ func TestLoadConfigFile_TemplateConfig(t *testing.T) { for name, tc := range testCases { t.Run(name, func(t *testing.T) { - config, err := LoadConfig(tc.fixturePath) + config, err := LoadConfigFile(tc.fixturePath) if err != nil { t.Fatal(err) } @@ -896,7 +1108,7 @@ func TestLoadConfigFile_Template(t *testing.T) { for name, tc := range testCases { t.Run(name, func(t *testing.T) { - config, err := LoadConfig(tc.fixturePath) + config, err := LoadConfigFile(tc.fixturePath) if err != nil { t.Fatalf("err: %s", err) } @@ -926,11 +1138,6 @@ func TestLoadConfigFile_Template(t *testing.T) { }, }, }, - Vault: &Vault{ - Retry: &Retry{ - NumRetries: 12, - }, - }, Templates: tc.expectedTemplates, } @@ -1007,7 +1214,7 @@ func TestLoadConfigFile_Template_NoSinks(t *testing.T) { for name, tc := range testCases { t.Run(name, func(t *testing.T) { - config, err := LoadConfig(tc.fixturePath) + config, err := LoadConfigFile(tc.fixturePath) if err != nil { t.Fatalf("err: %s", err) } @@ -1028,11 +1235,6 @@ func TestLoadConfigFile_Template_NoSinks(t *testing.T) { Sinks: nil, }, Templates: tc.expectedTemplates, - Vault: &Vault{ - Retry: &Retry{ - NumRetries: 12, - }, - }, } config.Prune() @@ -1044,7 +1246,7 @@ func TestLoadConfigFile_Template_NoSinks(t *testing.T) { } func TestLoadConfigFile_Vault_Retry(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-vault-retry.hcl") + config, err := LoadConfigFile("./test-fixtures/config-vault-retry.hcl") if err != nil { t.Fatal(err) } @@ -1089,7 +1291,7 @@ func TestLoadConfigFile_Vault_Retry(t *testing.T) { } func TestLoadConfigFile_Vault_Retry_Empty(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-vault-retry-empty.hcl") + config, err := LoadConfigFile("./test-fixtures/config-vault-retry-empty.hcl") if err != nil { t.Fatal(err) } @@ -1134,7 +1336,7 @@ func TestLoadConfigFile_Vault_Retry_Empty(t *testing.T) { } func TestLoadConfigFile_EnforceConsistency(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-consistency.hcl") + config, err := LoadConfigFile("./test-fixtures/config-consistency.hcl") if err != nil { t.Fatal(err) } @@ -1155,11 +1357,6 @@ func TestLoadConfigFile_EnforceConsistency(t *testing.T) { EnforceConsistency: "always", WhenInconsistent: "retry", }, - Vault: &Vault{ - Retry: &Retry{ - NumRetries: 12, - }, - }, } config.Prune() @@ -1169,7 +1366,7 @@ func TestLoadConfigFile_EnforceConsistency(t *testing.T) { } func TestLoadConfigFile_EnforceConsistency_APIProxy(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-consistency-apiproxy.hcl") + config, err := LoadConfigFile("./test-fixtures/config-consistency-apiproxy.hcl") if err != nil { t.Fatal(err) } @@ -1189,11 +1386,6 @@ func TestLoadConfigFile_EnforceConsistency_APIProxy(t *testing.T) { EnforceConsistency: "always", WhenInconsistent: "retry", }, - Vault: &Vault{ - Retry: &Retry{ - NumRetries: 12, - }, - }, } config.Prune() @@ -1203,7 +1395,7 @@ func TestLoadConfigFile_EnforceConsistency_APIProxy(t *testing.T) { } func TestLoadConfigFile_Disable_Idle_Conns_All(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-disable-idle-connections-all.hcl") + config, err := LoadConfigFile("./test-fixtures/config-disable-idle-connections-all.hcl") if err != nil { t.Fatal(err) } @@ -1252,7 +1444,7 @@ func TestLoadConfigFile_Disable_Idle_Conns_All(t *testing.T) { } func TestLoadConfigFile_Disable_Idle_Conns_Auto_Auth(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-disable-idle-connections-auto-auth.hcl") + config, err := LoadConfigFile("./test-fixtures/config-disable-idle-connections-auto-auth.hcl") if err != nil { t.Fatal(err) } @@ -1301,7 +1493,7 @@ func TestLoadConfigFile_Disable_Idle_Conns_Auto_Auth(t *testing.T) { } func TestLoadConfigFile_Disable_Idle_Conns_Templating(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-disable-idle-connections-templating.hcl") + config, err := LoadConfigFile("./test-fixtures/config-disable-idle-connections-templating.hcl") if err != nil { t.Fatal(err) } @@ -1350,7 +1542,7 @@ func TestLoadConfigFile_Disable_Idle_Conns_Templating(t *testing.T) { } func TestLoadConfigFile_Disable_Idle_Conns_Caching(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-disable-idle-connections-caching.hcl") + config, err := LoadConfigFile("./test-fixtures/config-disable-idle-connections-caching.hcl") if err != nil { t.Fatal(err) } @@ -1399,7 +1591,7 @@ func TestLoadConfigFile_Disable_Idle_Conns_Caching(t *testing.T) { } func TestLoadConfigFile_Disable_Idle_Conns_Proxying(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-disable-idle-connections-proxying.hcl") + config, err := LoadConfigFile("./test-fixtures/config-disable-idle-connections-proxying.hcl") if err != nil { t.Fatal(err) } @@ -1448,7 +1640,7 @@ func TestLoadConfigFile_Disable_Idle_Conns_Proxying(t *testing.T) { } func TestLoadConfigFile_Disable_Idle_Conns_Empty(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-disable-idle-connections-empty.hcl") + config, err := LoadConfigFile("./test-fixtures/config-disable-idle-connections-empty.hcl") if err != nil { t.Fatal(err) } @@ -1503,7 +1695,7 @@ func TestLoadConfigFile_Disable_Idle_Conns_Env(t *testing.T) { if err != nil { t.Fatal(err) } - config, err := LoadConfig("./test-fixtures/config-disable-idle-connections-empty.hcl") + config, err := LoadConfigFile("./test-fixtures/config-disable-idle-connections-empty.hcl") if err != nil { t.Fatal(err) } @@ -1552,14 +1744,14 @@ func TestLoadConfigFile_Disable_Idle_Conns_Env(t *testing.T) { } func TestLoadConfigFile_Bad_Value_Disable_Idle_Conns(t *testing.T) { - _, err := LoadConfig("./test-fixtures/bad-config-disable-idle-connections.hcl") + _, err := LoadConfigFile("./test-fixtures/bad-config-disable-idle-connections.hcl") if err == nil { t.Fatal("should have error, it didn't") } } func TestLoadConfigFile_Disable_Keep_Alives_All(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-disable-keep-alives-all.hcl") + config, err := LoadConfigFile("./test-fixtures/config-disable-keep-alives-all.hcl") if err != nil { t.Fatal(err) } @@ -1608,7 +1800,7 @@ func TestLoadConfigFile_Disable_Keep_Alives_All(t *testing.T) { } func TestLoadConfigFile_Disable_Keep_Alives_Auto_Auth(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-disable-keep-alives-auto-auth.hcl") + config, err := LoadConfigFile("./test-fixtures/config-disable-keep-alives-auto-auth.hcl") if err != nil { t.Fatal(err) } @@ -1657,7 +1849,7 @@ func TestLoadConfigFile_Disable_Keep_Alives_Auto_Auth(t *testing.T) { } func TestLoadConfigFile_Disable_Keep_Alives_Templating(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-disable-keep-alives-templating.hcl") + config, err := LoadConfigFile("./test-fixtures/config-disable-keep-alives-templating.hcl") if err != nil { t.Fatal(err) } @@ -1706,7 +1898,7 @@ func TestLoadConfigFile_Disable_Keep_Alives_Templating(t *testing.T) { } func TestLoadConfigFile_Disable_Keep_Alives_Caching(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-disable-keep-alives-caching.hcl") + config, err := LoadConfigFile("./test-fixtures/config-disable-keep-alives-caching.hcl") if err != nil { t.Fatal(err) } @@ -1755,7 +1947,7 @@ func TestLoadConfigFile_Disable_Keep_Alives_Caching(t *testing.T) { } func TestLoadConfigFile_Disable_Keep_Alives_Proxying(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-disable-keep-alives-proxying.hcl") + config, err := LoadConfigFile("./test-fixtures/config-disable-keep-alives-proxying.hcl") if err != nil { t.Fatal(err) } @@ -1804,7 +1996,7 @@ func TestLoadConfigFile_Disable_Keep_Alives_Proxying(t *testing.T) { } func TestLoadConfigFile_Disable_Keep_Alives_Empty(t *testing.T) { - config, err := LoadConfig("./test-fixtures/config-disable-keep-alives-empty.hcl") + config, err := LoadConfigFile("./test-fixtures/config-disable-keep-alives-empty.hcl") if err != nil { t.Fatal(err) } @@ -1859,7 +2051,7 @@ func TestLoadConfigFile_Disable_Keep_Alives_Env(t *testing.T) { if err != nil { t.Fatal(err) } - config, err := LoadConfig("./test-fixtures/config-disable-keep-alives-empty.hcl") + config, err := LoadConfigFile("./test-fixtures/config-disable-keep-alives-empty.hcl") if err != nil { t.Fatal(err) } @@ -1908,7 +2100,7 @@ func TestLoadConfigFile_Disable_Keep_Alives_Env(t *testing.T) { } func TestLoadConfigFile_Bad_Value_Disable_Keep_Alives(t *testing.T) { - _, err := LoadConfig("./test-fixtures/bad-config-disable-keep-alives.hcl") + _, err := LoadConfigFile("./test-fixtures/bad-config-disable-keep-alives.hcl") if err == nil { t.Fatal("should have error, it didn't") } diff --git a/command/agent/config/test-fixtures/config-dir-auto-auth-and-listener/config1.hcl b/command/agent/config/test-fixtures/config-dir-auto-auth-and-listener/config1.hcl new file mode 100644 index 000000000..849aab288 --- /dev/null +++ b/command/agent/config/test-fixtures/config-dir-auto-auth-and-listener/config1.hcl @@ -0,0 +1,20 @@ +pid_file = "./pidfile" + +auto_auth { + method { + type = "aws" + config = { + role = "foobar" + } + } + + sink { + type = "file" + config = { + path = "/tmp/file-foo" + } + aad = "foobar" + dh_type = "curve25519" + dh_path = "/tmp/file-foo-dhpath" + } +} \ No newline at end of file diff --git a/command/agent/config/test-fixtures/config-dir-auto-auth-and-listener/config2.hcl b/command/agent/config/test-fixtures/config-dir-auto-auth-and-listener/config2.hcl new file mode 100644 index 000000000..e1efa9562 --- /dev/null +++ b/command/agent/config/test-fixtures/config-dir-auto-auth-and-listener/config2.hcl @@ -0,0 +1,6 @@ +pid_file = "./pidfile" + +listener "tcp" { + address = "127.0.0.1:8300" + tls_disable = true +} \ No newline at end of file diff --git a/command/agent/config/test-fixtures/config-dir-cache/config-cache1.hcl b/command/agent/config/test-fixtures/config-dir-cache/config-cache1.hcl new file mode 100644 index 000000000..8dab7ed91 --- /dev/null +++ b/command/agent/config/test-fixtures/config-dir-cache/config-cache1.hcl @@ -0,0 +1,47 @@ +pid_file = "./pidfile" + +auto_auth { + method { + type = "aws" + config = { + role = "foobar" + } + } + + sink { + type = "file" + config = { + path = "/tmp/file-foo" + } + aad = "foobar" + dh_type = "curve25519" + dh_path = "/tmp/file-foo-dhpath" + } +} + +listener "unix" { + address = "/path/to/socket" + tls_disable = true + socket_mode = "configmode" + socket_user = "configuser" + socket_group = "configgroup" +} + +listener "tcp" { + address = "127.0.0.1:8300" + tls_disable = true +} + +listener { + type = "tcp" + address = "127.0.0.1:3000" + tls_disable = true + role = "metrics_only" +} + +listener "tcp" { + role = "default" + address = "127.0.0.1:8400" + tls_key_file = "/path/to/cakey.pem" + tls_cert_file = "/path/to/cacert.pem" +} \ No newline at end of file diff --git a/command/agent/config/test-fixtures/config-dir-cache/config-cache2.hcl b/command/agent/config/test-fixtures/config-dir-cache/config-cache2.hcl new file mode 100644 index 000000000..f8398188c --- /dev/null +++ b/command/agent/config/test-fixtures/config-dir-cache/config-cache2.hcl @@ -0,0 +1,19 @@ +cache { + use_auto_auth_token = true + persist = { + type = "kubernetes" + path = "/vault/agent-cache/" + keep_after_import = true + exit_on_err = true + service_account_token_file = "/tmp/serviceaccount/token" + } +} + +vault { + address = "http://127.0.0.1:1111" + ca_cert = "config_ca_cert" + ca_path = "config_ca_path" + tls_skip_verify = "true" + client_cert = "config_client_cert" + client_key = "config_client_key" +} diff --git a/command/agent/config/test-fixtures/config-dir-vault-block/config1.hcl b/command/agent/config/test-fixtures/config-dir-vault-block/config1.hcl new file mode 100644 index 000000000..eeec3b8f2 --- /dev/null +++ b/command/agent/config/test-fixtures/config-dir-vault-block/config1.hcl @@ -0,0 +1,8 @@ +vault { + address = "http://127.0.0.1:1111" + ca_cert = "config_ca_cert" + ca_path = "config_ca_path" + tls_skip_verify = "true" + client_cert = "config_client_cert" + client_key = "config_client_key" +} diff --git a/command/agent/config/test-fixtures/config-dir-vault-block/config2.hcl b/command/agent/config/test-fixtures/config-dir-vault-block/config2.hcl new file mode 100644 index 000000000..849aab288 --- /dev/null +++ b/command/agent/config/test-fixtures/config-dir-vault-block/config2.hcl @@ -0,0 +1,20 @@ +pid_file = "./pidfile" + +auto_auth { + method { + type = "aws" + config = { + role = "foobar" + } + } + + sink { + type = "file" + config = { + path = "/tmp/file-foo" + } + aad = "foobar" + dh_type = "curve25519" + dh_path = "/tmp/file-foo-dhpath" + } +} \ No newline at end of file diff --git a/command/agent/template/template.go b/command/agent/template/template.go index 32e9022bb..8d44e0db1 100644 --- a/command/agent/template/template.go +++ b/command/agent/template/template.go @@ -264,9 +264,9 @@ func newRunnerConfig(sc *ServerConfig, templates ctconfig.TemplateConfigs) (*ctc ServerName: pointerutil.StringPtr(""), } - // We need to assign something to Vault.Retry or it will use its default of 12 retries. + // If Vault.Retry isn't specified, use the default of 12 retries. // This retry value will be respected regardless of if we use the cache. - var attempts int + attempts := ctconfig.DefaultRetryAttempts if sc.AgentConfig.Vault != nil && sc.AgentConfig.Vault.Retry != nil { attempts = sc.AgentConfig.Vault.Retry.NumRetries } diff --git a/command/agent_test.go b/command/agent_test.go index 4c1ef04e8..13dc17cd5 100644 --- a/command/agent_test.go +++ b/command/agent_test.go @@ -61,191 +61,6 @@ func testAgentCommand(tb testing.TB, logger hclog.Logger) (*cli.MockUi, *AgentCo } } -/* -func TestAgent_Cache_UnixListener(t *testing.T) { - logger := logging.NewVaultLogger(hclog.Trace) - coreConfig := &vault.CoreConfig{ - Logger: logger.Named("core"), - CredentialBackends: map[string]logical.Factory{ - "jwt": vaultjwt.Factory, - }, - } - cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{ - HandlerFunc: vaulthttp.Handler, - }) - cluster.Start() - defer cluster.Cleanup() - - vault.TestWaitActive(t, cluster.Cores[0].Core) - client := cluster.Cores[0].Client - - defer os.Setenv(api.EnvVaultAddress, os.Getenv(api.EnvVaultAddress)) - os.Setenv(api.EnvVaultAddress, client.Address()) - - defer os.Setenv(api.EnvVaultCACert, os.Getenv(api.EnvVaultCACert)) - os.Setenv(api.EnvVaultCACert, fmt.Sprintf("%s/ca_cert.pem", cluster.TempDir)) - - // Setup Vault - err := client.Sys().EnableAuthWithOptions("jwt", &api.EnableAuthOptions{ - Type: "jwt", - }) - if err != nil { - t.Fatal(err) - } - - _, err = client.Logical().Write("auth/jwt/config", map[string]interface{}{ - "bound_issuer": "https://team-vault.auth0.com/", - "jwt_validation_pubkeys": agent.TestECDSAPubKey, - }) - if err != nil { - t.Fatal(err) - } - - _, err = client.Logical().Write("auth/jwt/role/test", map[string]interface{}{ - "role_type": "jwt", - "bound_subject": "r3qXcK2bix9eFECzsU3Sbmh0K16fatW6@clients", - "bound_audiences": "https://vault.plugin.auth.jwt.test", - "user_claim": "https://vault/user", - "groups_claim": "https://vault/groups", - "policies": "test", - "period": "3s", - }) - if err != nil { - t.Fatal(err) - } - - inf, err := ioutil.TempFile("", "auth.jwt.test.") - if err != nil { - t.Fatal(err) - } - in := inf.Name() - inf.Close() - os.Remove(in) - t.Logf("input: %s", in) - - sink1f, err := ioutil.TempFile("", "sink1.jwt.test.") - if err != nil { - t.Fatal(err) - } - sink1 := sink1f.Name() - sink1f.Close() - os.Remove(sink1) - t.Logf("sink1: %s", sink1) - - sink2f, err := ioutil.TempFile("", "sink2.jwt.test.") - if err != nil { - t.Fatal(err) - } - sink2 := sink2f.Name() - sink2f.Close() - os.Remove(sink2) - t.Logf("sink2: %s", sink2) - - conff, err := ioutil.TempFile("", "conf.jwt.test.") - if err != nil { - t.Fatal(err) - } - conf := conff.Name() - conff.Close() - os.Remove(conf) - t.Logf("config: %s", conf) - - jwtToken, _ := agent.GetTestJWT(t) - if err := ioutil.WriteFile(in, []byte(jwtToken), 0600); err != nil { - t.Fatal(err) - } else { - logger.Trace("wrote test jwt", "path", in) - } - - socketff, err := ioutil.TempFile("", "cache.socket.") - if err != nil { - t.Fatal(err) - } - socketf := socketff.Name() - socketff.Close() - os.Remove(socketf) - t.Logf("socketf: %s", socketf) - - config := ` -auto_auth { - method { - type = "jwt" - config = { - role = "test" - path = "%s" - } - } - - sink { - type = "file" - config = { - path = "%s" - } - } - - sink "file" { - config = { - path = "%s" - } - } -} - -cache { - use_auto_auth_token = true - - listener "unix" { - address = "%s" - tls_disable = true - } -} -` - - config = fmt.Sprintf(config, in, sink1, sink2, socketf) - if err := ioutil.WriteFile(conf, []byte(config), 0600); err != nil { - t.Fatal(err) - } else { - logger.Trace("wrote test config", "path", conf) - } - - _, cmd := testAgentCommand(t, logger) - cmd.client = client - - // Kill the command 5 seconds after it starts - go func() { - select { - case <-cmd.ShutdownCh: - case <-time.After(5 * time.Second): - cmd.ShutdownCh <- struct{}{} - } - }() - - originalVaultAgentAddress := os.Getenv(api.EnvVaultAgentAddr) - - // Create a client that talks to the agent - os.Setenv(api.EnvVaultAgentAddr, socketf) - testClient, err := api.NewClient(api.DefaultConfig()) - if err != nil { - t.Fatal(err) - } - os.Setenv(api.EnvVaultAgentAddr, originalVaultAgentAddress) - - // Start the agent - go cmd.Run([]string{"-config", conf}) - - // Give some time for the auto-auth to complete - time.Sleep(1 * time.Second) - - // Invoke lookup self through the agent - secret, err := testClient.Auth().Token().LookupSelf() - if err != nil { - t.Fatal(err) - } - if secret == nil || secret.Data == nil || secret.Data["id"].(string) == "" { - t.Fatalf("failed to perform lookup self through agent") - } -} -*/ - func TestAgent_ExitAfterAuth(t *testing.T) { t.Run("via_config", func(t *testing.T) { testAgentExitAfterAuth(t, false) @@ -2254,7 +2069,7 @@ cache {} func TestAgent_LogFile_CliOverridesConfig(t *testing.T) { // Create basic config configFile := populateTempFile(t, "agent-config.hcl", BasicHclConfig) - cfg, err := agentConfig.LoadConfig(configFile.Name()) + cfg, err := agentConfig.LoadConfigFile(configFile.Name()) if err != nil { t.Fatal("Cannot load config to test update/merge", err) } @@ -2282,7 +2097,7 @@ func TestAgent_LogFile_CliOverridesConfig(t *testing.T) { func TestAgent_LogFile_Config(t *testing.T) { configFile := populateTempFile(t, "agent-config.hcl", BasicHclConfig) - cfg, err := agentConfig.LoadConfig(configFile.Name()) + cfg, err := agentConfig.LoadConfigFile(configFile.Name()) if err != nil { t.Fatal("Cannot load config to test update/merge", err) } diff --git a/website/content/docs/agent/index.mdx b/website/content/docs/agent/index.mdx index c28f3da47..e0156baba 100644 --- a/website/content/docs/agent/index.mdx +++ b/website/content/docs/agent/index.mdx @@ -361,6 +361,12 @@ To run Vault Agent: $ vault agent -h ``` +As with Vault, the `-config` flag can be used in three different ways: + +- Use the flag once to name the path to a single specific configuration file. +- Use the flag multiple times to name multiple configuration files, which will be composed at runtime. +- Use the flag to name a directory of configuration files, the contents of which will be composed at runtime. + ## Example Configuration An example configuration, with very contrived values, follows: