Skip to content

Commit

Permalink
manifest: test user kickstart file injection
Browse files Browse the repository at this point in the history
Test tar and ostree commit kickstart files with the existing
checkKickstartUnattendedOptions() function.
Add a new checkRawKickstartForContainer() for the container ISO
pipeline.
  • Loading branch information
achilleas-k committed Apr 25, 2024
1 parent 0f90a82 commit e6d1b18
Showing 1 changed file with 134 additions and 2 deletions.
136 changes: 134 additions & 2 deletions pkg/manifest/anaconda_installer_iso_tree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,17 @@ chmod 0440 /etc/sudoers.d/%wheel
restorecon -rvF /etc/sudoers.d
%end
`
}
ksContainerContent = `reqpart --add-boot
part swap --fstype=swap --size=1024
part / --fstype=ext4 --grow
content += extra
reboot --eject
%post
bootc switch --mutate-in-place --transport registry local.example.org/registry/org/image
%end
`
)

func calculateInlineFileChecksum(parts ...string) string {
content := "%include /run/install/repo/test-base.ks\n"
Expand Down Expand Up @@ -220,6 +228,35 @@ func checkKickstartUnattendedOptions(stages []*osbuild.Stage, sudobits bool, ext
return nil
}

func checkRawKickstartForContainer(stages []*osbuild.Stage, extra string) error {
ksParts := []string{ksContainerContent}
if extra != "" {
ksParts = append(ksParts, extra)
}
ksCopyStageOptions := findRawKickstartFileStage(stages)
if ksCopyStageOptions == nil { // raw kickstart stage (file stage) should exist
return fmt.Errorf("expected raw kickstart file but not found")
}

if ksCopyStageOptions != nil {
contentHash := calculateInlineFileChecksum(ksParts...)
expContentID := fmt.Sprintf("input://file-%[1]s/sha256:%[1]s", contentHash)
// inline file IDs are the hash of their content so this is the hash of the expected content
if inlineID := ksCopyStageOptions.Paths[0].From; inlineID != expContentID {
return fmt.Errorf("raw kickstart content mismatch: %s != %s", expContentID, inlineID)
}
}

ksOptions := getKickstartOptions(stages)

// check the kickstart path depending on whether we have extra raw content included
if ksOptions.Path != testBaseKsPath {
return fmt.Errorf("kickstart file path should be %q but is %q", testBaseKsPath, ksOptions.Path)
}

return nil
}

func TestAnacondaISOTreePayloadsBad(t *testing.T) {
assert := assert.New(t)
pipeline := newTestAnacondaISOTree()
Expand Down Expand Up @@ -313,6 +350,47 @@ func TestAnacondaISOTreeSerializeWithOS(t *testing.T) {
assert.NoError(t, checkKickstartUnattendedOptions(sp.Stages, true, ""))
})

t.Run("user-kickstart-without-sudo-bits", func(t *testing.T) {
userks := "%post\necho 'Some kind of text in a file sent by post'\n%end"
pipeline := newTestAnacondaISOTree()
pipeline.OSPipeline = osPayload
pipeline.Kickstart = &kickstart.Options{
Path: testKsPath,
Unattended: true,
UserFile: &kickstart.File{
Contents: userks,
},
}
pipeline.ISOLinux = true
pipeline.serializeStart(nil, nil, nil, nil)
sp := pipeline.serialize()
pipeline.serializeEnd()
assert.NoError(t, checkISOTreeStages(sp.Stages, append(payloadStages, "org.osbuild.isolinux", "org.osbuild.kickstart"),
variantStages))
assert.NoError(t, checkKickstartUnattendedOptions(sp.Stages, false, userks))
})

t.Run("user-kickstart-with-sudo-bits", func(t *testing.T) {
userks := "%post\necho 'Some kind of text in a file sent by post'\n%end"
pipeline := newTestAnacondaISOTree()
pipeline.OSPipeline = osPayload
pipeline.Kickstart = &kickstart.Options{
Path: testKsPath,
Unattended: true,
SudoNopasswd: []string{`%wheel`, `%sudo`},
UserFile: &kickstart.File{
Contents: userks,
},
}
pipeline.ISOLinux = true
pipeline.serializeStart(nil, nil, nil, nil)
sp := pipeline.serialize()
pipeline.serializeEnd()
assert.NoError(t, checkISOTreeStages(sp.Stages, append(payloadStages, "org.osbuild.isolinux", "org.osbuild.kickstart"),
variantStages))
assert.NoError(t, checkKickstartUnattendedOptions(sp.Stages, true, userks))
})

}

func TestAnacondaISOTreeSerializeWithOSTree(t *testing.T) {
Expand Down Expand Up @@ -380,6 +458,43 @@ func TestAnacondaISOTreeSerializeWithOSTree(t *testing.T) {
assert.NoError(t, checkISOTreeStages(sp.Stages, append(payloadStages, "org.osbuild.isolinux"), variantStages))
assert.NoError(t, checkKickstartUnattendedOptions(sp.Stages, true, ""))
})

t.Run("user-kickstart-without-sudo-bits", func(t *testing.T) {
userks := "%post\necho 'Some kind of text in a file sent by post'\n%end"
pipeline := newTestAnacondaISOTree()
pipeline.Kickstart = &kickstart.Options{
Path: testKsPath,
Unattended: true,
UserFile: &kickstart.File{
Contents: userks,
},
}
pipeline.ISOLinux = true
pipeline.serializeStart(nil, nil, []ostree.CommitSpec{ostreeCommit}, nil)
sp := pipeline.serialize()
pipeline.serializeEnd()
assert.NoError(t, checkISOTreeStages(sp.Stages, append(payloadStages, "org.osbuild.isolinux"), variantStages))
assert.NoError(t, checkKickstartUnattendedOptions(sp.Stages, false, userks))
})

t.Run("user-kickstart-with-sudo-bits", func(t *testing.T) {
userks := "%post\necho 'Some kind of text in a file sent by post'\n%end"
pipeline := newTestAnacondaISOTree()
pipeline.Kickstart = &kickstart.Options{
Path: testKsPath,
Unattended: true,
SudoNopasswd: []string{`%wheel`, `%sudo`},
UserFile: &kickstart.File{
Contents: userks,
},
}
pipeline.ISOLinux = true
pipeline.serializeStart(nil, nil, []ostree.CommitSpec{ostreeCommit}, nil)
sp := pipeline.serialize()
pipeline.serializeEnd()
assert.NoError(t, checkISOTreeStages(sp.Stages, append(payloadStages, "org.osbuild.isolinux"), variantStages))
assert.NoError(t, checkKickstartUnattendedOptions(sp.Stages, true, userks))
})
}

func TestAnacondaISOTreeSerializeWithContainer(t *testing.T) {
Expand Down Expand Up @@ -451,6 +566,23 @@ func TestAnacondaISOTreeSerializeWithContainer(t *testing.T) {
assert.Equal(t, 1, len(opts.Network))
assert.Equal(t, "on", opts.Network[0].OnBoot)
})

t.Run("user-kickstart", func(t *testing.T) {
userks := "%post\necho 'Some kind of text in a file sent by post'\n%end"
pipeline := newTestAnacondaISOTree()
pipeline.Kickstart = &kickstart.Options{
Path: testKsPath,
UserFile: &kickstart.File{
Contents: userks,
},
}
pipeline.ISOLinux = true
pipeline.serializeStart(nil, []container.Spec{containerPayload}, nil, nil)
sp := pipeline.serialize()
pipeline.serializeEnd()
assert.NoError(t, checkISOTreeStages(sp.Stages, append(payloadStages, "org.osbuild.isolinux"), variantStages))
assert.NoError(t, checkRawKickstartForContainer(sp.Stages, userks))
})
}

func TestMakeKickstartSudoersPostEmpty(t *testing.T) {
Expand Down

0 comments on commit e6d1b18

Please sign in to comment.