agent: add disable_keep_alives configurable (#16479)

agent: add disable_keep_alives config

Co-authored-by: Christopher Swenson <christopher.swenson@hashicorp.com>
This commit is contained in:
Jason O'Donnell 2022-07-28 15:59:49 -04:00 committed by GitHub
parent 6be7c6610e
commit e3f942f51c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 551 additions and 12 deletions

View File

@ -756,6 +756,24 @@ func (c *Client) MaxIdleConnections() int {
return c.config.HttpClient.Transport.(*http.Transport).MaxIdleConns
}
func (c *Client) SetDisableKeepAlives(disable bool) {
c.modifyLock.RLock()
defer c.modifyLock.RUnlock()
c.config.modifyLock.Lock()
defer c.config.modifyLock.Unlock()
c.config.HttpClient.Transport.(*http.Transport).DisableKeepAlives = disable
}
func (c *Client) DisableKeepAlives() bool {
c.modifyLock.RLock()
defer c.modifyLock.RUnlock()
c.config.modifyLock.RLock()
defer c.config.modifyLock.RUnlock()
return c.config.HttpClient.Transport.(*http.Transport).DisableKeepAlives
}
func (c *Client) MaxRetries() int {
c.modifyLock.RLock()
defer c.modifyLock.RUnlock()

3
changelog/16479.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
agent: Added `disable_keep_alives` configuration to disable keep alives in auto-auth, caching and templating.
```

View File

@ -379,6 +379,10 @@ func (c *AgentCommand) Run(args []string) int {
sinkClient.SetMaxIdleConnections(-1)
}
if config.DisableKeepAlivesAutoAuth {
sinkClient.SetDisableKeepAlives(true)
}
for _, sc := range config.AutoAuth.Sinks {
switch sc.Type {
case "file":
@ -507,10 +511,14 @@ func (c *AgentCommand) Run(args []string) int {
return 1
}
if config.DisableIdleConnsAutoAuth {
if config.DisableIdleConnsCaching {
proxyClient.SetMaxIdleConnections(-1)
}
if config.DisableKeepAlivesCaching {
proxyClient.SetDisableKeepAlives(true)
}
// Create the API proxier
apiProxy, err := cache.NewAPIProxy(&cache.APIProxyConfig{
Client: proxyClient,
@ -824,6 +832,10 @@ func (c *AgentCommand) Run(args []string) int {
ahClient.SetMaxIdleConnections(-1)
}
if config.DisableKeepAlivesAutoAuth {
ahClient.SetDisableKeepAlives(true)
}
ah := auth.NewAuthHandler(&auth.AuthHandlerConfig{
Logger: c.logger.Named("auth.handler"),
Client: ahClient,

View File

@ -24,19 +24,26 @@ import (
type Config struct {
*configutil.SharedConfig `hcl:"-"`
AutoAuth *AutoAuth `hcl:"auto_auth"`
ExitAfterAuth bool `hcl:"exit_after_auth"`
Cache *Cache `hcl:"cache"`
Vault *Vault `hcl:"vault"`
TemplateConfig *TemplateConfig `hcl:"template_config"`
Templates []*ctconfig.TemplateConfig `hcl:"templates"`
DisableIdleConns []string `hcl:"disable_idle_connections"`
DisableIdleConnsCaching bool `hcl:"-"`
DisableIdleConnsTemplating bool `hcl:"-"`
DisableIdleConnsAutoAuth bool `hcl:"-"`
AutoAuth *AutoAuth `hcl:"auto_auth"`
ExitAfterAuth bool `hcl:"exit_after_auth"`
Cache *Cache `hcl:"cache"`
Vault *Vault `hcl:"vault"`
TemplateConfig *TemplateConfig `hcl:"template_config"`
Templates []*ctconfig.TemplateConfig `hcl:"templates"`
DisableIdleConns []string `hcl:"disable_idle_connections"`
DisableIdleConnsCaching bool `hcl:"-"`
DisableIdleConnsTemplating bool `hcl:"-"`
DisableIdleConnsAutoAuth bool `hcl:"-"`
DisableKeepAlives []string `hcl:"disable_keep_alives"`
DisableKeepAlivesCaching bool `hcl:"-"`
DisableKeepAlivesTemplating bool `hcl:"-"`
DisableKeepAlivesAutoAuth bool `hcl:"-"`
}
const DisableIdleConnsEnv = "VAULT_AGENT_DISABLE_IDLE_CONNECTIONS"
const (
DisableIdleConnsEnv = "VAULT_AGENT_DISABLE_IDLE_CONNECTIONS"
DisableKeepAlivesEnv = "VAULT_AGENT_DISABLE_KEEP_ALIVES"
)
func (c *Config) Prune() {
for _, l := range c.Listeners {
@ -288,6 +295,28 @@ func LoadConfig(path string) (*Config, error) {
}
}
if disableKeepAlivesEnv := os.Getenv(DisableKeepAlivesEnv); disableKeepAlivesEnv != "" {
result.DisableKeepAlives, err = parseutil.ParseCommaStringSlice(strings.ToLower(disableKeepAlivesEnv))
if err != nil {
return nil, fmt.Errorf("error parsing environment variable %s: %v", DisableKeepAlivesEnv, err)
}
}
for _, subsystem := range result.DisableKeepAlives {
switch subsystem {
case "auto-auth":
result.DisableKeepAlivesAutoAuth = true
case "caching":
result.DisableKeepAlivesCaching = true
case "templating":
result.DisableKeepAlivesTemplating = true
case "":
continue
default:
return nil, fmt.Errorf("unknown disable_keep_alives value: %s", subsystem)
}
}
return result, nil
}

View File

@ -1344,3 +1344,310 @@ func TestLoadConfigFile_Bad_Value_Disable_Idle_Conns(t *testing.T) {
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")
if err != nil {
t.Fatal(err)
}
expected := &Config{
SharedConfig: &configutil.SharedConfig{
PidFile: "./pidfile",
},
DisableKeepAlives: []string{"auto-auth", "caching", "templating"},
DisableKeepAlivesCaching: true,
DisableKeepAlivesAutoAuth: true,
DisableKeepAlivesTemplating: true,
AutoAuth: &AutoAuth{
Method: &Method{
Type: "aws",
MountPath: "auth/aws",
Namespace: "my-namespace/",
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",
},
},
},
},
Vault: &Vault{
Address: "http://127.0.0.1:1111",
Retry: &Retry{
ctconfig.DefaultRetryAttempts,
},
},
}
config.Prune()
if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
}
func TestLoadConfigFile_Disable_Keep_Alives_Auto_Auth(t *testing.T) {
config, err := LoadConfig("./test-fixtures/config-disable-keep-alives-auto-auth.hcl")
if err != nil {
t.Fatal(err)
}
expected := &Config{
SharedConfig: &configutil.SharedConfig{
PidFile: "./pidfile",
},
DisableKeepAlives: []string{"auto-auth"},
DisableKeepAlivesCaching: false,
DisableKeepAlivesAutoAuth: true,
DisableKeepAlivesTemplating: false,
AutoAuth: &AutoAuth{
Method: &Method{
Type: "aws",
MountPath: "auth/aws",
Namespace: "my-namespace/",
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",
},
},
},
},
Vault: &Vault{
Address: "http://127.0.0.1:1111",
Retry: &Retry{
ctconfig.DefaultRetryAttempts,
},
},
}
config.Prune()
if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
}
func TestLoadConfigFile_Disable_Keep_Alives_Templating(t *testing.T) {
config, err := LoadConfig("./test-fixtures/config-disable-keep-alives-templating.hcl")
if err != nil {
t.Fatal(err)
}
expected := &Config{
SharedConfig: &configutil.SharedConfig{
PidFile: "./pidfile",
},
DisableKeepAlives: []string{"templating"},
DisableKeepAlivesCaching: false,
DisableKeepAlivesAutoAuth: false,
DisableKeepAlivesTemplating: true,
AutoAuth: &AutoAuth{
Method: &Method{
Type: "aws",
MountPath: "auth/aws",
Namespace: "my-namespace/",
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",
},
},
},
},
Vault: &Vault{
Address: "http://127.0.0.1:1111",
Retry: &Retry{
ctconfig.DefaultRetryAttempts,
},
},
}
config.Prune()
if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
}
func TestLoadConfigFile_Disable_Keep_Alives_Caching(t *testing.T) {
config, err := LoadConfig("./test-fixtures/config-disable-keep-alives-caching.hcl")
if err != nil {
t.Fatal(err)
}
expected := &Config{
SharedConfig: &configutil.SharedConfig{
PidFile: "./pidfile",
},
DisableKeepAlives: []string{"caching"},
DisableKeepAlivesCaching: true,
DisableKeepAlivesAutoAuth: false,
DisableKeepAlivesTemplating: false,
AutoAuth: &AutoAuth{
Method: &Method{
Type: "aws",
MountPath: "auth/aws",
Namespace: "my-namespace/",
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",
},
},
},
},
Vault: &Vault{
Address: "http://127.0.0.1:1111",
Retry: &Retry{
ctconfig.DefaultRetryAttempts,
},
},
}
config.Prune()
if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
}
func TestLoadConfigFile_Disable_Keep_Alives_Empty(t *testing.T) {
config, err := LoadConfig("./test-fixtures/config-disable-keep-alives-empty.hcl")
if err != nil {
t.Fatal(err)
}
expected := &Config{
SharedConfig: &configutil.SharedConfig{
PidFile: "./pidfile",
},
DisableKeepAlives: []string{},
DisableKeepAlivesCaching: false,
DisableKeepAlivesAutoAuth: false,
DisableKeepAlivesTemplating: false,
AutoAuth: &AutoAuth{
Method: &Method{
Type: "aws",
MountPath: "auth/aws",
Namespace: "my-namespace/",
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",
},
},
},
},
Vault: &Vault{
Address: "http://127.0.0.1:1111",
Retry: &Retry{
ctconfig.DefaultRetryAttempts,
},
},
}
config.Prune()
if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
}
func TestLoadConfigFile_Disable_Keep_Alives_Env(t *testing.T) {
err := os.Setenv(DisableKeepAlivesEnv, "auto-auth,caching,templating")
defer os.Unsetenv(DisableKeepAlivesEnv)
if err != nil {
t.Fatal(err)
}
config, err := LoadConfig("./test-fixtures/config-disable-keep-alives-empty.hcl")
if err != nil {
t.Fatal(err)
}
expected := &Config{
SharedConfig: &configutil.SharedConfig{
PidFile: "./pidfile",
},
DisableKeepAlives: []string{"auto-auth", "caching", "templating"},
DisableKeepAlivesCaching: true,
DisableKeepAlivesAutoAuth: true,
DisableKeepAlivesTemplating: true,
AutoAuth: &AutoAuth{
Method: &Method{
Type: "aws",
MountPath: "auth/aws",
Namespace: "my-namespace/",
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",
},
},
},
},
Vault: &Vault{
Address: "http://127.0.0.1:1111",
Retry: &Retry{
ctconfig.DefaultRetryAttempts,
},
},
}
config.Prune()
if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
}
func TestLoadConfigFile_Bad_Value_Disable_Keep_Alives(t *testing.T) {
_, err := LoadConfig("./test-fixtures/bad-config-disable-keep-alives.hcl")
if err == nil {
t.Fatal("should have error, it didn't")
}
}

View File

@ -0,0 +1,27 @@
pid_file = "./pidfile"
disable_keep_alives = ["foo","caching","templating"]
auto_auth {
method {
type = "aws"
namespace = "my-namespace/"
config = {
role = "foobar"
}
}
sink {
type = "file"
config = {
path = "/tmp/file-foo"
}
aad = "foobar"
dh_type = "curve25519"
dh_path = "/tmp/file-foo-dhpath"
}
}
vault {
address = "http://127.0.0.1:1111"
}

View File

@ -0,0 +1,27 @@
pid_file = "./pidfile"
disable_keep_alives = ["auto-auth","caching","templating"]
auto_auth {
method {
type = "aws"
namespace = "my-namespace/"
config = {
role = "foobar"
}
}
sink {
type = "file"
config = {
path = "/tmp/file-foo"
}
aad = "foobar"
dh_type = "curve25519"
dh_path = "/tmp/file-foo-dhpath"
}
}
vault {
address = "http://127.0.0.1:1111"
}

View File

@ -0,0 +1,27 @@
pid_file = "./pidfile"
disable_keep_alives = ["auto-auth"]
auto_auth {
method {
type = "aws"
namespace = "my-namespace/"
config = {
role = "foobar"
}
}
sink {
type = "file"
config = {
path = "/tmp/file-foo"
}
aad = "foobar"
dh_type = "curve25519"
dh_path = "/tmp/file-foo-dhpath"
}
}
vault {
address = "http://127.0.0.1:1111"
}

View File

@ -0,0 +1,27 @@
pid_file = "./pidfile"
disable_keep_alives = ["caching"]
auto_auth {
method {
type = "aws"
namespace = "my-namespace/"
config = {
role = "foobar"
}
}
sink {
type = "file"
config = {
path = "/tmp/file-foo"
}
aad = "foobar"
dh_type = "curve25519"
dh_path = "/tmp/file-foo-dhpath"
}
}
vault {
address = "http://127.0.0.1:1111"
}

View File

@ -0,0 +1,27 @@
pid_file = "./pidfile"
disable_keep_alives = []
auto_auth {
method {
type = "aws"
namespace = "my-namespace/"
config = {
role = "foobar"
}
}
sink {
type = "file"
config = {
path = "/tmp/file-foo"
}
aad = "foobar"
dh_type = "curve25519"
dh_path = "/tmp/file-foo-dhpath"
}
}
vault {
address = "http://127.0.0.1:1111"
}

View File

@ -0,0 +1,27 @@
pid_file = "./pidfile"
disable_keep_alives = ["templating"]
auto_auth {
method {
type = "aws"
namespace = "my-namespace/"
config = {
role = "foobar"
}
}
sink {
type = "file"
config = {
path = "/tmp/file-foo"
}
aad = "foobar"
dh_type = "curve25519"
dh_path = "/tmp/file-foo-dhpath"
}
}
vault {
address = "http://127.0.0.1:1111"
}

View File

@ -250,6 +250,10 @@ func newRunnerConfig(sc *ServerConfig, templates ctconfig.TemplateConfigs) (*ctc
conf.Vault.Transport.MaxIdleConns = &idleConns
}
if sc.AgentConfig.DisableKeepAlivesTemplating {
conf.Vault.Transport.DisableKeepAlives = pointerutil.BoolPtr(true)
}
conf.Vault.SSL = &ctconfig.SSLConfig{
Enabled: pointerutil.BoolPtr(false),
Verify: pointerutil.BoolPtr(false),

View File

@ -148,6 +148,10 @@ These are the currently-available general configuration option:
Valid values include: `auto-auth`, `caching` and `templating`. Can also be configured by setting the `VAULT_AGENT_DISABLE_IDLE_CONNECTIONS`
environment variable as a comma separated string. This environment variable will override any values found in a configuration file.
- `disable_keep_alives` `(string array: [])` - A list of strings that disables keep alives for various features in Vault Agent.
Valid values include: `auto-auth`, `caching` and `templating`. Can also be configured by setting the `VAULT_AGENT_DISABLE_KEEP_ALIVES`
environment variable as a comma separated string. This environment variable will override any values found in a configuration file.
- `template` <code>([template][template]: <optional\>)</code> - Specifies options used for templating Vault secrets to files.
- `template_config` <code>([template_config][template-config]: <optional\>)</code> - Specifies templating engine behavior.