Skip to content

Commit

Permalink
add command annotation for configuring a command to execute after sec…
Browse files Browse the repository at this point in the history
…ret rendering
  • Loading branch information
joemiller committed Feb 20, 2020
1 parent 517f85b commit a6e370c
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 2 deletions.
5 changes: 4 additions & 1 deletion agent-inject/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
// TODO swap out 'github.com/mattbaird/jsonpatch' for 'github.com/evanphx/json-patch'

const (
DefaultVaultImage = "vault:1.3.1"
DefaultVaultImage = "vault:1.3.1"
DefaultVaultAuthPath = "auth/kubernetes"
)

Expand Down Expand Up @@ -96,6 +96,9 @@ type Secret struct {

// Template is the optional custom template to use when rendering the secret.
Template string

// Command is the optional command to run after rendering the secret.
Command string
}

type Vault struct {
Expand Down
16 changes: 15 additions & 1 deletion agent-inject/agent/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ const (
// from auth/token/lookup-self
AnnotationAgentInjectToken = "vault.hashicorp.com/agent-inject-token"

// AnnotationAgentInjectCommand is the key annotation that configures Vault Agent
// to run a command after the secret is rendered. The name of the template is any
// unique string after "vault.hashicorp.com/agent-inject-command-". This should map
// to the same unique value provided in ""vault.hashicorp.com/agent-inject-secret-".
// If not provided (the default), no command is executed.
AnnotationAgentInjectCommand = "vault.hashicorp.com/agent-inject-command"

// AnnotationAgentImage is the name of the Vault docker image to use.
AnnotationAgentImage = "vault.hashicorp.com/agent-image"

Expand Down Expand Up @@ -210,7 +217,14 @@ func secrets(annotations map[string]string) []*Secret {
template = val
}

secrets = append(secrets, &Secret{Name: name, Path: path, Template: template})
var command string
commandName := fmt.Sprintf("%s-%s", AnnotationAgentInjectCommand, raw)

if val, ok := annotations[commandName]; ok {
command = val
}

secrets = append(secrets, &Secret{Name: name, Path: path, Template: template, Command: command})
}
}
return secrets
Expand Down
43 changes: 43 additions & 0 deletions agent-inject/agent/annotations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,49 @@ func TestTemplateShortcuts(t *testing.T) {
}
}

func TestSecretCommandAnnotations(t *testing.T) {
tests := []struct {
annotations map[string]string
expectedKey string
expectedCommand string
}{
{
map[string]string{
"vault.hashicorp.com/agent-inject-secret-foobar": "test1",
"vault.hashicorp.com/agent-inject-command-foobar": "pkill -HUP nginx",
}, "foobar", "pkill -HUP nginx",
},
{
map[string]string{
"vault.hashicorp.com/agent-inject-secret-foobar": "test2",
"vault.hashicorp.com/agent-inject-command-foobar2": "pkill -HUP nginx",
}, "foobar", "",
},
}

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

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

if len(agent.Secrets) == 0 {
t.Error("Secrets length was zero, it shouldn't have been")
}

if agent.Secrets[0].Name != tt.expectedKey {
t.Errorf("expected name %s, got %s", tt.expectedKey, agent.Secrets[0].Name)
}

if agent.Secrets[0].Command != tt.expectedCommand {
t.Errorf("expected command %s, got %s", tt.expectedCommand, agent.Secrets[0].Command)
}
}
}

func TestCouldErrorAnnotations(t *testing.T) {
tests := []struct {
key string
Expand Down
2 changes: 2 additions & 0 deletions agent-inject/agent/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ type Template struct {
Contents string `json:"contents"`
LeftDelim string `json:"left_delimiter,omitempty"`
RightDelim string `json:"right_delimiter,omitempty"`
Command string `json:"command,omitempty"`
}

func (a *Agent) newTemplateConfigs() []*Template {
Expand All @@ -85,6 +86,7 @@ func (a *Agent) newTemplateConfigs() []*Template {
Destination: fmt.Sprintf("/vault/secrets/%s", secret.Name),
LeftDelim: "{{",
RightDelim: "}}",
Command: secret.Command,
}
templates = append(templates, tmpl)
}
Expand Down
5 changes: 5 additions & 0 deletions agent-inject/agent/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func TestNewConfig(t *testing.T) {
"vault.hashicorp.com/agent-inject-secret-foo": "db/creds/foo",
"vault.hashicorp.com/agent-inject-template-foo": "template foo",
"vault.hashicorp.com/agent-inject-secret-bar": "db/creds/bar",
"vault.hashicorp.com/agent-inject-command-bar": "pkill -HUP app",
}

pod := testPod(annotations)
Expand Down Expand Up @@ -102,6 +103,10 @@ func TestNewConfig(t *testing.T) {
if !strings.Contains(template.Contents, "with secret \"db/creds/bar\"") {
t.Errorf("expected template contents to contain %s, got %s", "with secret \"db/creds/bar\"", template.Contents)
}

if !strings.Contains(template.Command, "pkill -HUP app") {
t.Errorf("expected command contents to contain %s, got %s", "pkill -HUP app", template.Command)
}
} else {
t.Error("shouldn't have got here")
}
Expand Down

0 comments on commit a6e370c

Please sign in to comment.