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

Adding support for exit after auth as an annotation #729

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
8 changes: 8 additions & 0 deletions agent-inject/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ type Agent struct {
// token on shutting down.
RevokeOnShutdown bool

// ExitAfterAuth is used to control if the agent should exit after a successful auth.
ExitAfterAuth bool

// RevokeGrace controls after receiving the signal for pod
// termination that the container will attempt to revoke its own Vault token.
RevokeGrace uint64
Expand Down Expand Up @@ -445,6 +448,11 @@ func New(pod *corev1.Pod) (*Agent, error) {
return agent, err
}

agent.ExitAfterAuth, err = agent.getExitAfterAuth()
if err != nil {
return nil, err
}

agent.Containers = strings.Split(pod.Annotations[AnnotationAgentInjectContainers], ",")

agent.RevokeGrace, err = agent.revokeGrace()
Expand Down
17 changes: 17 additions & 0 deletions agent-inject/agent/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ const (
// make sure it's written to `/home/vault/.vault-token`. Only supported for sidecar containers.
AnnotationAgentRevokeOnShutdown = "vault.hashicorp.com/agent-revoke-on-shutdown"

// AnnotationAgentExitAfterAuth is the key of the annotation that configures whether the vault-agent sidecar will exit after successful authentication.
AnnotationAgentExitAfterAuth = "vault.hashicorp.com/agent-exit-after-auth"

// AnnotationAgentRevokeGrace sets the number of seconds after receiving the signal for pod
// termination that the container will attempt to revoke its own Vault token. Defaults to 5s.
AnnotationAgentRevokeGrace = "vault.hashicorp.com/agent-revoke-grace"
Expand Down Expand Up @@ -349,6 +352,7 @@ type AgentConfig struct {
VaultNamespace string
Namespace string
RevokeOnShutdown bool
ExitAfterAuth bool
UserID string
GroupID string
SameID bool
Expand Down Expand Up @@ -466,6 +470,10 @@ func Init(pod *corev1.Pod, cfg AgentConfig) error {
pod.ObjectMeta.Annotations[AnnotationAgentRevokeOnShutdown] = strconv.FormatBool(cfg.RevokeOnShutdown)
}

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

if _, ok := pod.ObjectMeta.Annotations[AnnotationAgentRevokeGrace]; !ok {
pod.ObjectMeta.Annotations[AnnotationAgentRevokeGrace] = strconv.Itoa(DefaultRevokeGrace)
}
Expand Down Expand Up @@ -745,6 +753,15 @@ func (a *Agent) revokeOnShutdown() (bool, error) {
return parseutil.ParseBool(raw)
}

func (a *Agent) getExitAfterAuth() (bool, error) {
raw, ok := a.Annotations[AnnotationAgentExitAfterAuth]
if !ok {
return false, nil
}

return parseutil.ParseBool(raw)
}

func (a *Agent) revokeGrace() (uint64, error) {
raw, ok := a.Annotations[AnnotationAgentRevokeGrace]
if !ok {
Expand Down
33 changes: 32 additions & 1 deletion agent-inject/agent/annotations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func basicAgentConfig() AgentConfig {
ResourceLimitCPU: DefaultResourceLimitCPU,
ResourceLimitMem: DefaultResourceLimitMem,
ExitOnRetryFailure: DefaultTemplateConfigExitOnRetryFailure,
ExitAfterAuth: true,
}
}

Expand Down Expand Up @@ -71,7 +72,7 @@ func TestInitCanSet(t *testing.T) {
}

if raw != tt.annotationValue {
t.Errorf("Default annotation confiured value incorrect, wanted %s, got %s", tt.annotationValue, raw)
t.Errorf("Default annotation configured value incorrect, wanted %s, got %s", tt.annotationValue, raw)
}
}
}
Expand Down Expand Up @@ -927,6 +928,18 @@ func TestCouldErrorAnnotations(t *testing.T) {
{AnnotationAgentAuthMaxBackoff, "1s", true},
{AnnotationAgentAuthMaxBackoff, "1m", true},
{AnnotationAgentAuthMaxBackoff, "x", false},

{AnnotationAgentExitAfterAuth, "true", true},
{AnnotationAgentExitAfterAuth, "false", true},
{AnnotationAgentExitAfterAuth, "TRUE", true},
{AnnotationAgentExitAfterAuth, "FALSE", true},
{AnnotationAgentExitAfterAuth, "0", true},
{AnnotationAgentExitAfterAuth, "1", true},
{AnnotationAgentExitAfterAuth, "t", true},
{AnnotationAgentExitAfterAuth, "f", true},
{AnnotationAgentExitAfterAuth, "tRuE", false},
{AnnotationAgentExitAfterAuth, "fAlSe", false},
{AnnotationAgentExitAfterAuth, "", true},
}

for i, tt := range tests {
Expand Down Expand Up @@ -1365,6 +1378,24 @@ func TestAutoAuthExitOnError(t *testing.T) {
require.Equal(t, true, agent.AutoAuthExitOnError)
}

func TestExitAfterAuth(t *testing.T) {
pod := testPod(map[string]string{
"vault.hashicorp.com/agent-exit-after-auth": "true",
})
agentConfig := basicAgentConfig()
err := Init(pod, agentConfig)
if err != nil {
t.Errorf("got error, shouldn't have: %s", err)
}

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

require.Equal(t, true, agent.ExitAfterAuth)
}

func TestDisableIdleConnections(t *testing.T) {
tests := map[string]struct {
annotations map[string]string
Expand Down
2 changes: 2 additions & 0 deletions agent-inject/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ type Handler struct {
Clientset *kubernetes.Clientset
Log hclog.Logger
RevokeOnShutdown bool
ExitAfterAuth bool
UserID string
GroupID string
SameID bool
Expand Down Expand Up @@ -229,6 +230,7 @@ func (h *Handler) Mutate(req *admissionv1.AdmissionRequest) MutateResponse {
ProxyAddress: h.ProxyAddress,
Namespace: req.Namespace,
RevokeOnShutdown: h.RevokeOnShutdown,
ExitAfterAuth: h.ExitAfterAuth,
UserID: h.UserID,
GroupID: h.GroupID,
SameID: h.SameID,
Expand Down
2 changes: 2 additions & 0 deletions subcommand/injector/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ type Command struct {
flagVaultAuthPath string // Mount path of the Vault Auth Method
flagVaultNamespace string // Vault enterprise namespace
flagRevokeOnShutdown bool // Revoke Vault Token on pod shutdown
flagExitAfterAuth bool // Exit after successful auth
flagRunAsUser string // User (uid) to run Vault agent as
flagRunAsGroup string // Group (gid) to run Vault agent as
flagRunAsSameUser bool // Run Vault agent as the User (uid) of the first application container
Expand Down Expand Up @@ -208,6 +209,7 @@ func (c *Command) Run(args []string) int {
RequireAnnotation: true,
Log: logger,
RevokeOnShutdown: c.flagRevokeOnShutdown,
ExitAfterAuth: c.flagExitAfterAuth,
UserID: c.flagRunAsUser,
GroupID: c.flagRunAsGroup,
SameID: c.flagRunAsSameUser,
Expand Down
12 changes: 12 additions & 0 deletions subcommand/injector/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ type Specification struct {
// RevokeOnShutdown is AGENT_INJECT_REVOKE_ON_SHUTDOWN environment variable.
RevokeOnShutdown string `split_words:"true"`

// ExitAfterAuth is the AGENT_INJECT_EXIT_AFTER_AUTH environment variable.
ExitAfterAuth string `split_words:"true"`

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

Expand Down Expand Up @@ -187,6 +190,8 @@ func (c *Command) init() {
c.flagSet.StringVar(&c.flagVaultNamespace, "vault-namespace", "", "Vault enterprise namespace.")
c.flagSet.BoolVar(&c.flagRevokeOnShutdown, "revoke-on-shutdown", false,
"Automatically revoke Vault Token on Pod termination.")
c.flagSet.BoolVar(&c.flagExitAfterAuth, "exit-after-auth", false,
"Exit after successful authentication to Vault.")
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),
Expand Down Expand Up @@ -352,6 +357,13 @@ func (c *Command) parseEnvs() error {
}
}

if envs.ExitAfterAuth != "" {
c.flagExitAfterAuth, err = parseutil.ParseBool(envs.ExitAfterAuth)
if err != nil {
return err
}
}

if envs.RunAsUser != "" {
c.flagRunAsUser = envs.RunAsUser
}
Expand Down
2 changes: 2 additions & 0 deletions subcommand/injector/flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ func TestCommandEnvBools(t *testing.T) {
}{
{env: "AGENT_INJECT_REVOKE_ON_SHUTDOWN", value: true, cmdPtr: &cmd.flagRevokeOnShutdown},
{env: "AGENT_INJECT_REVOKE_ON_SHUTDOWN", value: false, cmdPtr: &cmd.flagRevokeOnShutdown},
{env: "AGENT_INJECT_EXIT_AFTER_AUTH", value: true, cmdPtr: &cmd.flagExitAfterAuth},
{env: "AGENT_INJECT_EXIT_AFTER_AUTH", value: false, cmdPtr: &cmd.flagExitAfterAuth},
{env: "AGENT_INJECT_RUN_AS_SAME_USER", value: true, cmdPtr: &cmd.flagRunAsSameUser},
{env: "AGENT_INJECT_RUN_AS_SAME_USER", value: false, cmdPtr: &cmd.flagRunAsSameUser},
{env: "AGENT_INJECT_SET_SECURITY_CONTEXT", value: true, cmdPtr: &cmd.flagSetSecurityContext},
Expand Down
Loading