Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add annotations to configure Agent Cache #132

Merged
merged 4 commits into from
Jun 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions agent-inject/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ const (
DefaultAgentRunAsGroup = 1000
DefaultAgentRunAsSameUser = false
DefaultAgentSetSecurityContext = true

DefaultAgentCacheEnable = "false"
DefaultAgentCacheUseAutoAuthToken = "true"
DefaultAgentCacheListenerPort = "8200"
)

// Agent is the top level structure holding all the
Expand Down Expand Up @@ -101,6 +105,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 @@ -185,6 +192,17 @@ type Vault struct {
TLSServerName string
}

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

// ListenerPort is the port the cache should listen to
ListenerPort 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 @@ -277,6 +295,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,
ListenerPort: pod.Annotations[AnnotationAgentCacheListenerPort],
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 @@ -166,6 +166,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"

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

type AgentConfig struct {
Expand Down Expand Up @@ -291,6 +302,18 @@ func Init(pod *corev1.Pod, cfg AgentConfig) error {
pod.ObjectMeta.Annotations[AnnotationAgentSetSecurityContext] = strconv.FormatBool(true)
}

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

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

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

return nil
}

Expand Down Expand Up @@ -464,3 +487,12 @@ func (a *Agent) setSecurityContext() (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 @@ -517,6 +517,18 @@ func TestCouldErrorAnnotations(t *testing.T) {
{AnnotationAgentSetSecurityContext, "false", true},
{AnnotationAgentSetSecurityContext, "secure", false},
{AnnotationAgentSetSecurityContext, "", 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: fmt.Sprintf("127.0.0.1:%s", a.VaultAgentCache.ListenerPort),
TLSDisable: true,
},
}
config.Cache = &Cache{
UseAuthAuthToken: a.VaultAgentCache.UseAutoAuthToken,
}
}

return config.render()
}

Expand Down
109 changes: 109 additions & 0 deletions agent-inject/agent/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,27 @@ 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

agentConfig := AgentConfig{
"foobar-image", "http://foobar:8200", "test", "test", true, "100", "1000",
DefaultAgentRunAsSameUser, DefaultAgentSetSecurityContext,
}
err := Init(pod, agentConfig)
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 +104,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 +141,93 @@ func TestNewConfig(t *testing.T) {
}
}
}

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

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

agentConfig := AgentConfig{
"foobar-image", "http://foobar:8200", "test", "test", true, "100", "1000",
DefaultAgentRunAsSameUser, DefaultAgentSetSecurityContext,
}
err := Init(pod, agentConfig)
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",
AnnotationAgentCacheListenerPort: "8100",
}

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

agentConfig := AgentConfig{
"foobar-image", "http://foobar:8200", "test", "test", true, "100", "1000",
DefaultAgentRunAsSameUser, DefaultAgentSetSecurityContext,
}
err := Init(pod, agentConfig)
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 be 127.0.0.1:8100, got %s", config.Listener[0].Address)
}

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