Error: container has runAsNonRoot and image has non-numeric user (tokei), cannot verify user is non-root (pod: "tokei-pie-6c6fd5cb84-s4bz7_tokei-pie(239057ea-fe47-40a9-8041-966c65344a44)", container: tokei-pie)
funcverifyRunAsNonRoot(pod *v1.Pod, container *v1.Container, uid *int64, username string)error { effectiveSc := securitycontext.DetermineEffectiveSecurityContext(pod, container) // If the option is not set, or if running as root is allowed, return nil. if effectiveSc == nil || effectiveSc.RunAsNonRoot == nil || !*effectiveSc.RunAsNonRoot { returnnil }
switch { case uid != nil && *uid == 0: return fmt.Errorf("container has runAsNonRoot and image will run as root (pod: %q, container: %s)", format.Pod(pod), container.Name) case uid == nil && len(username) > 0: return fmt.Errorf("container has runAsNonRoot and image has non-numeric user (%s), cannot verify user is non-root (pod: %q, container: %s)", username, format.Pod(pod), container.Name) default: returnnil } }
// Rather than just erroring out later in setuid(2) and setgid(2), check // that the user is mapped here. if _, err := config.Config.HostUID(execUser.Uid); err != nil { return errors.New("cannot set uid to unmapped user in user namespace") } if _, err := config.Config.HostGID(execUser.Gid); err != nil { return errors.New("cannot set gid to unmapped user in user namespace") }
if config.RootlessEUID { // We cannot set any additional groups in a rootless container and thus // we bail if the user asked us to do so. TODO: We currently can't do // this check earlier, but if libcontainer.Process.User was typesafe // this might work. iflen(addGroups) > 0 { return errors.New("cannot set any additional groups in a rootless container") } }
// Before we change to the container's user make sure that the processes // STDIO is correctly owned by the user that we are switching to. if err := fixStdioPermissions(config, execUser); err != nil { return err }
// This isn't allowed in an unprivileged user namespace since Linux 3.19. // There's nothing we can do about /etc/group entries, so we silently // ignore setting groups here (since the user didn't explicitly ask us to // set the group). allowSupGroups := !config.RootlessEUID && string(bytes.TrimSpace(setgroups)) != "deny"
if allowSupGroups { suppGroups := append(execUser.Sgids, addGroups...) if err := unix.Setgroups(suppGroups); err != nil { return err } }
// if we didn't get HOME already, set it based on the user's HOME if envHome := os.Getenv("HOME"); envHome == "" { if err := os.Setenv("HOME", execUser.Home); err != nil { return err } } returnnil }
funcGetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (*ExecUser, error) { if defaults == nil { defaults = new(ExecUser) }
// Copy over defaults. user := &ExecUser{ Uid: defaults.Uid, Gid: defaults.Gid, Sgids: defaults.Sgids, Home: defaults.Home, }
// Sgids slice *cannot* be nil. if user.Sgids == nil { user.Sgids = []int{} }
// Allow for userArg to have either "user" syntax, or optionally "user:group" syntax var userArg, groupArg string parseLine([]byte(userSpec), &userArg, &groupArg)
// Convert userArg and groupArg to be numeric, so we don't have to execute // Atoi *twice* for each iteration over lines. uidArg, uidErr := strconv.Atoi(userArg) gidArg, gidErr := strconv.Atoi(groupArg)
// Find the matching user. users, err := ParsePasswdFilter(passwd, func(u User)bool { if userArg == "" { // Default to current state of the user. return u.Uid == user.Uid }
if uidErr == nil { // If the userArg is numeric, always treat it as a UID. return uidArg == u.Uid }
return u.Name == userArg })
if err != nil && passwd != nil { if userArg == "" { userArg = strconv.Itoa(user.Uid) } returnnil, fmt.Errorf("unable to find user %s: %v", userArg, err) }
var matchedUserName string iflen(users) > 0 { // First match wins, even if there's more than one matching entry. matchedUserName = users[0].Name user.Uid = users[0].Uid user.Gid = users[0].Gid user.Home = users[0].Home } elseif userArg != "" { // If we can't find a user with the given username, the only other valid // option is if it's a numeric username with no associated entry in passwd.
if uidErr != nil { // Not numeric. returnnil, fmt.Errorf("unable to find user %s: %v", userArg, ErrNoPasswdEntries) } user.Uid = uidArg
// Must be inside valid uid range. if user.Uid < minID || user.Uid > maxID { returnnil, ErrRange }
// Okay, so it's numeric. We can just roll with this. } }