Skip to content

Commit

Permalink
Support disable_idle_connections (#366)
Browse files Browse the repository at this point in the history
Adds support for setting `disable_idle_connections` in the injected
agent's config, via an annotation
per-pod (vault.hashicorp.com/agent-disable-idle-connections), or the
AGENT_INJECT_DISABLE_IDLE_CONNECTIONS environment variable that will
affect all injections.
  • Loading branch information
tvoran authored Jul 1, 2022
1 parent 4a523e7 commit 4d93d46
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 18 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## Unreleased

Features:
* Support for setting [`disable_idle_connections`](https://github.com/hashicorp/vault/pull/15986) in the agent config [GH-366](https://github.com/hashicorp/vault-k8s/pull/366)

Improvements:
* Added support to configure default vault namespace on the agent config [GH-345](https://github.com/hashicorp/vault-k8s/pull/345)

Expand Down
8 changes: 8 additions & 0 deletions agent-inject/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ type Agent struct {
// EnableQuit controls whether the quit endpoint is enabled on a localhost
// listener
EnableQuit bool

// DisableIdleConnections controls which Agent features have idle
// connections disabled
DisableIdleConnections []string
}

type ServiceAccountTokenVolume struct {
Expand Down Expand Up @@ -463,6 +467,10 @@ func New(pod *corev1.Pod, patches []*jsonpatch.JsonPatchOperation) (*Agent, erro
return nil, err
}

if pod.Annotations[AnnotationAgentDisableIdleConnections] != "" {
agent.DisableIdleConnections = strings.Split(pod.Annotations[AnnotationAgentDisableIdleConnections], ",")
}

return agent, nil
}

Expand Down
10 changes: 10 additions & 0 deletions agent-inject/agent/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,11 @@ const (
// AnnotationAgentAuthMaxBackoff specifies the maximum backoff duration used when the agent auto auth fails.
// Defaults to 5 minutes.
AnnotationAgentAuthMaxBackoff = "vault.hashicorp.com/auth-max-backoff"

// AnnotationAgentDisableIdleConnections specifies disabling idle connections for various
// features in Vault Agent. Comma-separated string, with valid values auto-auth, caching,
// templating.
AnnotationAgentDisableIdleConnections = "vault.hashicorp.com/agent-disable-idle-connections"
)

type AgentConfig struct {
Expand All @@ -295,6 +300,7 @@ type AgentConfig struct {
StaticSecretRenderInterval string
AuthMinBackoff string
AuthMaxBackoff string
DisableIdleConnections string
}

// Init configures the expected annotations required to create a new instance
Expand Down Expand Up @@ -491,6 +497,10 @@ func Init(pod *corev1.Pod, cfg AgentConfig) error {
pod.ObjectMeta.Annotations[AnnotationAgentAuthMaxBackoff] = cfg.AuthMaxBackoff
}

if _, ok := pod.ObjectMeta.Annotations[AnnotationAgentDisableIdleConnections]; !ok {
pod.ObjectMeta.Annotations[AnnotationAgentDisableIdleConnections] = cfg.DisableIdleConnections
}

return nil
}

Expand Down
48 changes: 39 additions & 9 deletions agent-inject/agent/annotations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

"github.com/hashicorp/vault/sdk/helper/pointerutil"
"github.com/mattbaird/jsonpatch"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -66,7 +67,6 @@ func TestInitCanSet(t *testing.T) {

if raw != tt.annotationValue {
t.Errorf("Default annotation confiured value incorrect, wanted %s, got %s", tt.annotationValue, raw)

}
}
}
Expand Down Expand Up @@ -195,7 +195,6 @@ func TestSecretAnnotationsWithPreserveCaseSensitivityFlagOff(t *testing.T) {

if agent.Secrets[0].Path != tt.expectedPath {
t.Errorf("expected %s, got %s", tt.expectedPath, agent.Secrets[0].Path)

}
} else if len(agent.Secrets) > 0 {
t.Errorf("Secrets length was greater than zero, it shouldn't have been: %s", tt.key)
Expand Down Expand Up @@ -243,7 +242,6 @@ func TestSecretAnnotationsWithPreserveCaseSensitivityFlagOn(t *testing.T) {

if agent.Secrets[0].Path != tt.expectedPath {
t.Errorf("expected %s, got %s", tt.expectedPath, agent.Secrets[0].Path)

}
} else if len(agent.Secrets) > 0 {
t.Error("Secrets length was greater than zero, it shouldn't have been")
Expand Down Expand Up @@ -428,14 +426,14 @@ func TestSecretMixedTemplatesAnnotations(t *testing.T) {
"vault.hashicorp.com/agent-inject-template-file-test2": "",
},
map[string]Secret{
"foobar": Secret{
"foobar": {
Name: "foobar",
Path: "test1",
Template: "",
TemplateFile: "/etc/config.tmpl",
MountPath: secretVolumePath,
},
"test2": Secret{
"test2": {
Name: "test2",
Path: "test2",
Template: "foobarTemplate",
Expand Down Expand Up @@ -817,7 +815,6 @@ func TestVaultNamespaceAnnotation(t *testing.T) {
}

func Test_runAsSameID(t *testing.T) {

tests := []struct {
name string
runAsSameUser string
Expand Down Expand Up @@ -892,7 +889,6 @@ func Test_runAsSameID(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

annotations := map[string]string{}
if len(tt.runAsSameUser) > 0 {
annotations[AnnotationAgentRunAsSameUser] = tt.runAsSameUser
Expand Down Expand Up @@ -1053,10 +1049,8 @@ func TestInjectContainers(t *testing.T) {
output[i].Value = nil
}
require.Equal(t, tt.ExpectedPatch, output)

})
}

}

func TestDefaultTemplateOverride(t *testing.T) {
Expand Down Expand Up @@ -1159,3 +1153,39 @@ func TestAuthMinMaxBackoff(t *testing.T) {
require.Equal(t, "5s", agent.Vault.AuthMinBackoff, "expected 5s, got %v", agent.Vault.AuthMinBackoff)
require.Equal(t, "10s", agent.Vault.AuthMaxBackoff, "expected 10s, got %v", agent.Vault.AuthMaxBackoff)
}

func TestDisableIdleConnections(t *testing.T) {
tests := map[string]struct {
annotations map[string]string
expectedValue []string
}{
"full list": {
annotations: map[string]string{
"vault.hashicorp.com/agent-disable-idle-connections": "auto-auth,caching,templating",
},
expectedValue: []string{"auto-auth", "caching", "templating"},
},
"one": {
annotations: map[string]string{
"vault.hashicorp.com/agent-disable-idle-connections": "auto-auth",
},
expectedValue: []string{"auto-auth"},
},
"none": {
annotations: map[string]string{},
expectedValue: nil,
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
pod := testPod(tc.annotations)
agentConfig := basicAgentConfig()
err := Init(pod, agentConfig)
require.NoError(t, err)
agent, err := New(pod, nil)
require.NoError(t, err)

assert.Equal(t, tc.expectedValue, agent.DisableIdleConnections)
})
}
}
18 changes: 10 additions & 8 deletions agent-inject/agent/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,15 @@ const (
// Config is the top level struct that composes a Vault Agent
// configuration file.
type Config struct {
AutoAuth *AutoAuth `json:"auto_auth"`
ExitAfterAuth bool `json:"exit_after_auth"`
PidFile string `json:"pid_file"`
Vault *VaultConfig `json:"vault"`
Templates []*Template `json:"template,omitempty"`
Listener []*Listener `json:"listener,omitempty"`
Cache *Cache `json:"cache,omitempty"`
TemplateConfig *TemplateConfig `json:"template_config,omitempty"`
AutoAuth *AutoAuth `json:"auto_auth"`
ExitAfterAuth bool `json:"exit_after_auth"`
PidFile string `json:"pid_file"`
Vault *VaultConfig `json:"vault"`
Templates []*Template `json:"template,omitempty"`
Listener []*Listener `json:"listener,omitempty"`
Cache *Cache `json:"cache,omitempty"`
TemplateConfig *TemplateConfig `json:"template_config,omitempty"`
DisableIdleConnections []string `json:"disable_idle_connections,omitempty"`
}

// Vault contains configuration for connecting to Vault servers
Expand Down Expand Up @@ -190,6 +191,7 @@ func (a *Agent) newConfig(init bool) ([]byte, error) {
ExitOnRetryFailure: a.VaultAgentTemplateConfig.ExitOnRetryFailure,
StaticSecretRenderInterval: a.VaultAgentTemplateConfig.StaticSecretRenderInterval,
},
DisableIdleConnections: a.DisableIdleConnections,
}

if a.InjectToken {
Expand Down
2 changes: 2 additions & 0 deletions agent-inject/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ type Handler struct {
StaticSecretRenderInterval string
AuthMinBackoff string
AuthMaxBackoff string
DisableIdleConnections string
}

// Handle is the http.HandlerFunc implementation that actually handles the
Expand Down Expand Up @@ -202,6 +203,7 @@ func (h *Handler) Mutate(req *admissionv1.AdmissionRequest) *admissionv1.Admissi
StaticSecretRenderInterval: h.StaticSecretRenderInterval,
AuthMinBackoff: h.AuthMinBackoff,
AuthMaxBackoff: h.AuthMaxBackoff,
DisableIdleConnections: h.DisableIdleConnections,
}
err = agent.Init(&pod, cfg)
if err != nil {
Expand Down
4 changes: 3 additions & 1 deletion subcommand/injector/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import (
"k8s.io/client-go/informers"
informerv1 "k8s.io/client-go/informers/core/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/listers/admissionregistration/v1"
v1 "k8s.io/client-go/listers/admissionregistration/v1"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/cache"
)
Expand Down Expand Up @@ -71,6 +71,7 @@ type Command struct {
flagTLSCipherSuites string // Comma-separated list of supported cipher suites
flagAuthMinBackoff string // Auth min backoff on failure
flagAuthMaxBackoff string // Auth min backoff on failure
flagDisableIdleConnections string // Idle connections control

flagSet *flag.FlagSet

Expand Down Expand Up @@ -207,6 +208,7 @@ func (c *Command) Run(args []string) int {
StaticSecretRenderInterval: c.flagStaticSecretRenderInterval,
AuthMinBackoff: c.flagAuthMinBackoff,
AuthMaxBackoff: c.flagAuthMaxBackoff,
DisableIdleConnections: c.flagDisableIdleConnections,
}

mux := http.NewServeMux()
Expand Down
9 changes: 9 additions & 0 deletions subcommand/injector/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ type Specification struct {

// AuthMaxBackoff is the AGENT_MAX_BACKOFF environment variable
AuthMaxBackoff string `envconfig:"AGENT_INJECT_AUTH_MAX_BACKOFF"`

// DisableIdleConnections is the AGENT_INJECT_DISABLE_IDLE_CONNECTIONS environment variable
DisableIdleConnections string `split_words:"true"`
}

func (c *Command) init() {
Expand Down Expand Up @@ -183,6 +186,8 @@ func (c *Command) init() {
"Sets the minimum backoff on auto-auth failure. Default is 1s")
c.flagSet.StringVar(&c.flagAuthMaxBackoff, "auth-max-backoff", "",
"Sets the maximum backoff on auto-auth failure. Default is 5m")
c.flagSet.StringVar(&c.flagDisableIdleConnections, "disable-idle-connections", "",
"Comma-separated list of Vault features where idle connections should be disabled.")

tlsVersions := []string{}
for v := range tlsutil.TLSLookup {
Expand Down Expand Up @@ -380,5 +385,9 @@ func (c *Command) parseEnvs() error {
}
}

if envs.DisableIdleConnections != "" {
c.flagDisableIdleConnections = envs.DisableIdleConnections
}

return nil
}
1 change: 1 addition & 0 deletions subcommand/injector/flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ func TestCommandEnvs(t *testing.T) {
{env: "AGENT_INJECT_TLS_CIPHER_SUITES", value: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", cmdPtr: &cmd.flagTLSCipherSuites},
{env: "AGENT_INJECT_AUTH_MIN_BACKOFF", value: "5s", cmdPtr: &cmd.flagAuthMinBackoff},
{env: "AGENT_INJECT_AUTH_MAX_BACKOFF", value: "5s", cmdPtr: &cmd.flagAuthMaxBackoff},
{env: "AGENT_INJECT_DISABLE_IDLE_CONNECTIONS", value: "auto-auth,caching,templating", cmdPtr: &cmd.flagDisableIdleConnections},
}

for _, tt := range tests {
Expand Down

0 comments on commit 4d93d46

Please sign in to comment.