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

schema: added non-unique parameter to PasswdUser #985

Open
wants to merge 2 commits 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
3 changes: 3 additions & 0 deletions config/v3_2_experimental/schema/ignition.json
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,9 @@
},
"shell": {
"type": ["string", "null"]
},
"nonUnique": {
Copy link
Contributor

Choose a reason for hiding this comment

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

The name nonUnique follows the existing pattern of naming fields after useradd options. But I'm wondering if the name is too unclear in this case, since it doesn't mention UIDs.

"type": ["boolean", "null"]
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add a similar field to PasswdGroup for the groupadd call.

}
},
"required": [
Expand Down
1 change: 1 addition & 0 deletions config/v3_2_experimental/types/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ type PasswdUser struct {
NoCreateHome *bool `json:"noCreateHome,omitempty"`
NoLogInit *bool `json:"noLogInit,omitempty"`
NoUserGroup *bool `json:"noUserGroup,omitempty"`
NonUnique *bool `json:"nonUnique,omitempty"`
PasswordHash *string `json:"passwordHash,omitempty"`
PrimaryGroup *string `json:"primaryGroup,omitempty"`
SSHAuthorizedKeys []SSHAuthorizedKey `json:"sshAuthorizedKeys,omitempty"`
Expand Down
23 changes: 23 additions & 0 deletions internal/exec/stages/files/passwd.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package files

import (
"errors"
"fmt"
"path/filepath"

Expand Down Expand Up @@ -77,6 +78,23 @@ func (s *stage) createPasswd(config types.Config) error {
return nil
}

func userUIDConflict(a types.PasswdUser, list []types.PasswdUser) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

I might be missing something, but I don't think this function is necessary, since useradd will catch duplicates for us. And userUIDConflict won't catch conflicts with users that already exist on the system.

if a.UID == nil {
return nil
}

for _, b := range list {
if b.UID == nil || a.Name == b.Name {
continue
}

if uint64(*b.UID) == uint64(*a.UID) && ((*b.NonUnique) == false || (*a.NonUnique) == false) {
return errors.New(fmt.Sprintf("conflicting uid from user: %s with uid: %d", b.Name, *b.UID))
}
}
return nil
}

// createUsers creates the users as described in config.Passwd.Users.
func (s stage) createUsers(config types.Config) error {
if len(config.Passwd.Users) == 0 {
Expand All @@ -86,6 +104,11 @@ func (s stage) createUsers(config types.Config) error {
defer s.Logger.PopPrefix()

for _, u := range config.Passwd.Users {
if err := userUIDConflict(u, config.Passwd.Users); err != nil {
return fmt.Errorf("failed to create user %q: %v",
u.Name, err)
}

if err := s.EnsureUser(u); err != nil {
return fmt.Errorf("failed to create user %q: %v",
u.Name, err)
Expand Down
2 changes: 2 additions & 0 deletions internal/exec/util/passwd.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ func (u Util) EnsureUser(c types.PasswdUser) error {
strconv.FormatUint(uint64(*c.UID), 10))
}

args = appendIfTrue(args, c.NonUnique, "--non-unique")
Copy link
Contributor

Choose a reason for hiding this comment

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

If a config specifies two users with the same UID, and one of them specifies nonUnique: true and one of them doesn't, what should happen? The answer can't depend on the order of the entries, since Ignition configs are declarative.


args = appendIfStringSet(args, "--comment", c.Gecos)
args = appendIfStringSet(args, "--gid", c.PrimaryGroup)

Expand Down
18 changes: 14 additions & 4 deletions tests/positive/passwd/users.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ func AddPasswdUsers() types.Test {
{
"name": "jenkins",
"uid": 1020
},
{
"name": "test2",
"uid": 1030,
"nonUnique": true
},
{
"name": "test3",
"uid": 1030,
"nonUnique": true
}
]
}
Expand Down Expand Up @@ -116,28 +126,28 @@ ENCRYPT_METHOD SHA512
Name: "passwd",
Directory: "etc",
},
Contents: "root:x:0:0:root:/root:/bin/bash\ncore:x:500:500:CoreOS Admin:/home/core:/bin/bash\nsystemd-coredump:x:998:998:systemd Core Dumper:/:/sbin/nologin\nfleet:x:253:253::/:/sbin/nologin\ntest:x:1000:1000::/home/test:/bin/bash\njenkins:x:1020:1001::/home/jenkins:/bin/bash\n",
Contents: "root:x:0:0:root:/root:/bin/bash\ncore:x:500:500:CoreOS Admin:/home/core:/bin/bash\nsystemd-coredump:x:998:998:systemd Core Dumper:/:/sbin/nologin\nfleet:x:253:253::/:/sbin/nologin\ntest:x:1000:1000::/home/test:/bin/bash\njenkins:x:1020:1001::/home/jenkins:/bin/bash\ntest2:x:1030:1002::/home/test2:/bin/bash\ntest3:x:1030:1003::/home/test3:/bin/bash\n",
},
{
Node: types.Node{
Name: "group",
Directory: "etc",
},
Contents: "root:x:0:root\nwheel:x:10:root,core\nsudo:x:150:\ndocker:x:233:core\nsystemd-coredump:x:998:\nfleet:x:253:core\ncore:x:500:\nrkt-admin:x:999:\nrkt:x:251:core\ntest:x:1000:\njenkins:x:1001:\n",
Contents: "root:x:0:root\nwheel:x:10:root,core\nsudo:x:150:\ndocker:x:233:core\nsystemd-coredump:x:998:\nfleet:x:253:core\ncore:x:500:\nrkt-admin:x:999:\nrkt:x:251:core\ntest:x:1000:\njenkins:x:1001:\ntest2:x:1002:\ntest3:x:1003:\n",
},
{
Node: types.Node{
Name: "shadow",
Directory: "etc",
},
Contents: "root:*:15887:0:::::\ncore:*:15887:0:::::\nsystemd-coredump:!!:17301::::::\nfleet:!!:17301::::::\ntest:zJW/EKqqIk44o:17331:0:99999:7:::\njenkins:*:17331:0:99999:7:::\n",
Contents: "root:*:15887:0:::::\ncore:*:15887:0:::::\nsystemd-coredump:!!:17301::::::\nfleet:!!:17301::::::\ntest:zJW/EKqqIk44o:17331:0:99999:7:::\njenkins:*:17331:0:99999:7:::\ntest2:*:17331:0:99999:7:::\ntest3:*:17331:0:99999:7:::\n",
},
{
Node: types.Node{
Name: "gshadow",
Directory: "etc",
},
Contents: "root:*::root\nusers:*::\nsudo:*::\nwheel:*::root,core\nsudo:*::\ndocker:*::core\nsystemd-coredump:!!::\nfleet:!!::core\nrkt-admin:!!::\nrkt:!!::core\ncore:*::\ntest:!::\njenkins:!::\n",
Contents: "root:*::root\nusers:*::\nsudo:*::\nwheel:*::root,core\nsudo:*::\ndocker:*::core\nsystemd-coredump:!!::\nfleet:!!::core\nrkt-admin:!!::\nrkt:!!::core\ncore:*::\ntest:!::\njenkins:!::\ntest2:!::\ntest3:!::\n",
},
{
Node: types.Node{
Expand Down
2 changes: 2 additions & 0 deletions tests/stubs/useradd-stub/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ var (
flagGid int
flagGroups string
flagShell string
flagNonUnique bool
)

func main() {
Expand All @@ -54,6 +55,7 @@ func main() {
flag.IntVar(&flagGid, "gid", -1, "The group name or number of the user's initial login group")
flag.StringVar(&flagGroups, "groups", "", "A list of supplementary groups which the user is also a member of")
flag.StringVar(&flagShell, "shell", "", "The name of the user's login shell")
flag.BoolVar(&flagNonUnique, "non-unique", false, "Allow the creation of a user account with a duplicate (non-unique) UID. ")

flag.Parse()

Expand Down