Skip to content

Commit

Permalink
create ostree user sudoers file
Browse files Browse the repository at this point in the history
In the context of compatibility with edge-management when creating image ISO artifact.
When creating an ostree user, the user is created with username and ssh-key without a password, the user has no possibility to manage the system as has no password to enter when using sudo command.
Create a sudoer file at first boot stage.
FIXES: https://issues.redhat.com/browse/THEEDGE-3837
  • Loading branch information
ldjebran authored and achilleas-k committed Feb 8, 2024
1 parent 1709a76 commit d4ff36d
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 2 deletions.
2 changes: 2 additions & 0 deletions pkg/distro/image_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ type ImageConfig struct {
DisabledServices []string
DefaultTarget *string
Sysconfig []*osbuild.SysconfigStageOptions
// whether to create sudoer file for wheel group with NOPASSWD option
WheelNoPasswd *bool

// List of files from which to import GPG keys into the RPM database
GPGKeyFiles []string
Expand Down
8 changes: 8 additions & 0 deletions pkg/distro/image_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ func TestImageConfigInheritFrom(t *testing.T) {
},
LeapsecTz: common.ToPtr(""),
},
WheelNoPasswd: common.ToPtr(true),
},
expectedConfig: &ImageConfig{
Timezone: common.ToPtr("UTC"),
Expand All @@ -92,6 +93,7 @@ func TestImageConfigInheritFrom(t *testing.T) {
EnabledServices: []string{"sshd"},
DisabledServices: []string{"named"},
DefaultTarget: common.ToPtr("multi-user.target"),
WheelNoPasswd: common.ToPtr(true),
Sysconfig: []*osbuild.SysconfigStageOptions{
{
Kernel: &osbuild.SysconfigKernelOptions{
Expand Down Expand Up @@ -133,6 +135,7 @@ func TestImageConfigInheritFrom(t *testing.T) {
EnabledServices: []string{"sshd"},
DisabledServices: []string{"named"},
DefaultTarget: common.ToPtr("multi-user.target"),
WheelNoPasswd: common.ToPtr(true),
},
imageConfig: &ImageConfig{},
expectedConfig: &ImageConfig{
Expand All @@ -147,6 +150,7 @@ func TestImageConfigInheritFrom(t *testing.T) {
EnabledServices: []string{"sshd"},
DisabledServices: []string{"named"},
DefaultTarget: common.ToPtr("multi-user.target"),
WheelNoPasswd: common.ToPtr(true),
},
},
{
Expand All @@ -164,6 +168,7 @@ func TestImageConfigInheritFrom(t *testing.T) {
EnabledServices: []string{"sshd"},
DisabledServices: []string{"named"},
DefaultTarget: common.ToPtr("multi-user.target"),
WheelNoPasswd: common.ToPtr(true),
},
expectedConfig: &ImageConfig{
Timezone: common.ToPtr("America/New_York"),
Expand All @@ -177,6 +182,7 @@ func TestImageConfigInheritFrom(t *testing.T) {
EnabledServices: []string{"sshd"},
DisabledServices: []string{"named"},
DefaultTarget: common.ToPtr("multi-user.target"),
WheelNoPasswd: common.ToPtr(true),
},
},
{
Expand All @@ -194,6 +200,7 @@ func TestImageConfigInheritFrom(t *testing.T) {
EnabledServices: []string{"sshd"},
DisabledServices: []string{"named"},
DefaultTarget: common.ToPtr("multi-user.target"),
WheelNoPasswd: common.ToPtr(true),
},
expectedConfig: &ImageConfig{
Timezone: common.ToPtr("America/New_York"),
Expand All @@ -207,6 +214,7 @@ func TestImageConfigInheritFrom(t *testing.T) {
EnabledServices: []string{"sshd"},
DisabledServices: []string{"named"},
DefaultTarget: common.ToPtr("multi-user.target"),
WheelNoPasswd: common.ToPtr(true),
},
},
}
Expand Down
1 change: 1 addition & 0 deletions pkg/distro/rhel8/edge.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ func edgeInstallerImgType(rd distribution) imageType {
},
defaultImageConfig: &distro.ImageConfig{
EnabledServices: edgeServices(rd),
WheelNoPasswd: common.ToPtr(true),
},
rpmOstree: true,
bootISO: true,
Expand Down
4 changes: 4 additions & 0 deletions pkg/distro/rhel8/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ func edgeInstallerImage(workload workload.Workload,
rng *rand.Rand) (image.ImageKind, error) {

d := t.arch.distro
imageConfig := t.getDefaultImageConfig()

commit, err := makeOSTreePayloadCommit(options.OSTree, t.OSTreeRef())
if err != nil {
Expand All @@ -436,6 +437,9 @@ func edgeInstallerImage(workload workload.Workload,
img.ExtraBasePackages = packageSets[installerPkgsKey]
img.Users = users.UsersFromBP(customizations.GetUsers())
img.Groups = users.GroupsFromBP(customizations.GetGroups())
if imageConfig.WheelNoPasswd != nil {
img.WheelNoPasswd = *imageConfig.WheelNoPasswd
}

img.SquashfsCompression = "xz"
img.AdditionalDracutModules = []string{"prefixdevname", "prefixdevname-tools"}
Expand Down
1 change: 1 addition & 0 deletions pkg/distro/rhel9/edge.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ var (
defaultImageConfig: &distro.ImageConfig{
Locale: common.ToPtr("en_US.UTF-8"),
EnabledServices: edgeServices,
WheelNoPasswd: common.ToPtr(true),
},
rpmOstree: true,
bootISO: true,
Expand Down
4 changes: 4 additions & 0 deletions pkg/distro/rhel9/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ func edgeInstallerImage(workload workload.Workload,
rng *rand.Rand) (image.ImageKind, error) {

d := t.arch.distro
imageConfig := t.getDefaultImageConfig()

commit, err := makeOSTreePayloadCommit(options.OSTree, t.OSTreeRef())
if err != nil {
Expand All @@ -389,6 +390,9 @@ func edgeInstallerImage(workload workload.Workload,
img.ExtraBasePackages = packageSets[installerPkgsKey]
img.Users = users.UsersFromBP(customizations.GetUsers())
img.Groups = users.GroupsFromBP(customizations.GetGroups())
if imageConfig.WheelNoPasswd != nil {
img.WheelNoPasswd = *imageConfig.WheelNoPasswd
}

img.SquashfsCompression = "xz"
img.AdditionalDracutModules = []string{
Expand Down
4 changes: 3 additions & 1 deletion pkg/image/anaconda_ostree_installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ type AnacondaOSTreeInstaller struct {
ExtraBasePackages rpmmd.PackageSet
Users []users.User
Groups []users.Group
// whether to create sudoer file for wheel group with NOPASSWD option
WheelNoPasswd bool

SquashfsCompression string

Expand Down Expand Up @@ -108,7 +110,7 @@ func (img *AnacondaOSTreeInstaller) InstantiateManifest(m *manifest.Manifest,
isoTreePipeline.Remote = img.Remote
isoTreePipeline.Users = img.Users
isoTreePipeline.Groups = img.Groups

isoTreePipeline.WheelNoPasswd = img.WheelNoPasswd
isoTreePipeline.SquashfsCompression = img.SquashfsCompression

// For ostree installers, always put the kickstart file in the root of the ISO
Expand Down
33 changes: 32 additions & 1 deletion pkg/manifest/anaconda_installer_iso_tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ type AnacondaInstallerISOTree struct {
Remote string
Users []users.User
Groups []users.Group
// whether to create sudoer file for wheel group with NOPASSWD option
WheelNoPasswd bool

PartitionTable *disk.PartitionTable

Expand Down Expand Up @@ -330,9 +332,16 @@ func (p *AnacondaInstallerISOTree) serialize() osbuild.Pipeline {
osbuild.NewOstreePullStageInputs("org.osbuild.source", p.ostreeCommitSpec.Checksum, p.ostreeCommitSpec.Ref),
))

baseksPath := p.KSPath
if p.WheelNoPasswd {
// move the base kickstart to another file so we can write the
// %post kickstart snippet in the default location and include the
// base
baseksPath = "/osbuild-base.ks"
}
// Configure the kickstart file with the payload and any user options
kickstartOptions, err := osbuild.NewKickstartStageOptionsWithOSTreeCommit(
p.KSPath,
baseksPath,
p.Users,
p.Groups,
makeISORootPath(p.PayloadPath),
Expand All @@ -345,6 +354,28 @@ func (p *AnacondaInstallerISOTree) serialize() osbuild.Pipeline {
}

pipeline.AddStage(osbuild.NewKickstartStage(kickstartOptions))

if p.WheelNoPasswd {
// Because osbuild core only supports a subset of options,
// we append to the base here with hardcoded wheel group with NOPASSWD option
hardcodedKickstartBits := `
%include /run/install/repo/osbuild-base.ks
%post
echo -e "%wheel\tALL=(ALL)\tNOPASSWD: ALL" > "/etc/sudoers.d/wheel"
chmod 0440 /etc/sudoers.d/wheel
restorecon -rvF /etc/sudoers.d
%end
`
kickstartFile, err := fsnode.NewFile(p.KSPath, nil, nil, nil, []byte(hardcodedKickstartBits))
if err != nil {
panic(err)
}

p.Files = []*fsnode.File{kickstartFile}

pipeline.AddStages(osbuild.GenFileNodesStages(p.Files)...)
}
}

if p.containerSpec != nil {
Expand Down

0 comments on commit d4ff36d

Please sign in to comment.