agent: route templating server through cache (#10927)
* agent: route templating server through cache * Remove TemplateRetry, fix unix path * Remove mtls comment, remove redundant tls enable * Fix test * Refactor vault address logic * Fix cert/key for mtls * Update command/agent/template/template_test.go Co-authored-by: Theron Voran <tvoran@users.noreply.github.com> * Update command/agent/template/template_test.go Co-authored-by: Theron Voran <tvoran@users.noreply.github.com> * Update command/agent/template/template_test.go Co-authored-by: Theron Voran <tvoran@users.noreply.github.com> * Update command/agent/template/template_test.go Co-authored-by: Theron Voran <tvoran@users.noreply.github.com> * Update command/agent/template/template_test.go Co-authored-by: Theron Voran <tvoran@users.noreply.github.com> * Update command/agent/template/template_test.go Co-authored-by: Theron Voran <tvoran@users.noreply.github.com> * Reject mtls listeners * changelog Co-authored-by: Theron Voran <tvoran@users.noreply.github.com>
This commit is contained in:
parent
b54bc22f9e
commit
458061d43b
|
@ -0,0 +1,3 @@
|
|||
```release-note:improvement
|
||||
agent: Route templating server through cache when enabled.
|
||||
```
|
|
@ -589,8 +589,7 @@ func (c *AgentCommand) Run(args []string) int {
|
|||
Logger: c.logger.Named("template.server"),
|
||||
LogLevel: level,
|
||||
LogWriter: c.logWriter,
|
||||
VaultConf: config.Vault,
|
||||
TemplateRetry: config.TemplateRetry,
|
||||
AgentConfig: config,
|
||||
Namespace: namespace,
|
||||
ExitAfterAuth: exitAfterAuth,
|
||||
})
|
||||
|
|
|
@ -27,9 +27,9 @@ import (
|
|||
type ServerConfig struct {
|
||||
Logger hclog.Logger
|
||||
// Client *api.Client
|
||||
VaultConf *config.Vault
|
||||
AgentConfig *config.Config
|
||||
|
||||
ExitAfterAuth bool
|
||||
TemplateRetry *config.TemplateRetry
|
||||
Namespace string
|
||||
|
||||
// LogLevel is needed to set the internal Consul Template Runner's log level
|
||||
|
@ -164,12 +164,12 @@ func (ts *Server) Run(ctx context.Context, incoming chan string, templates []*ct
|
|||
},
|
||||
}
|
||||
|
||||
if ts.config.TemplateRetry != nil && ts.config.TemplateRetry.Enabled {
|
||||
if ts.config.AgentConfig.TemplateRetry != nil && ts.config.AgentConfig.TemplateRetry.Enabled {
|
||||
ctv.Vault.Retry = &ctconfig.RetryConfig{
|
||||
Attempts: &ts.config.TemplateRetry.Attempts,
|
||||
Backoff: &ts.config.TemplateRetry.Backoff,
|
||||
MaxBackoff: &ts.config.TemplateRetry.MaxBackoff,
|
||||
Enabled: &ts.config.TemplateRetry.Enabled,
|
||||
Attempts: &ts.config.AgentConfig.TemplateRetry.Attempts,
|
||||
Backoff: &ts.config.AgentConfig.TemplateRetry.Backoff,
|
||||
MaxBackoff: &ts.config.AgentConfig.TemplateRetry.MaxBackoff,
|
||||
Enabled: &ts.config.AgentConfig.TemplateRetry.Enabled,
|
||||
}
|
||||
} else if ts.testingLimitRetry != 0 {
|
||||
// If we're testing, limit retries to 3 attempts to avoid
|
||||
|
@ -239,7 +239,7 @@ func newRunnerConfig(sc *ServerConfig, templates ctconfig.TemplateConfigs) (*ctc
|
|||
// Always set these to ensure nothing is picked up from the environment
|
||||
conf.Vault.RenewToken = pointerutil.BoolPtr(false)
|
||||
conf.Vault.Token = pointerutil.StringPtr("")
|
||||
conf.Vault.Address = &sc.VaultConf.Address
|
||||
conf.Vault.Address = &sc.AgentConfig.Vault.Address
|
||||
|
||||
if sc.Namespace != "" {
|
||||
conf.Vault.Namespace = &sc.Namespace
|
||||
|
@ -255,16 +255,35 @@ func newRunnerConfig(sc *ServerConfig, templates ctconfig.TemplateConfigs) (*ctc
|
|||
ServerName: pointerutil.StringPtr(""),
|
||||
}
|
||||
|
||||
if strings.HasPrefix(sc.VaultConf.Address, "https") || sc.VaultConf.CACert != "" {
|
||||
skipVerify := sc.VaultConf.TLSSkipVerify
|
||||
// Use the cache if available or fallback to the Vault server values.
|
||||
if sc.AgentConfig.Cache != nil && len(sc.AgentConfig.Listeners) != 0 {
|
||||
scheme := "unix://"
|
||||
if sc.AgentConfig.Listeners[0].Type == "tcp" {
|
||||
scheme = "https://"
|
||||
if sc.AgentConfig.Listeners[0].TLSDisable {
|
||||
scheme = "http://"
|
||||
}
|
||||
}
|
||||
address := fmt.Sprintf("%s%s", scheme, sc.AgentConfig.Listeners[0].Address)
|
||||
conf.Vault.Address = &address
|
||||
|
||||
// Skip verification if its using the cache because they're part of the same agent.
|
||||
if scheme == "https://" {
|
||||
if sc.AgentConfig.Listeners[0].TLSRequireAndVerifyClientCert {
|
||||
return nil, errors.New("template server cannot use local cache when mTLS is enabled")
|
||||
}
|
||||
conf.Vault.SSL.Verify = pointerutil.BoolPtr(false)
|
||||
}
|
||||
} else if strings.HasPrefix(sc.AgentConfig.Vault.Address, "https") || sc.AgentConfig.Vault.CACert != "" {
|
||||
skipVerify := sc.AgentConfig.Vault.TLSSkipVerify
|
||||
verify := !skipVerify
|
||||
conf.Vault.SSL = &ctconfig.SSLConfig{
|
||||
Enabled: pointerutil.BoolPtr(true),
|
||||
Verify: &verify,
|
||||
Cert: &sc.VaultConf.ClientCert,
|
||||
Key: &sc.VaultConf.ClientKey,
|
||||
CaCert: &sc.VaultConf.CACert,
|
||||
CaPath: &sc.VaultConf.CAPath,
|
||||
Cert: &sc.AgentConfig.Vault.ClientCert,
|
||||
Key: &sc.AgentConfig.Vault.ClientKey,
|
||||
CaCert: &sc.AgentConfig.Vault.CACert,
|
||||
CaPath: &sc.AgentConfig.Vault.CAPath,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
ctconfig "github.com/hashicorp/consul-template/config"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/vault/command/agent/config"
|
||||
"github.com/hashicorp/vault/internalshared/configutil"
|
||||
"github.com/hashicorp/vault/sdk/helper/logging"
|
||||
"github.com/hashicorp/vault/sdk/helper/pointerutil"
|
||||
)
|
||||
|
@ -27,6 +28,251 @@ func TestNewServer(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func newAgentConfig(listeners []*configutil.Listener, enableCache bool) *config.Config {
|
||||
agentConfig := &config.Config{
|
||||
SharedConfig: &configutil.SharedConfig{
|
||||
PidFile: "./pidfile",
|
||||
Listeners: listeners,
|
||||
},
|
||||
AutoAuth: &config.AutoAuth{
|
||||
Method: &config.Method{
|
||||
Type: "aws",
|
||||
MountPath: "auth/aws",
|
||||
Config: map[string]interface{}{
|
||||
"role": "foobar",
|
||||
},
|
||||
},
|
||||
Sinks: []*config.Sink{
|
||||
{
|
||||
Type: "file",
|
||||
DHType: "curve25519",
|
||||
DHPath: "/tmp/file-foo-dhpath",
|
||||
AAD: "foobar",
|
||||
Config: map[string]interface{}{
|
||||
"path": "/tmp/file-foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Vault: &config.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",
|
||||
},
|
||||
}
|
||||
if enableCache {
|
||||
agentConfig.Cache = &config.Cache{UseAutoAuthToken: true}
|
||||
}
|
||||
|
||||
return agentConfig
|
||||
}
|
||||
|
||||
func TestCacheConfigUnix(t *testing.T) {
|
||||
listeners := []*configutil.Listener{
|
||||
{
|
||||
Type: "unix",
|
||||
Address: "foobar",
|
||||
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:8400",
|
||||
TLSKeyFile: "/path/to/cakey.pem",
|
||||
TLSCertFile: "/path/to/cacert.pem",
|
||||
},
|
||||
}
|
||||
|
||||
agentConfig := newAgentConfig(listeners, true)
|
||||
serverConfig := ServerConfig{AgentConfig: agentConfig}
|
||||
|
||||
ctConfig, err := newRunnerConfig(&serverConfig, ctconfig.TemplateConfigs{})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
expected := "unix://foobar"
|
||||
if *ctConfig.Vault.Address != expected {
|
||||
t.Fatalf("expected %s, got %s", expected, *ctConfig.Vault.Address)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCacheConfigHTTP(t *testing.T) {
|
||||
listeners := []*configutil.Listener{
|
||||
{
|
||||
Type: "tcp",
|
||||
Address: "127.0.0.1:8300",
|
||||
TLSDisable: true,
|
||||
},
|
||||
{
|
||||
Type: "unix",
|
||||
Address: "foobar",
|
||||
TLSDisable: true,
|
||||
SocketMode: "configmode",
|
||||
SocketUser: "configuser",
|
||||
SocketGroup: "configgroup",
|
||||
},
|
||||
{
|
||||
Type: "tcp",
|
||||
Address: "127.0.0.1:8400",
|
||||
TLSKeyFile: "/path/to/cakey.pem",
|
||||
TLSCertFile: "/path/to/cacert.pem",
|
||||
},
|
||||
}
|
||||
|
||||
agentConfig := newAgentConfig(listeners, true)
|
||||
serverConfig := ServerConfig{AgentConfig: agentConfig}
|
||||
|
||||
ctConfig, err := newRunnerConfig(&serverConfig, ctconfig.TemplateConfigs{})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
expected := "http://127.0.0.1:8300"
|
||||
if *ctConfig.Vault.Address != expected {
|
||||
t.Fatalf("expected %s, got %s", expected, *ctConfig.Vault.Address)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCacheConfigHTTPS(t *testing.T) {
|
||||
listeners := []*configutil.Listener{
|
||||
{
|
||||
Type: "tcp",
|
||||
Address: "127.0.0.1:8300",
|
||||
TLSKeyFile: "/path/to/cakey.pem",
|
||||
TLSCertFile: "/path/to/cacert.pem",
|
||||
},
|
||||
{
|
||||
Type: "unix",
|
||||
Address: "foobar",
|
||||
TLSDisable: true,
|
||||
SocketMode: "configmode",
|
||||
SocketUser: "configuser",
|
||||
SocketGroup: "configgroup",
|
||||
},
|
||||
{
|
||||
Type: "tcp",
|
||||
Address: "127.0.0.1:8400",
|
||||
TLSDisable: true,
|
||||
},
|
||||
}
|
||||
|
||||
agentConfig := newAgentConfig(listeners, true)
|
||||
serverConfig := ServerConfig{AgentConfig: agentConfig}
|
||||
|
||||
ctConfig, err := newRunnerConfig(&serverConfig, ctconfig.TemplateConfigs{})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
expected := "https://127.0.0.1:8300"
|
||||
if *ctConfig.Vault.Address != expected {
|
||||
t.Fatalf("expected %s, got %s", expected, *ctConfig.Vault.Address)
|
||||
}
|
||||
|
||||
if *ctConfig.Vault.SSL.Verify {
|
||||
t.Fatalf("expected %t, got %t", true, *ctConfig.Vault.SSL.Verify)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCacheConfigNoCache(t *testing.T) {
|
||||
listeners := []*configutil.Listener{
|
||||
{
|
||||
Type: "tcp",
|
||||
Address: "127.0.0.1:8300",
|
||||
TLSKeyFile: "/path/to/cakey.pem",
|
||||
TLSCertFile: "/path/to/cacert.pem",
|
||||
},
|
||||
{
|
||||
Type: "unix",
|
||||
Address: "foobar",
|
||||
TLSDisable: true,
|
||||
SocketMode: "configmode",
|
||||
SocketUser: "configuser",
|
||||
SocketGroup: "configgroup",
|
||||
},
|
||||
{
|
||||
Type: "tcp",
|
||||
Address: "127.0.0.1:8400",
|
||||
TLSDisable: true,
|
||||
},
|
||||
}
|
||||
|
||||
agentConfig := newAgentConfig(listeners, false)
|
||||
serverConfig := ServerConfig{AgentConfig: agentConfig}
|
||||
|
||||
ctConfig, err := newRunnerConfig(&serverConfig, ctconfig.TemplateConfigs{})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
expected := "http://127.0.0.1:1111"
|
||||
if *ctConfig.Vault.Address != expected {
|
||||
t.Fatalf("expected %s, got %s", expected, *ctConfig.Vault.Address)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCacheConfigNoListener(t *testing.T) {
|
||||
listeners := []*configutil.Listener{}
|
||||
|
||||
agentConfig := newAgentConfig(listeners, true)
|
||||
serverConfig := ServerConfig{AgentConfig: agentConfig}
|
||||
|
||||
ctConfig, err := newRunnerConfig(&serverConfig, ctconfig.TemplateConfigs{})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
expected := "http://127.0.0.1:1111"
|
||||
if *ctConfig.Vault.Address != expected {
|
||||
t.Fatalf("expected %s, got %s", expected, *ctConfig.Vault.Address)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCacheConfigRejectMTLS(t *testing.T) {
|
||||
listeners := []*configutil.Listener{
|
||||
{
|
||||
Type: "tcp",
|
||||
Address: "127.0.0.1:8300",
|
||||
TLSKeyFile: "/path/to/cakey.pem",
|
||||
TLSCertFile: "/path/to/cacert.pem",
|
||||
TLSRequireAndVerifyClientCert: true,
|
||||
},
|
||||
{
|
||||
Type: "unix",
|
||||
Address: "foobar",
|
||||
TLSDisable: true,
|
||||
SocketMode: "configmode",
|
||||
SocketUser: "configuser",
|
||||
SocketGroup: "configgroup",
|
||||
},
|
||||
{
|
||||
Type: "tcp",
|
||||
Address: "127.0.0.1:8400",
|
||||
TLSDisable: true,
|
||||
},
|
||||
}
|
||||
|
||||
agentConfig := newAgentConfig(listeners, true)
|
||||
serverConfig := ServerConfig{AgentConfig: agentConfig}
|
||||
|
||||
_, err := newRunnerConfig(&serverConfig, ctconfig.TemplateConfigs{})
|
||||
if err == nil {
|
||||
t.Fatal("expected error, got none")
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerRun(t *testing.T) {
|
||||
// create http test server
|
||||
mux := http.NewServeMux()
|
||||
|
@ -162,9 +408,11 @@ func TestServerRun(t *testing.T) {
|
|||
ctx, _ := context.WithTimeout(context.Background(), 20*time.Second)
|
||||
sc := ServerConfig{
|
||||
Logger: logging.NewVaultLogger(hclog.Trace),
|
||||
VaultConf: &config.Vault{
|
||||
AgentConfig: &config.Config{
|
||||
Vault: &config.Vault{
|
||||
Address: ts.URL,
|
||||
},
|
||||
},
|
||||
LogLevel: hclog.Trace,
|
||||
LogWriter: hclog.DefaultOutput,
|
||||
ExitAfterAuth: true,
|
||||
|
|
Loading…
Reference in New Issue