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 flag and annotation to override default template #242

Merged
merged 8 commits into from
Apr 8, 2021
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
13 changes: 13 additions & 0 deletions agent-inject/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ type Agent struct {
// configure the Vault Agent container.
Annotations map[string]string

// DefaultTemplate is the default template to be used when
// no custom template is specified via annotations.
DefaultTemplate string

// ImageName is the name of the Vault image to use for the
// sidecar container.
ImageName string
Expand Down Expand Up @@ -251,6 +255,7 @@ func New(pod *corev1.Pod, patches []*jsonpatch.JsonPatchOperation) (*Agent, erro
Annotations: pod.Annotations,
ConfigMapName: pod.Annotations[AnnotationAgentConfigMap],
ImageName: pod.Annotations[AnnotationAgentImage],
DefaultTemplate: pod.Annotations[AnnotationAgentInjectDefaultTemplate],
LimitsCPU: pod.Annotations[AnnotationAgentLimitsCPU],
LimitsMem: pod.Annotations[AnnotationAgentLimitsMem],
Namespace: pod.Annotations[AnnotationAgentRequestNamespace],
Expand Down Expand Up @@ -351,6 +356,14 @@ func New(pod *corev1.Pod, patches []*jsonpatch.JsonPatchOperation) (*Agent, erro
return agent, err
}

agent.DefaultTemplate = strings.ToLower(agent.DefaultTemplate)
switch agent.DefaultTemplate {
case "map":
case "json":
default:
return agent, fmt.Errorf("invalid default template type: %s", agent.DefaultTemplate)
}

agent.VaultAgentCache = VaultAgentCache{
Enable: agentCacheEnable,
ListenerPort: pod.Annotations[AnnotationAgentCacheListenerPort],
Expand Down
9 changes: 9 additions & 0 deletions agent-inject/agent/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ const (
// If not provided, a default generic template is used.
AnnotationAgentInjectTemplate = "vault.hashicorp.com/agent-inject-template"

// AnnotationAgentInjectDefaultTemplate sets the default template type. Possible values
// are "json" and "map".
AnnotationAgentInjectDefaultTemplate = "vault.hashicorp.com/agent-inject-default-template"

// AnnotationAgentInjectTemplateFile is the optional key annotation that configures Vault
// Agent what template on disk to use for rendering the secrets. The name
// of the template is any unique string after "vault.hashicorp.com/agent-inject-template-file-",
Expand Down Expand Up @@ -236,6 +240,7 @@ type AgentConfig struct {
SameID bool
SetSecurityContext bool
ProxyAddress string
DefaultTemplate string
ResourceRequestCPU string
ResourceRequestMem string
ResourceLimitCPU string
Expand Down Expand Up @@ -384,6 +389,10 @@ func Init(pod *corev1.Pod, cfg AgentConfig) error {
pod.ObjectMeta.Annotations[AnnotationAgentCacheExitOnErr] = strconv.FormatBool(DefaultAgentCacheExitOnErr)
}

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

return nil
}

Expand Down
201 changes: 124 additions & 77 deletions agent-inject/agent/annotations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,32 @@ import (
"github.com/stretchr/testify/require"
)

func basicAgentConfig() AgentConfig {
return AgentConfig{
Image: "foobar-image",
Address: "http://foobar:8200",
AuthType: DefaultVaultAuthType,
AuthPath: "test",
Namespace: "test",
RevokeOnShutdown: true,
UserID: "100",
GroupID: "1000",
SameID: DefaultAgentRunAsSameUser,
SetSecurityContext: DefaultAgentSetSecurityContext,
ProxyAddress: "http://proxy:3128",
DefaultTemplate: DefaultTemplateType,
ResourceRequestCPU: DefaultResourceRequestCPU,
ResourceRequestMem: DefaultResourceRequestMem,
ResourceLimitCPU: DefaultResourceLimitCPU,
ResourceLimitMem: DefaultResourceLimitMem,
}
}

func TestInitCanSet(t *testing.T) {
annotations := make(map[string]string)
pod := testPod(annotations)

agentConfig := AgentConfig{
"foobar-image", "http://foobar:8200", DefaultVaultAuthType, "test", "test", true, "100", "1000",
DefaultAgentRunAsSameUser, DefaultAgentSetSecurityContext, "http://proxy:3128",
DefaultResourceRequestCPU, DefaultResourceRequestMem, DefaultResourceLimitCPU, DefaultResourceLimitMem,
}
agentConfig := basicAgentConfig()
err := Init(pod, agentConfig)
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
Expand Down Expand Up @@ -56,11 +73,12 @@ func TestInitDefaults(t *testing.T) {
annotations := make(map[string]string)
pod := testPod(annotations)

agentConfig := AgentConfig{
"", "http://foobar:8200", DefaultVaultAuthType, "test", "test", true, "", "",
DefaultAgentRunAsSameUser, DefaultAgentSetSecurityContext, "",
DefaultResourceRequestCPU, DefaultResourceRequestMem, DefaultResourceLimitCPU, DefaultResourceLimitMem,
}
agentConfig := basicAgentConfig()
agentConfig.Image = ""
agentConfig.UserID = ""
agentConfig.GroupID = ""
agentConfig.ProxyAddress = ""

err := Init(pod, agentConfig)
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
Expand Down Expand Up @@ -91,11 +109,9 @@ func TestInitError(t *testing.T) {
annotations := make(map[string]string)
pod := testPod(annotations)

agentConfig := AgentConfig{
"image", "", DefaultVaultAuthType, "authPath", "namespace", true, "100", "1000",
DefaultAgentRunAsSameUser, DefaultAgentSetSecurityContext, "",
DefaultResourceRequestCPU, DefaultResourceRequestMem, DefaultResourceLimitCPU, DefaultResourceLimitMem,
}
agentConfig := basicAgentConfig()
agentConfig.Address = ""

err := Init(pod, agentConfig)
if err == nil {
t.Error("expected error no address, got none")
Expand Down Expand Up @@ -156,11 +172,7 @@ func TestSecretAnnotationsWithPreserveCaseSensitivityFlagOff(t *testing.T) {
pod := testPod(annotation)
var patches []*jsonpatch.JsonPatchOperation

agentConfig := AgentConfig{
"", "http://foobar:8200", DefaultVaultAuthType, "test", "test", true, "100", "1000",
DefaultAgentRunAsSameUser, DefaultAgentSetSecurityContext, "",
DefaultResourceRequestCPU, DefaultResourceRequestMem, DefaultResourceLimitCPU, DefaultResourceLimitMem,
}
agentConfig := basicAgentConfig()
err := Init(pod, agentConfig)
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
Expand Down Expand Up @@ -208,11 +220,7 @@ func TestSecretAnnotationsWithPreserveCaseSensitivityFlagOn(t *testing.T) {
pod := testPod(annotation)
var patches []*jsonpatch.JsonPatchOperation

agentConfig := AgentConfig{
"", "http://foobar:8200", DefaultVaultAuthType, "test", "test", true, "100", "1000",
DefaultAgentRunAsSameUser, DefaultAgentSetSecurityContext, "",
DefaultResourceRequestCPU, DefaultResourceRequestMem, DefaultResourceLimitCPU, DefaultResourceLimitMem,
}
agentConfig := basicAgentConfig()
err := Init(pod, agentConfig)
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
Expand Down Expand Up @@ -296,11 +304,7 @@ func TestSecretLocationFileAnnotations(t *testing.T) {
pod := testPod(tt.annotations)
var patches []*jsonpatch.JsonPatchOperation

agentConfig := AgentConfig{
"", "http://foobar:8200", DefaultVaultAuthType, "test", "test", true, "100", "1000",
DefaultAgentRunAsSameUser, DefaultAgentSetSecurityContext, "",
DefaultResourceRequestCPU, DefaultResourceRequestMem, DefaultResourceLimitCPU, DefaultResourceLimitMem,
}
agentConfig := basicAgentConfig()
err := Init(pod, agentConfig)
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
Expand Down Expand Up @@ -382,11 +386,7 @@ func TestSecretTemplateAnnotations(t *testing.T) {
pod := testPod(tt.annotations)
var patches []*jsonpatch.JsonPatchOperation

agentConfig := AgentConfig{
"", "http://foobar:8200", DefaultVaultAuthType, "test", "test", true, "100", "1000",
DefaultAgentRunAsSameUser, DefaultAgentSetSecurityContext, "",
DefaultResourceRequestCPU, DefaultResourceRequestMem, DefaultResourceLimitCPU, DefaultResourceLimitMem,
}
agentConfig := basicAgentConfig()
err := Init(pod, agentConfig)
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
Expand Down Expand Up @@ -443,11 +443,7 @@ func TestTemplateShortcuts(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
pod := testPod(tt.annotations)
agentConfig := AgentConfig{
"", "http://foobar:8200", DefaultVaultAuthType, "test", "test", true, "100", "1000",
DefaultAgentRunAsSameUser, DefaultAgentSetSecurityContext, "",
DefaultResourceRequestCPU, DefaultResourceRequestMem, DefaultResourceLimitCPU, DefaultResourceLimitMem,
}
agentConfig := basicAgentConfig()
err := Init(pod, agentConfig)
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
Expand Down Expand Up @@ -516,11 +512,7 @@ func TestSecretMixedTemplatesAnnotations(t *testing.T) {
}
for _, tt := range tests {
pod := testPod(tt.annotations)
agentConfig := AgentConfig{
"", "http://foobar:8200", DefaultVaultAuthType, "test", "test", true, "", "",
DefaultAgentRunAsSameUser, DefaultAgentSetSecurityContext, "",
DefaultResourceRequestCPU, DefaultResourceRequestMem, DefaultResourceLimitCPU, DefaultResourceLimitMem,
}
agentConfig := basicAgentConfig()
err := Init(pod, agentConfig)
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
Expand Down Expand Up @@ -581,11 +573,7 @@ func TestSecretTemplateFileAnnotations(t *testing.T) {
pod := testPod(tt.annotations)
var patches []*jsonpatch.JsonPatchOperation

agentConfig := AgentConfig{
"", "http://foobar:8200", DefaultVaultAuthType, "test", "test", true, "", "",
DefaultAgentRunAsSameUser, DefaultAgentSetSecurityContext, "",
DefaultResourceRequestCPU, DefaultResourceRequestMem, DefaultResourceLimitCPU, DefaultResourceLimitMem,
}
agentConfig := basicAgentConfig()
err := Init(pod, agentConfig)
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
Expand Down Expand Up @@ -637,11 +625,7 @@ func TestSecretCommandAnnotations(t *testing.T) {

for _, tt := range tests {
pod := testPod(tt.annotations)
agentConfig := AgentConfig{
"", "http://foobar:8200", DefaultVaultAuthType, "test", "test", true, "100", "1000",
DefaultAgentRunAsSameUser, DefaultAgentSetSecurityContext, "",
DefaultResourceRequestCPU, DefaultResourceRequestMem, DefaultResourceLimitCPU, DefaultResourceLimitMem,
}
agentConfig := basicAgentConfig()
err := Init(pod, agentConfig)
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
Expand Down Expand Up @@ -770,12 +754,7 @@ func TestCouldErrorAnnotations(t *testing.T) {
annotations := map[string]string{tt.key: tt.value}
pod := testPod(annotations)
var patches []*jsonpatch.JsonPatchOperation

agentConfig := AgentConfig{
"", "http://foobar:8200", DefaultVaultAuthType, "test", "test", true, "100", "1000",
DefaultAgentRunAsSameUser, DefaultAgentSetSecurityContext, "",
DefaultResourceRequestCPU, DefaultResourceRequestMem, DefaultResourceLimitCPU, DefaultResourceLimitMem,
}
agentConfig := basicAgentConfig()
err := Init(pod, agentConfig)
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
Expand All @@ -792,12 +771,7 @@ func TestCouldErrorAnnotations(t *testing.T) {

func TestInitEmptyPod(t *testing.T) {
var pod *corev1.Pod

agentConfig := AgentConfig{
"foobar-image", "http://foobar:8200", DefaultVaultAuthType, "test", "test", true, "100", "1000",
DefaultAgentRunAsSameUser, DefaultAgentSetSecurityContext, "",
DefaultResourceRequestCPU, DefaultResourceRequestMem, DefaultResourceLimitCPU, DefaultResourceLimitMem,
}
agentConfig := basicAgentConfig()
err := Init(pod, agentConfig)
if err == nil {
t.Errorf("got no error, should have")
Expand All @@ -823,11 +797,7 @@ func TestVaultNamespaceAnnotation(t *testing.T) {
pod := testPod(annotation)
var patches []*jsonpatch.JsonPatchOperation

agentConfig := AgentConfig{
"foobar-image", "http://foobar:8200", DefaultVaultAuthType, "test", "test", true, "100", "1000",
DefaultAgentRunAsSameUser, DefaultAgentSetSecurityContext, "",
DefaultResourceRequestCPU, DefaultResourceRequestMem, DefaultResourceLimitCPU, DefaultResourceLimitMem,
}
agentConfig := basicAgentConfig()
err := Init(pod, agentConfig)
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
Expand Down Expand Up @@ -984,11 +954,7 @@ func TestAuthConfigAnnotations(t *testing.T) {
pod := testPod(tt.annotations)
var patches []*jsonpatch.JsonPatchOperation

agentConfig := AgentConfig{
"", "http://foobar:8200", DefaultVaultAuthType, "test", "test", true, "100", "1000",
DefaultAgentRunAsSameUser, DefaultAgentSetSecurityContext, "",
DefaultResourceRequestCPU, DefaultResourceRequestMem, DefaultResourceLimitCPU, DefaultResourceLimitMem,
}
agentConfig := basicAgentConfig()
err := Init(pod, agentConfig)
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
Expand All @@ -1002,3 +968,84 @@ func TestAuthConfigAnnotations(t *testing.T) {
require.Equal(t, agent.Vault.AuthConfig, tt.expectedAuthConfig, "expected AuthConfig %v, got %v", tt.expectedAuthConfig, agent.Vault.AuthConfig)
}
}

func TestDefaultTemplateOverride(t *testing.T) {
tests := []struct {
annotations map[string]string
expectedValue string
expectedErr bool
}{
{
map[string]string{
"vault.hashicorp.com/agent-inject-default-template": "json",
},
"json",
false,
},
{
map[string]string{
"vault.hashicorp.com/agent-inject-default-template": "JSON",
},
"json",
false,
},
{
map[string]string{
"vault.hashicorp.com/agent-inject-default-template": "map",
},
"map",
false,
},
{
map[string]string{
"vault.hashicorp.com/agent-inject-default-template": "MAP",
},
"map",
false,
},
{
map[string]string{
"vault.hashicorp.com/agent-inject-default-template": "foobar",
},
"",
true,
},
{
map[string]string{
"vault.hashicorp.com/agent-inject-default-template": "jsn",
},
"",
true,
},
{
map[string]string{
"vault.hashicorp.com/agent-inject-default-template": "",
},
"",
true,
},
}

for _, tt := range tests {
pod := testPod(tt.annotations)
var patches []*jsonpatch.JsonPatchOperation

agentConfig := basicAgentConfig()
err := Init(pod, agentConfig)
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
}

agent, err := New(pod, patches)
if err != nil && !tt.expectedErr {
t.Errorf("got error, shouldn't have: %s", err)
} else if err == nil && tt.expectedErr {
t.Error("got no error, should have")
}

if !tt.expectedErr {
require.Equal(t, agent.DefaultTemplate, tt.expectedValue,
"expected %v, got %v", tt.expectedValue, agent.DefaultTemplate)
}
}
}
Loading