Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
27 changes: 15 additions & 12 deletions runner/internal/executor/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,16 +133,17 @@ func (ex *RunExecutor) Run(ctx context.Context) (err error) {
ctx = log.WithLogger(ctx, log.NewEntry(logger, int(log.DefaultEntry.Logger.Level))) // todo loglevel
log.Info(ctx, "Run job", "log_level", log.GetLogger(ctx).Logger.Level.String())

if ex.jobSpec.User != nil {
if err := fillUser(ex.jobSpec.User); err != nil {
ex.SetJobStateWithTerminationReason(
ctx,
types.JobStateFailed,
types.TerminationReasonExecutorError,
fmt.Sprintf("Failed to fill in the job user fields (%s)", err),
)
return gerrors.Wrap(err)
}
if ex.jobSpec.User == nil {
ex.jobSpec.User = &schemas.User{Uid: &ex.currentUid}
}
if err := fillUser(ex.jobSpec.User); err != nil {
ex.SetJobStateWithTerminationReason(
ctx,
types.JobStateFailed,
types.TerminationReasonExecutorError,
fmt.Sprintf("Failed to fill in the job user fields (%s)", err),
)
return gerrors.Wrap(err)
}

if err := ex.setupFiles(ctx); err != nil {
Expand Down Expand Up @@ -331,15 +332,15 @@ func (ex *RunExecutor) execJob(ctx context.Context, jobLogFile io.Writer) error
cmd.Dir = workingDir
}

// User must be already set
user := ex.jobSpec.User
if user != nil {
if ex.currentUid == 0 {
Comment thread
un-def marked this conversation as resolved.
log.Trace(
ctx, "Using credentials",
"uid", *user.Uid, "gid", *user.Gid, "groups", user.GroupIds,
"username", user.GetUsername(), "groupname", user.GetGroupname(),
"home", user.HomeDir,
)
log.Trace(ctx, "Current user", "uid", ex.currentUid)

// 1. Ideally, We should check uid, gid, and supplementary groups mismatches,
// but, for the sake of simplicity, we only check uid. Unprivileged runner
Expand All @@ -362,6 +363,8 @@ func (ex *RunExecutor) execJob(ctx context.Context, jobLogFile io.Writer) error
Gid: *user.Gid,
Groups: user.GroupIds,
}
} else {
log.Info(ctx, "Current user is not root, cannot set process credentials", "uid", ex.currentUid)
}

envMap := NewEnvMap(ParseEnvList(os.Environ()), jobEnvs, ex.secrets)
Expand Down
106 changes: 54 additions & 52 deletions runner/internal/executor/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,67 +39,69 @@ func (ex *RunExecutor) setupFiles(ctx context.Context) error {
homeDir := ex.workingDir
uid := -1
gid := -1
if ex.jobSpec.User != nil {
if ex.jobSpec.User.HomeDir != "" {
homeDir = ex.jobSpec.User.HomeDir
}
if ex.jobSpec.User.Uid != nil {
uid = int(*ex.jobSpec.User.Uid)
}
if ex.jobSpec.User.Gid != nil {
gid = int(*ex.jobSpec.User.Gid)
}
// User must be already set
if ex.jobSpec.User.HomeDir != "" {
homeDir = ex.jobSpec.User.HomeDir
}
if ex.jobSpec.User.Uid != nil {
uid = int(*ex.jobSpec.User.Uid)
}
if ex.jobSpec.User.Gid != nil {
gid = int(*ex.jobSpec.User.Gid)
}

for _, fa := range ex.run.RunSpec.FileArchives {
log.Trace(ctx, "Extracting file archive", "id", fa.Id, "path", fa.Path)

p := path.Clean(fa.Path)
// `~username[/path/to]` is not supported
if p == "~" {
p = homeDir
} else if rest, found := strings.CutPrefix(p, "~/"); found {
p = path.Join(homeDir, rest)
} else if !path.IsAbs(p) {
p = path.Join(ex.workingDir, p)
}
dir, root := path.Split(p)
if err := mkdirAll(ctx, dir, uid, gid); err != nil {
archivePath := path.Join(ex.archiveDir, fa.Id)
if err := extractFileArchive(ctx, archivePath, fa.Path, ex.workingDir, uid, gid, homeDir); err != nil {
return gerrors.Wrap(err)
}
}

if err := os.RemoveAll(p); err != nil {
log.Warning(ctx, "Failed to remove", "path", p, "err", err)
}
Comment thread
un-def marked this conversation as resolved.
if err := os.RemoveAll(ex.archiveDir); err != nil {
log.Warning(ctx, "Failed to remove file archives dir", "path", ex.archiveDir, "err", err)
}

archivePath := path.Join(ex.archiveDir, fa.Id)
archive, err := os.Open(archivePath)
if err != nil {
return gerrors.Wrap(err)
}
defer func() {
_ = archive.Close()
if err := os.Remove(archivePath); err != nil {
log.Warning(ctx, "Failed to remove archive", "path", archivePath, "err", err)
}
}()
return nil
}

var paths []string
repl := fmt.Sprintf("%s$2", root)
renameAndRemember := func(s string) string {
s = renameRegex.ReplaceAllString(s, repl)
paths = append(paths, s)
return s
}
if err := extract.Tar(ctx, archive, dir, renameAndRemember); err != nil {
return gerrors.Wrap(err)
}
func extractFileArchive(ctx context.Context, archivePath string, targetPath string, targetRoot string, uid int, gid int, homeDir string) error {
log.Trace(ctx, "Extracting file archive", "archive", archivePath, "target", targetPath)

if uid != -1 || gid != -1 {
for _, p := range paths {
if err := os.Chown(path.Join(dir, p), uid, gid); err != nil {
log.Warning(ctx, "Failed to chown", "path", p, "err", err)
}
targetPath = path.Clean(targetPath)
// `~username[/path/to]` is not supported
if targetPath == "~" {
targetPath = homeDir
} else if rest, found := strings.CutPrefix(targetPath, "~/"); found {
targetPath = path.Join(homeDir, rest)
} else if !path.IsAbs(targetPath) {
targetPath = path.Join(targetRoot, targetPath)
}
dir, root := path.Split(targetPath)
if err := mkdirAll(ctx, dir, uid, gid); err != nil {
return gerrors.Wrap(err)
}

archive, err := os.Open(archivePath)
if err != nil {
return gerrors.Wrap(err)
}
defer archive.Close()

var paths []string
repl := fmt.Sprintf("%s$2", root)
renameAndRemember := func(s string) string {
s = renameRegex.ReplaceAllString(s, repl)
paths = append(paths, s)
return s
}
if err := extract.Tar(ctx, archive, dir, renameAndRemember); err != nil {
return gerrors.Wrap(err)
}

if uid != -1 || gid != -1 {
for _, p := range paths {
if err := os.Chown(path.Join(dir, p), uid, gid); err != nil {
log.Warning(ctx, "Failed to chown", "path", p, "err", err)
}
}
}
Expand Down
Loading