Skip to content

Commit

Permalink
Add annotations to configure Agent Cache
Browse files Browse the repository at this point in the history
- TLS is always disabled because there is no way to mount arbitrary
volumes to the agent sidecar container
  • Loading branch information
lawliet89 committed May 6, 2020
1 parent ceb7ea1 commit 5fe1803
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 0 deletions.
29 changes: 29 additions & 0 deletions agent-inject/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ const (
DefaultVaultAuthPath = "auth/kubernetes"
DefaultAgentRunAsUser = 100
DefaultAgentRunAsGroup = 1000

DefaultAgentCacheEnable = "false"
DefaultAgentCacheUseAutoAuthToken = "true"
DefaultAgentCacheListenerAddress = "127.0.0.1:8200"
)

// Agent is the top level structure holding all the
Expand Down Expand Up @@ -99,6 +103,9 @@ type Agent struct {
// Vault is the structure holding all the Vault specific configurations.
Vault Vault

// VaultAgentCache is the structure holding the Vault agent cache specific configurations
VaultAgentCache VaultAgentCache

// RunAsUser is the user ID to run the Vault agent container(s) as.
RunAsUser int64

Expand Down Expand Up @@ -175,6 +182,17 @@ type Vault struct {
TLSServerName string
}

type VaultAgentCache struct {
// Enable configures whether the cache is enabled or not
Enable bool

// ListenerAddress is the address the cache should listen to
ListenerAddress string

// UseAutoAuthToken configures whether the auto auth token is used in cache requests
UseAutoAuthToken string
}

// New creates a new instance of Agent by parsing all the Kubernetes annotations.
func New(pod *corev1.Pod, patches []*jsonpatch.JsonPatchOperation) (*Agent, error) {
saName, saPath := serviceaccount(pod)
Expand Down Expand Up @@ -257,6 +275,17 @@ func New(pod *corev1.Pod, patches []*jsonpatch.JsonPatchOperation) (*Agent, erro
return agent, err
}

agentCacheEnable, err := agent.agentCacheEnable()
if err != nil {
return agent, err
}

agent.VaultAgentCache = VaultAgentCache{
Enable: agentCacheEnable,
ListenerAddress: pod.Annotations[AnnotationAgentCacheListenerAddress],
UseAutoAuthToken: pod.Annotations[AnnotationAgentCacheUseAutoAuthToken],
}

return agent, nil
}

Expand Down
32 changes: 32 additions & 0 deletions agent-inject/agent/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,17 @@ const (
// AnnotationPreserveSecretCase if enabled will preserve the case of secret name
// by default the name is converted to lower case.
AnnotationPreserveSecretCase = "vault.hashicorp.com/preserve-secret-case"

// AnnotationAgentCacheEnable if enabled will configure the sidecar container
// to enable agent caching
AnnotationAgentCacheEnable = "vault.hashicorp.com/agent-cache-enable"

// AnnotationAgentCacheUseAutoAuthToken configures the agent cache to use the
// auto auth token or not. Can be set to "force" to force usage of the auto-auth token
AnnotationAgentCacheUseAutoAuthToken = "vault.hashicorp.com/agent-cache-use-auth-auth-token"

// AnnotationAgentCacheListenerAddress configures the address the agent cache should listen on
AnnotationAgentCacheListenerAddress = "vault.hashicorp.com/agent-cache-listener-address"
)

type AgentConfig struct {
Expand Down Expand Up @@ -257,6 +268,18 @@ func Init(pod *corev1.Pod, cfg AgentConfig) error {
pod.ObjectMeta.Annotations[AnnotationAgentRunAsGroup] = cfg.GroupID
}

if _, ok := pod.ObjectMeta.Annotations[AnnotationAgentCacheEnable]; !ok {
pod.ObjectMeta.Annotations[AnnotationAgentCacheEnable] = DefaultAgentCacheEnable
}

if _, ok := pod.ObjectMeta.Annotations[AnnotationAgentCacheListenerAddress]; !ok {
pod.ObjectMeta.Annotations[AnnotationAgentCacheListenerAddress] = DefaultAgentCacheListenerAddress
}

if _, ok := pod.ObjectMeta.Annotations[AnnotationAgentCacheUseAutoAuthToken]; !ok {
pod.ObjectMeta.Annotations[AnnotationAgentCacheUseAutoAuthToken] = DefaultAgentCacheUseAutoAuthToken
}

return nil
}

Expand Down Expand Up @@ -394,3 +417,12 @@ func (a *Agent) preserveSecretCase(secretName string) (bool, error) {
}
return strconv.ParseBool(raw)
}

func (a *Agent) agentCacheEnable() (bool, error) {
raw, ok := a.Annotations[AnnotationAgentCacheEnable]
if !ok {
return false, nil
}

return strconv.ParseBool(raw)
}
12 changes: 12 additions & 0 deletions agent-inject/agent/annotations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,18 @@ func TestCouldErrorAnnotations(t *testing.T) {
{AnnotationAgentRunAsGroup, "0", true},
{AnnotationAgentRunAsGroup, "100", true},
{AnnotationAgentRunAsGroup, "root", false},

{AnnotationAgentCacheEnable, "true", true},
{AnnotationAgentCacheEnable, "false", true},
{AnnotationAgentCacheEnable, "TRUE", true},
{AnnotationAgentCacheEnable, "FALSE", true},
{AnnotationAgentCacheEnable, "0", true},
{AnnotationAgentCacheEnable, "1", true},
{AnnotationAgentCacheEnable, "t", true},
{AnnotationAgentCacheEnable, "f", true},
{AnnotationAgentCacheEnable, "tRuE", false},
{AnnotationAgentCacheEnable, "fAlSe", false},
{AnnotationAgentCacheEnable, "", false},
}

for i, tt := range tests {
Expand Down
27 changes: 27 additions & 0 deletions agent-inject/agent/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ type Config struct {
PidFile string `json:"pid_file"`
Vault *VaultConfig `json:"vault"`
Templates []*Template `json:"template"`
Listener []*Listener `json:"listener,omitempty"`
Cache *Cache `json:"cache,omitempty"`
}

// Vault contains configuration for connecting to Vault servers
Expand Down Expand Up @@ -73,6 +75,18 @@ type Template struct {
Command string `json:"command,omitempty"`
}

// Listener defines the configuration for Vault Agent Cache Listener
type Listener struct {
Type string `json:"type"`
Address string `json:"address"`
TLSDisable bool `json:"tls_disable"`
}

// Cache defines the configuration for the Vault Agent Cache
type Cache struct {
UseAuthAuthToken string `json:"use_auto_auth_token"`
}

func (a *Agent) newTemplateConfigs() []*Template {
var templates []*Template
for _, secret := range a.Secrets {
Expand Down Expand Up @@ -127,6 +141,19 @@ func (a *Agent) newConfig(init bool) ([]byte, error) {
Templates: a.newTemplateConfigs(),
}

if a.VaultAgentCache.Enable && !init {
config.Listener = []*Listener{
{
Type: "tcp",
Address: a.VaultAgentCache.ListenerAddress,
TLSDisable: true,
},
}
config.Cache = &Cache{
UseAuthAuthToken: a.VaultAgentCache.UseAutoAuthToken,
}
}

return config.render()
}

Expand Down
97 changes: 97 additions & 0 deletions agent-inject/agent/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,23 @@ func TestNewConfig(t *testing.T) {
fmt.Sprintf("%s-%s", AnnotationVaultSecretVolumePath, "different-path"): "/etc/container_environment",

"vault.hashicorp.com/agent-inject-command-bar": "pkill -HUP app",

AnnotationAgentCacheEnable: "true",
}

pod := testPod(annotations)
var patches []*jsonpatch.JsonPatchOperation

err := Init(pod, AgentConfig{"foobar-image", "http://foobar:8200", "test", "test", true, "1000", "100"})
if err != nil {
t.Errorf("got error initialising pod, shouldn't have: %s", err)
}

agent, err := New(pod, patches)
if err != nil {
t.Errorf("got error creating agent, shouldn't have: %s", err)
}

cfg, err := agent.newConfig(true)
if err != nil {
t.Errorf("got error creating Vault config, shouldn't have: %s", err)
Expand Down Expand Up @@ -89,6 +100,10 @@ func TestNewConfig(t *testing.T) {
t.Errorf("auto_auth mount path: expected path to be %s, got %s", annotations[AnnotationVaultAuthPath], config.AutoAuth.Method.MountPath)
}

if len(config.Listener) != 0 || config.Cache != nil {
t.Error("agent Cache should be disabled for init containers")
}

if len(config.Templates) != 3 {
t.Errorf("expected 3 template, got %d", len(config.Templates))
}
Expand Down Expand Up @@ -122,3 +137,85 @@ func TestNewConfig(t *testing.T) {
}
}
}

func TestConfigVaultAgentCacheNotEnabledByDefault(t *testing.T) {
annotations := map[string]string{}

pod := testPod(annotations)
var patches []*jsonpatch.JsonPatchOperation

err := Init(pod, AgentConfig{"foobar-image", "http://foobar:8200", "test", "test", true, "1000", "100"})
if err != nil {
t.Errorf("got error initialising pod, shouldn't have: %s", err)
}

agent, err := New(pod, patches)
if err != nil {
t.Errorf("got error creating agent, shouldn't have: %s", err)
}

cfg, err := agent.newConfig(false)
if err != nil {
t.Errorf("got error creating Vault config, shouldn't have: %s", err)
}

config := &Config{}
if err := json.Unmarshal(cfg, config); err != nil {
t.Errorf("got error unmarshalling Vault config, shouldn't have: %s", err)
}

if len(config.Listener) != 0 || config.Cache != nil {
t.Error("agent Cache should be not be enabled by default")
}
}

func TestConfigVaultAgentCache(t *testing.T) {
annotations := map[string]string{
AnnotationAgentCacheEnable: "true",
AnnotationAgentCacheUseAutoAuthToken: "force",
AnnotationAgentCacheListenerAddress: "127.0.0.1:8100",
}

pod := testPod(annotations)
var patches []*jsonpatch.JsonPatchOperation

err := Init(pod, AgentConfig{"foobar-image", "http://foobar:8200", "test", "test", true, "1000", "100"})
if err != nil {
t.Errorf("got error initialising pod, shouldn't have: %s", err)
}

agent, err := New(pod, patches)
if err != nil {
t.Errorf("got error creating agent, shouldn't have: %s", err)
}

cfg, err := agent.newConfig(false)
if err != nil {
t.Errorf("got error creating Vault config, shouldn't have: %s", err)
}

config := &Config{}
if err := json.Unmarshal(cfg, config); err != nil {
t.Errorf("got error unmarshalling Vault config, shouldn't have: %s", err)
}

if len(config.Listener) == 0 || config.Cache == nil {
t.Error("agent Cache should be enabled")
}

if config.Cache.UseAuthAuthToken != "force" {
t.Errorf("agent Cache use_auto_auth_token should be 'force', got %s instead", config.Cache.UseAuthAuthToken)
}

if config.Listener[0].Type != "tcp" {
t.Errorf("agent Cache listener type should be tcp, got %s instead", config.Listener[0].Type)
}

if config.Listener[0].Address != "127.0.0.1:8100" {
t.Errorf("agent Cache listener address should be127.0.0.1:8100, got %s", config.Listener[0].Address)
}

if !config.Listener[0].TLSDisable {
t.Error("agent Cache listener TLS should be disabled")
}
}

0 comments on commit 5fe1803

Please sign in to comment.