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

New securityContext options and annotations #131

Merged
merged 10 commits into from
May 21, 2020
28 changes: 24 additions & 4 deletions agent-inject/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ import (
// TODO swap out 'github.com/mattbaird/jsonpatch' for 'github.com/evanphx/json-patch'

const (
DefaultVaultImage = "vault:1.3.2"
DefaultVaultAuthPath = "auth/kubernetes"
DefaultAgentRunAsUser = 100
DefaultAgentRunAsGroup = 1000
DefaultVaultImage = "vault:1.3.2"
DefaultVaultAuthPath = "auth/kubernetes"
DefaultAgentRunAsUser = 100
DefaultAgentRunAsGroup = 1000
DefaultAgentRunAsSameUser = false
DefaultAgentSetSecurityContext = true
)

// Agent is the top level structure holding all the
Expand Down Expand Up @@ -104,6 +106,14 @@ type Agent struct {

// RunAsGroup is the group ID to run the Vault agent container(s) as.
RunAsGroup int64

// RunAsSameID sets the user ID of the Vault agent container(s) to be the
// same as the first application container
RunAsSameID bool

// SetSecurityContext controls whether the injected containers have a
// SecurityContext set.
SetSecurityContext bool
}

type Secret struct {
Expand Down Expand Up @@ -257,6 +267,16 @@ func New(pod *corev1.Pod, patches []*jsonpatch.JsonPatchOperation) (*Agent, erro
return agent, err
}

agent.RunAsSameID, err = agent.runAsSameID(pod)
if err != nil {
return agent, err
}

agent.SetSecurityContext, err = agent.setSecurityContext()
if err != nil {
return agent, err
}

return agent, nil
}

Expand Down
85 changes: 76 additions & 9 deletions agent-inject/agent/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,16 @@ const (
// AnnotationAgentRunAsGroup sets the Group ID to run the Vault Agent containers as.
AnnotationAgentRunAsGroup = "vault.hashicorp.com/agent-run-as-group"

// AnnotationAgentRunAsSameUser sets the User ID of the injected Vault Agent
// containers to the User ID of the first application container in the Pod.
// Requires Spec.Containers[0].SecurityContext.RunAsUser to be set in the
// Pod Spec.
AnnotationAgentRunAsSameUser = "vault.hashicorp.com/agent-run-as-same-user"

// AnnotationAgentSetSecurityContext controls whether a SecurityContext (uid
// and gid) is set on the injected Vault Agent containers
AnnotationAgentSetSecurityContext = "vault.hashicorp.com/agent-set-security-context"

// AnnotationVaultService is the name of the Vault server. This can be overridden by the
// user but will be set by a flag on the deployment.
AnnotationVaultService = "vault.hashicorp.com/service"
Expand Down Expand Up @@ -159,19 +169,26 @@ const (
)

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

// 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, cfg AgentConfig) error {
var securityContextIsSet bool
var runAsUserIsSet bool
var runAsSameUserIsSet bool
var runAsGroupIsSet bool

if pod == nil {
return errors.New("pod is empty")
}
Expand Down Expand Up @@ -243,20 +260,37 @@ func Init(pod *corev1.Pod, cfg AgentConfig) error {
pod.ObjectMeta.Annotations[AnnotationVaultLogLevel] = DefaultAgentLogLevel
}

if _, ok := pod.ObjectMeta.Annotations[AnnotationAgentRunAsUser]; !ok {
if _, securityContextIsSet = pod.ObjectMeta.Annotations[AnnotationAgentSetSecurityContext]; !securityContextIsSet {
pod.ObjectMeta.Annotations[AnnotationAgentSetSecurityContext] = strconv.FormatBool(cfg.SetSecurityContext)
}

if _, runAsUserIsSet = pod.ObjectMeta.Annotations[AnnotationAgentRunAsUser]; !runAsUserIsSet {

if cfg.UserID == "" {
cfg.UserID = strconv.Itoa(DefaultAgentRunAsUser)
}
pod.ObjectMeta.Annotations[AnnotationAgentRunAsUser] = cfg.UserID
}

if _, ok := pod.ObjectMeta.Annotations[AnnotationAgentRunAsGroup]; !ok {
if _, runAsSameUserIsSet = pod.ObjectMeta.Annotations[AnnotationAgentRunAsSameUser]; !runAsSameUserIsSet {
pod.ObjectMeta.Annotations[AnnotationAgentRunAsSameUser] = strconv.FormatBool(cfg.SameID)
}

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

// If the SetSecurityContext startup option is false, and the analogous
// annotation isn't set, but one of the user or group annotations is set,
// flip SetSecurityContext to true so that the user and group options are
// set in the containers.
if !cfg.SetSecurityContext && !securityContextIsSet && (runAsUserIsSet || runAsSameUserIsSet || runAsGroupIsSet) {
pod.ObjectMeta.Annotations[AnnotationAgentSetSecurityContext] = strconv.FormatBool(true)
}

return nil
}

Expand Down Expand Up @@ -394,3 +428,36 @@ func (a *Agent) preserveSecretCase(secretName string) (bool, error) {
}
return strconv.ParseBool(raw)
}

func (a *Agent) runAsSameID(pod *corev1.Pod) (bool, error) {
raw, ok := a.Annotations[AnnotationAgentRunAsSameUser]
if !ok {
return DefaultAgentRunAsSameUser, nil
}
runAsSameID, err := strconv.ParseBool(raw)
if err != nil {
return DefaultAgentRunAsSameUser, err
}
if runAsSameID {
if len(pod.Spec.Containers) == 0 {
return DefaultAgentRunAsSameUser, errors.New("No containers found in Pod Spec")
}
if pod.Spec.Containers[0].SecurityContext == nil {
return DefaultAgentRunAsSameUser, errors.New("No SecurityContext found for Container 0")
}
if pod.Spec.Containers[0].SecurityContext.RunAsUser == nil {
return DefaultAgentRunAsSameUser, errors.New("RunAsUser is nil for Container 0's SecurityContext")
}
a.RunAsUser = *pod.Spec.Containers[0].SecurityContext.RunAsUser
}
return runAsSameID, nil
}

func (a *Agent) setSecurityContext() (bool, error) {
raw, ok := a.Annotations[AnnotationAgentSetSecurityContext]
if !ok {
return DefaultAgentSetSecurityContext, nil
}

return strconv.ParseBool(raw)
}
Loading