Skip to content

Commit

Permalink
set run-as-{user,group} globally in the injector via environment vari…
Browse files Browse the repository at this point in the history
…ables
  • Loading branch information
joemiller committed Feb 26, 2020
1 parent b611ea5 commit f30434e
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 32 deletions.
42 changes: 29 additions & 13 deletions agent-inject/agent/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,23 +146,33 @@ const (
AnnotationVaultAuthPath = "vault.hashicorp.com/auth-path"
)

type AgentConfig struct {
Image string
Address string
AuthPath string
Namespace string
RevokeOnShutdown bool
UserID string
GroupID string
}

// Init configures the expected annotations required to create a new instance
// of Agent. This should be run before running new to ensure all annotations are
// present.
func Init(pod *corev1.Pod, image, address, authPath, namespace string, revokeOnShutdown bool) error {
func Init(pod *corev1.Pod, cfg AgentConfig) error {
if pod == nil {
return errors.New("pod is empty")
}

if address == "" {
if cfg.Address == "" {
return errors.New("address for Vault required")
}

if authPath == "" {
if cfg.AuthPath == "" {
return errors.New("Vault Auth Path required")
}

if namespace == "" {
if cfg.Namespace == "" {
return errors.New("kubernetes namespace required")
}

Expand All @@ -171,22 +181,22 @@ func Init(pod *corev1.Pod, image, address, authPath, namespace string, revokeOnS
}

if _, ok := pod.ObjectMeta.Annotations[AnnotationVaultService]; !ok {
pod.ObjectMeta.Annotations[AnnotationVaultService] = address
pod.ObjectMeta.Annotations[AnnotationVaultService] = cfg.Address
}

if _, ok := pod.ObjectMeta.Annotations[AnnotationVaultAuthPath]; !ok {
pod.ObjectMeta.Annotations[AnnotationVaultAuthPath] = authPath
pod.ObjectMeta.Annotations[AnnotationVaultAuthPath] = cfg.AuthPath
}

if _, ok := pod.ObjectMeta.Annotations[AnnotationAgentImage]; !ok {
if image == "" {
image = DefaultVaultImage
if cfg.Image == "" {
cfg.Image = DefaultVaultImage
}
pod.ObjectMeta.Annotations[AnnotationAgentImage] = image
pod.ObjectMeta.Annotations[AnnotationAgentImage] = cfg.Image
}

if _, ok := pod.ObjectMeta.Annotations[AnnotationAgentRequestNamespace]; !ok {
pod.ObjectMeta.Annotations[AnnotationAgentRequestNamespace] = namespace
pod.ObjectMeta.Annotations[AnnotationAgentRequestNamespace] = cfg.Namespace
}

if _, ok := pod.ObjectMeta.Annotations[AnnotationAgentLimitsCPU]; !ok {
Expand All @@ -206,7 +216,7 @@ func Init(pod *corev1.Pod, image, address, authPath, namespace string, revokeOnS
}

if _, ok := pod.ObjectMeta.Annotations[AnnotationAgentRevokeOnShutdown]; !ok {
pod.ObjectMeta.Annotations[AnnotationAgentRevokeOnShutdown] = strconv.FormatBool(revokeOnShutdown)
pod.ObjectMeta.Annotations[AnnotationAgentRevokeOnShutdown] = strconv.FormatBool(cfg.RevokeOnShutdown)
}

if _, ok := pod.ObjectMeta.Annotations[AnnotationAgentRevokeGrace]; !ok {
Expand All @@ -218,11 +228,17 @@ func Init(pod *corev1.Pod, image, address, authPath, namespace string, revokeOnS
}

if _, ok := pod.ObjectMeta.Annotations[AnnotationAgentRunAsUser]; !ok {
pod.ObjectMeta.Annotations[AnnotationAgentRunAsUser] = strconv.Itoa(DefaultAgentRunAsUser)
if cfg.UserID == "" {
cfg.UserID = strconv.Itoa(DefaultAgentRunAsUser)
}
pod.ObjectMeta.Annotations[AnnotationAgentRunAsUser] = cfg.UserID
}

if _, ok := pod.ObjectMeta.Annotations[AnnotationAgentRunAsGroup]; !ok {
pod.ObjectMeta.Annotations[AnnotationAgentRunAsGroup] = strconv.Itoa(DefaultAgentRunAsGroup)
if cfg.GroupID == "" {
cfg.GroupID = strconv.Itoa(DefaultAgentRunAsGroup)
}
pod.ObjectMeta.Annotations[AnnotationAgentRunAsGroup] = cfg.GroupID
}

return nil
Expand Down
30 changes: 17 additions & 13 deletions agent-inject/agent/annotations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func TestInitCanSet(t *testing.T) {
annotations := make(map[string]string)
pod := testPod(annotations)

err := Init(pod, "foobar-image", "http://foobar:8200", "test", "test", true)
err := Init(pod, AgentConfig{"foobar-image", "http://foobar:8200", "test", "test", true, "1000", "100"})
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
}
Expand Down Expand Up @@ -47,7 +47,7 @@ func TestInitDefaults(t *testing.T) {
annotations := make(map[string]string)
pod := testPod(annotations)

err := Init(pod, "", "http://foobar:8200", "test", "test", true)
err := Init(pod, AgentConfig{"", "http://foobar:8200", "test", "test", true, "", ""})
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
}
Expand All @@ -69,7 +69,6 @@ func TestInitDefaults(t *testing.T) {

if raw != tt.annotationValue {
t.Errorf("Default annotation value incorrect, wanted %s, got %s", tt.annotationValue, raw)

}
}
}
Expand All @@ -78,7 +77,7 @@ func TestInitError(t *testing.T) {
annotations := make(map[string]string)
pod := testPod(annotations)

err := Init(pod, "image", "", "authPath", "namespace", true)
err := Init(pod, AgentConfig{"image", "", "authPath", "namespace", true, "1000", "100"})
if err == nil {
t.Error("expected error no address, got none")
}
Expand All @@ -88,7 +87,7 @@ func TestInitError(t *testing.T) {
t.Errorf("expected '%s' error, got %s", errMsg, err)
}

err = Init(pod, "image", "address", "", "namespace", true)
err = Init(pod, AgentConfig{"image", "address", "", "namespace", true, "1000", "100"})
if err == nil {
t.Error("expected error no authPath, got none")
}
Expand All @@ -98,7 +97,7 @@ func TestInitError(t *testing.T) {
t.Errorf("expected '%s' error, got %s", errMsg, err)
}

err = Init(pod, "image", "address", "authPath", "", true)
err = Init(pod, AgentConfig{"image", "address", "authPath", "", true, "1000", "100"})
if err == nil {
t.Error("expected error for no namespace, got none")
}
Expand Down Expand Up @@ -131,7 +130,7 @@ func TestSecretAnnotations(t *testing.T) {
pod := testPod(annotation)
var patches []*jsonpatch.JsonPatchOperation

err := Init(pod, "", "http://foobar:8200", "test", "test")
err := Init(pod, AgentConfig{"", "http://foobar:8200", "test", "test", true, "1000", "100"})
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
}
Expand Down Expand Up @@ -209,7 +208,7 @@ func TestSecretTemplateAnnotations(t *testing.T) {
pod := testPod(tt.annotations)
var patches []*jsonpatch.JsonPatchOperation

err := Init(pod, "", "http://foobar:8200", "test", "test")
err := Init(pod, AgentConfig{"", "http://foobar:8200", "test", "test", true, "1000", "100"})
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
}
Expand Down Expand Up @@ -264,7 +263,7 @@ func TestTemplateShortcuts(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
pod := testPod(tt.annotations)
err := Init(pod, "", "http://foobar:8200", "test", "test")
err := Init(pod, AgentConfig{"", "http://foobar:8200", "test", "test", true, "1000", "100"})
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
}
Expand Down Expand Up @@ -320,7 +319,7 @@ func TestSecretCommandAnnotations(t *testing.T) {

for _, tt := range tests {
pod := testPod(tt.annotations)
err := Init(pod, "", "http://foobar:8200", "test", "test")
err := Init(pod, AgentConfig{"", "http://foobar:8200", "test", "test", true, "1000", "100"})
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
}
Expand Down Expand Up @@ -431,7 +430,7 @@ func TestCouldErrorAnnotations(t *testing.T) {
pod := testPod(annotations)
var patches []*jsonpatch.JsonPatchOperation

err := Init(pod, "", "http://foobar:8200", "test", "test")
err := Init(pod, AgentConfig{"", "http://foobar:8200", "test", "test", true, "1000", "100"})
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
}
Expand All @@ -448,9 +447,9 @@ func TestCouldErrorAnnotations(t *testing.T) {
func TestInitEmptyPod(t *testing.T) {
var pod *corev1.Pod

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

Expand All @@ -473,6 +472,11 @@ func TestVaultNamespaceAnnotation(t *testing.T) {
pod := testPod(annotation)
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, shouldn't have: %s", err)
}

agent, err := New(pod, patches)
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
Expand Down
8 changes: 4 additions & 4 deletions agent-inject/agent/container_sidecar_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func TestContainerSidecar(t *testing.T) {
pod := testPod(annotations)
var patches []*jsonpatch.JsonPatchOperation

err := Init(pod, "foobar-image", "http://foobar:1234", "test", "test", false)
err := Init(pod, AgentConfig{"foobar-image", "http://foobar:1234", "test", "test", false, "1000", "100"})
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
}
Expand Down Expand Up @@ -111,7 +111,7 @@ func TestContainerSidecarRevokeHook(t *testing.T) {
pod := testPod(annotations)
var patches []*jsonpatch.JsonPatchOperation

err := Init(pod, "foobar-image", "http://foobar:1234", "test", "test", tt.revokeFlag)
err := Init(pod, AgentConfig{"foobar-image", "http://foobar:1234", "test", "test", tt.revokeFlag, "1000", "100"})
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
}
Expand Down Expand Up @@ -159,7 +159,7 @@ func TestContainerSidecarConfigMap(t *testing.T) {
pod := testPod(annotations)
var patches []*jsonpatch.JsonPatchOperation

err := Init(pod, "foobar-image", "http://foobar:1234", "test", "test", true)
err := Init(pod, AgentConfig{"foobar-image", "http://foobar:1234", "test", "test", true, "1000", "100"})
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
}
Expand Down Expand Up @@ -518,7 +518,7 @@ func TestContainerSidecarSecurityContext(t *testing.T) {
pod := testPod(annotations)
var patches []*jsonpatch.JsonPatchOperation

err := Init(pod, "foobar-image", "http://foobar:1234", "test", "test")
err := Init(pod, AgentConfig{"foobar-image", "http://foobar:1234", "test", "test", true, "1000", "100"})
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
}
Expand Down
13 changes: 12 additions & 1 deletion agent-inject/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ type Handler struct {
Clientset *kubernetes.Clientset
Log hclog.Logger
RevokeOnShutdown bool
UserID string
GroupID string
}

// Handle is the http.HandlerFunc implementation that actually handles the
Expand Down Expand Up @@ -136,7 +138,16 @@ func (h *Handler) Mutate(req *v1beta1.AdmissionRequest) *v1beta1.AdmissionRespon

h.Log.Debug("setting default annotations..")
var patches []*jsonpatch.JsonPatchOperation
err = agent.Init(&pod, h.ImageVault, h.VaultAddress, h.VaultAuthPath, req.Namespace, h.RevokeOnShutdown)
cfg := agent.AgentConfig{
Image: h.ImageVault,
Address: h.VaultAddress,
AuthPath: h.VaultAuthPath,
Namespace: req.Namespace,
RevokeOnShutdown: h.RevokeOnShutdown,
UserID: h.UserID,
GroupID: h.GroupID,
}
err = agent.Init(&pod, cfg)
if err != nil {
err := fmt.Errorf("error adding default annotations: %s", err)
return admissionError(err)
Expand Down
4 changes: 4 additions & 0 deletions subcommand/injector/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ type Command struct {
flagVaultImage string // Name of the Vault Image to use
flagVaultAuthPath string // Mount Path of the Vault Kubernetes Auth Method
flagRevokeOnShutdown bool // Revoke Vault Token on pod shutdown
flagRunAsUser string // User (uid) to run Vault agent as
flagRunAsGroup string // Group (gid) to run Vault agent as

flagSet *flag.FlagSet

Expand Down Expand Up @@ -118,6 +120,8 @@ func (c *Command) Run(args []string) int {
RequireAnnotation: true,
Log: logger,
RevokeOnShutdown: c.flagRevokeOnShutdown,
UserID: c.flagRunAsUser,
GroupID: c.flagRunAsGroup,
}

mux := http.NewServeMux()
Expand Down
20 changes: 19 additions & 1 deletion subcommand/injector/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,13 @@ type Specification struct {
VaultAuthPath string `split_words:"true"`

// RevokeOnShutdown is AGENT_INJECT_REVOKE_ON_SHUTDOWN environment variable.
RevokeOnShutdown string `split_words:"true" `
RevokeOnShutdown string `split_words:"true"`

// RunAsUser is the AGENT_INJECT_RUN_AS_USER environment variable. (uid)
RunAsUser string `envconfig:"AGENT_INJECT_RUN_AS_USER"`

// RunAsGroup is the AGENT_INJECT_RUN_AS_GROUP environment variable. (gid)
RunAsGroup string `envconfig:"AGENT_INJECT_RUN_AS_GROUP"`
}

func (c *Command) init() {
Expand All @@ -78,6 +84,10 @@ func (c *Command) init() {
fmt.Sprintf("Mount Path of the Vault Kubernetes Auth Method. Defaults to %q.", agent.DefaultVaultAuthPath))
c.flagSet.BoolVar(&c.flagRevokeOnShutdown, "revoke-on-shutdown", false,
"Automatically revoke Vault Token on Pod termination.")
c.flagSet.StringVar(&c.flagRunAsUser, "run-as-user", strconv.Itoa(agent.DefaultAgentRunAsUser),
fmt.Sprintf("User (uid) to run Vault agent as. Defaults to %d.", agent.DefaultAgentRunAsUser))
c.flagSet.StringVar(&c.flagRunAsGroup, "run-as-group", strconv.Itoa(agent.DefaultAgentRunAsGroup),
fmt.Sprintf("Group (gid) to run Vault agent as. Defaults to %d.", agent.DefaultAgentRunAsGroup))

c.help = flags.Usage(help, c.flagSet)
}
Expand Down Expand Up @@ -158,5 +168,13 @@ func (c *Command) parseEnvs() error {
}
}

if envs.RunAsUser != "" {
c.flagRunAsUser = envs.RunAsUser
}

if envs.RunAsGroup != "" {
c.flagRunAsGroup = envs.RunAsGroup
}

return nil
}
2 changes: 2 additions & 0 deletions subcommand/injector/flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ func TestCommandEnvs(t *testing.T) {
{env: "AGENT_INJECT_TLS_AUTO", value: "mutationWebhook", cmdPtr: &cmd.flagAutoName},
{env: "AGENT_INJECT_LOG_LEVEL", value: "info", cmdPtr: &cmd.flagLogLevel},
{env: "AGENT_INJECT_LOG_FORMAT", value: "standard", cmdPtr: &cmd.flagLogFormat},
{env: "AGENT_INJECT_RUN_AS_USER", value: "1000", cmdPtr: &cmd.flagRunAsUser},
{env: "AGENT_INJECT_RUN_AS_GROUP", value: "1001", cmdPtr: &cmd.flagRunAsGroup},
}

for _, tt := range tests {
Expand Down

0 comments on commit f30434e

Please sign in to comment.