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 annotation for rendered file permission #277

Merged
merged 4 commits into from
Aug 13, 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
3 changes: 3 additions & 0 deletions agent-inject/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ type Secret struct {

// FilePathAndName is the optional file path and name for the rendered secret file.
FilePathAndName string

// FilePermission is the optional file permission for the rendered secret file
FilePermission string
}

type Vault struct {
Expand Down
13 changes: 13 additions & 0 deletions agent-inject/agent/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ const (
// secret-volume-path annotation.
AnnotationAgentInjectFile = "vault.hashicorp.com/agent-inject-file"

// AnnotationAgentInjectFilePermission is the key of the annotation that contains the
// permission of the file to create on disk. The name of the
// secret is the string after "vault.hashicorp.com/agent-inject-perms-", and
// should map to the same unique value provided in
// "vault.hashicorp.com/agent-inject-secret-". The value is the value of the permission, for
// example "0644"
AnnotationAgentInjectFilePermission = "vault.hashicorp.com/agent-inject-perms"

// AnnotationAgentInjectTemplate is the key annotation that configures Vault
// Agent what template to use for rendering the secrets. The name
// of the template is any unique string after "vault.hashicorp.com/agent-inject-template-",
Expand Down Expand Up @@ -460,6 +468,11 @@ func (a *Agent) secrets() []*Secret {
s.FilePathAndName = val
}

filePerm := fmt.Sprintf("%s-%s", AnnotationAgentInjectFilePermission, raw)
if val, ok := a.Annotations[filePerm]; ok {
s.FilePermission = val
}

secrets = append(secrets, s)
}
}
Expand Down
49 changes: 49 additions & 0 deletions agent-inject/agent/annotations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,55 @@ func TestSecretTemplateFileAnnotations(t *testing.T) {
}
}

func TestSecretPermissionAnnotations(t *testing.T) {
tests := []struct {
annotations map[string]string
expectedKey string
expectedPermission string
}{
{
map[string]string{
"vault.hashicorp.com/agent-inject-secret-foobar": "test1",
"vault.hashicorp.com/agent-inject-perms-foobar": "0600",
}, "foobar", "0600",
},
{
map[string]string{
"vault.hashicorp.com/agent-inject-secret-foobar": "test2",
"vault.hashicorp.com/agent-inject-perms-foobar2": "0600",
}, "foobar", "",
},
}

for _, tt := range tests {
pod := testPod(tt.annotations)
agentConfig := basicAgentConfig()
err := Init(pod, agentConfig)
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
}

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].FilePermission != tt.expectedPermission {
t.Errorf("expected permission %s, got %s", tt.expectedPermission, agent.Secrets[0].Command)
}
}
}

func TestSecretCommandAnnotations(t *testing.T) {
tests := []struct {
annotations map[string]string
Expand Down
4 changes: 4 additions & 0 deletions agent-inject/agent/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ type Template struct {
RightDelim string `json:"right_delimiter,omitempty"`
Command string `json:"command,omitempty"`
Source string `json:"source,omitempty"`
Perms string `json:"perms,omitempty"`
}

// Listener defines the configuration for Vault Agent Cache Listener
Expand Down Expand Up @@ -136,6 +137,9 @@ func (a *Agent) newTemplateConfigs() []*Template {
RightDelim: "}}",
Command: secret.Command,
}
if secret.FilePermission != "" {
tmpl.Perms = secret.FilePermission
}
templates = append(templates, tmpl)
}
return templates
Expand Down
92 changes: 92 additions & 0 deletions agent-inject/agent/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,9 @@ func TestFilePathAndName(t *testing.T) {
}

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 All @@ -240,6 +243,95 @@ func TestFilePathAndName(t *testing.T) {
}
}

func TestFilePermission(t *testing.T) {

tests := []struct {
name string
annotations map[string]string
permission string
}{
{
"just secret",
map[string]string{
"vault.hashicorp.com/agent-inject-secret-foo": "db/creds/foo",
"vault.hashicorp.com/agent-inject-perms-foo": "0600",
},
"0600",
},
{
"just secret without permission",
map[string]string{
"vault.hashicorp.com/agent-inject-secret-foo": "db/creds/foo",
},
"",
},
{
"with relative file path",
map[string]string{
"vault.hashicorp.com/agent-inject-secret-foo": "db/creds/foo",
"vault.hashicorp.com/agent-inject-file-foo": "nested/foofile",
"vault.hashicorp.com/agent-inject-perms-foo": "0600",
},
"0600",
},
{
"with relative file path without permission",
map[string]string{
"vault.hashicorp.com/agent-inject-secret-foo": "db/creds/foo",
"vault.hashicorp.com/agent-inject-file-foo": "nested/foofile",
},
"",
},
{
"with absolute file path",
map[string]string{
"vault.hashicorp.com/agent-inject-secret-foo": "db/creds/foo",
"vault.hashicorp.com/agent-inject-file-foo": "/special/volume/foofile",
"vault.hashicorp.com/agent-inject-perms-foo": "0600",
},
"0600",
},
{
"with absolute file path without permission",
map[string]string{
"vault.hashicorp.com/agent-inject-secret-foo": "db/creds/foo",
"vault.hashicorp.com/agent-inject-file-foo": "/special/volume/foofile",
},
"",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
pod := testPod(tt.annotations)
var patches []*jsonpatch.JsonPatchOperation

agentConfig := basicAgentConfig()
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)
}

config := &Config{}
if err := json.Unmarshal(cfg, config); err != nil {
t.Errorf("got error unmarshalling Vault config, shouldn't have: %s", err)
}
if config.Templates[0].Perms != tt.permission {
t.Errorf("wrong permission: %s != %s", config.Templates[0].Perms, tt.permission)
}
})
}
}

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

Expand Down