Skip to content

Commit

Permalink
Fix use env vars when exec
Browse files Browse the repository at this point in the history
  • Loading branch information
dispensable committed Apr 22, 2023
1 parent 797999c commit c5e6b86
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 2 deletions.
77 changes: 77 additions & 0 deletions env.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package main

import (
"fmt"
"strings"
)

var (
preloadEnvVars map[string]struct{} = map[string]struct{}{
"SHELL": struct{}{},
"PWD": struct{}{},
"LOGNAME": struct{}{},
"HOME": struct{}{},
"LANG": struct{}{},
"USER": struct{}{},
"SHLVL": struct{}{},
"MAILTO": struct{}{},
"LC_ALL": struct{}{},
"PATH": struct{}{},
"_": struct{}{},
}
reservedEnvVars []string = []string{"LOGNAME", "USER"}
)

type CronEnvs struct {
envMap map[string]string
}

func NewCronEnvs(parentEnvs []string) *CronEnvs {
pEnvs := make(map[string]string)
for _, e := range parentEnvs {
splitAt := strings.Index(e, "=")
key := e[:splitAt]
if _, ok := preloadEnvVars[key]; ok {
pEnvs[key] = e[splitAt+1:]
}
}

return &CronEnvs{
envMap: pEnvs,
}
}

func (e *CronEnvs) SetEnv(key, value string) {
e.envMap[key] = value
}

func (e *CronEnvs) GetEnv(key string) string {
if value, ok := e.envMap[key]; ok {
return value
} else {
return ""
}
}

func (e *CronEnvs) UpdateEnvForJob(c *CrontabEntry) error {
for _, envStr := range c.Env {
splitAt := strings.Index(envStr, "=")
key := envStr[:splitAt]
for _, env := range reservedEnvVars {
if env == key {
return fmt.Errorf("User can't set env %s", key)
}
}
e.envMap[key] = envStr[splitAt+1:]
}
return nil
}

func (e *CronEnvs) GetEnvList() []string {
result := []string{}
for k, v := range e.envMap {
result = append(result, fmt.Sprintf("%s=%s", k, v))
}
return result
}

20 changes: 18 additions & 2 deletions runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func (r *Runner) Add(cronjob CrontabEntry) error {
cronjob.SetEntryId(eid)
r.cronjobs[eid] = &cronjob
prometheusMetricTask.With(r.cronjobToPrometheusLabels(cronjob)).Set(1)
log.WithFields(LogCronjobToFields(cronjob)).Infof("cronjob added")
log.WithFields(LogCronjobToFields(cronjob)).Infof("cronjob added without user switch")
}

return err
Expand Down Expand Up @@ -80,6 +80,22 @@ func (r *Runner) AddWithUser(cronjob CrontabEntry) error {
return false
}

// update user env
envs := NewCronEnvs(execCmd.Env)
envs.SetEnv("LOGNAME", cronjob.User)
envs.SetEnv("USER", cronjob.User)
if u.HomeDir != "" {
envs.SetEnv("HOME", u.HomeDir)
envs.SetEnv("PWD", u.HomeDir)
execCmd.Dir = u.HomeDir
}
err = envs.UpdateEnvForJob(&cronjob)
if err != nil {
log.WithFields(LogCronjobToFields(cronjob)).Errorf("Cannot override env vars: %v", err)
return false
}
execCmd.Env = envs.GetEnvList()

// add process credentials
execCmd.SysProcAttr = &syscall.SysProcAttr{}
execCmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(userId), Gid: uint32(groupId)}
Expand All @@ -93,7 +109,7 @@ func (r *Runner) AddWithUser(cronjob CrontabEntry) error {
cronjob.SetEntryId(eid)
r.cronjobs[eid] = &cronjob
prometheusMetricTask.With(r.cronjobToPrometheusLabels(cronjob)).Set(1)
log.WithFields(LogCronjobToFields(cronjob)).Infof("cronjob added")
log.WithFields(LogCronjobToFields(cronjob)).Infof("cronjob added with user")
}

return err
Expand Down

1 comment on commit c5e6b86

@dispensable
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

related: webdevops#39

Please sign in to comment.