diff --git a/cmd/image-builder/describeimg_test.go b/cmd/image-builder/describeimg_test.go index feae8b2279..ed3c967e28 100644 --- a/cmd/image-builder/describeimg_test.go +++ b/cmd/image-builder/describeimg_test.go @@ -72,6 +72,7 @@ blueprint: - customizations.directories - customizations.files - customizations.firewall + - customizations.firstboot - customizations.user - customizations.sshkey - customizations.group @@ -104,9 +105,11 @@ func TestDescribeImageRequiredBlueprintOptions(t *testing.T) { blueprint: supported_options: - distro + - customizations.cacerts - customizations.dnf - customizations.installation_device - customizations.filesystem + - customizations.firstboot - customizations.disk - customizations.fdo - customizations.ignition diff --git a/data/distrodefs/eln-11/archive.yaml b/data/distrodefs/eln-11/archive.yaml index 5361464a64..e467f8f921 100644 --- a/data/distrodefs/eln-11/archive.yaml +++ b/data/distrodefs/eln-11/archive.yaml @@ -32,6 +32,7 @@ image_types: - "customizations.dnf" - "customizations.files" - "customizations.firewall" + - "customizations.firstboot" - "customizations.user" - "customizations.sshkey" - "customizations.group" diff --git a/data/distrodefs/eln-11/container.yaml b/data/distrodefs/eln-11/container.yaml index 19546ac0f1..daafa2aaac 100644 --- a/data/distrodefs/eln-11/container.yaml +++ b/data/distrodefs/eln-11/container.yaml @@ -19,9 +19,11 @@ - "groups" - "enabled_modules" - "containers" + - "customizations.cacerts" - "customizations.directories" - "customizations.files" - "customizations.firewall" + - "customizations.firstboot" - "customizations.user" - "customizations.sshkey" - "customizations.group" diff --git a/data/distrodefs/eln-11/disk.yaml b/data/distrodefs/eln-11/disk.yaml index 94f7772bf6..cfe6d2ce20 100644 --- a/data/distrodefs/eln-11/disk.yaml +++ b/data/distrodefs/eln-11/disk.yaml @@ -297,6 +297,7 @@ - "customizations.dnf" - "customizations.files" - "customizations.filesystem" + - "customizations.firstboot" - "customizations.partitioning_mode" - "customizations.fips" - "customizations.firewall" diff --git a/data/distrodefs/eln-11/installer.yaml b/data/distrodefs/eln-11/installer.yaml index e652baa505..55c1d550fc 100644 --- a/data/distrodefs/eln-11/installer.yaml +++ b/data/distrodefs/eln-11/installer.yaml @@ -508,6 +508,7 @@ image_types: - "customizations.directories" - "customizations.files" - "customizations.firewall" + - "customizations.firstboot" - "customizations.user" - "customizations.sshkey" - "customizations.group" diff --git a/data/distrodefs/eln-11/network.yaml b/data/distrodefs/eln-11/network.yaml index 9b82d4908e..9f4c6a2924 100644 --- a/data/distrodefs/eln-11/network.yaml +++ b/data/distrodefs/eln-11/network.yaml @@ -13,6 +13,7 @@ - "customizations.files" - "customizations.fips" - "customizations.firewall" + - "customizations.firstboot" - "customizations.user" - "customizations.sshkey" - "customizations.group" diff --git a/data/distrodefs/eln-11/wsl.yaml b/data/distrodefs/eln-11/wsl.yaml index 3c68671d34..0e1b237ad2 100644 --- a/data/distrodefs/eln-11/wsl.yaml +++ b/data/distrodefs/eln-11/wsl.yaml @@ -153,10 +153,12 @@ image_types: - "groups" - "enabled_modules" - "containers" + - "customizations.cacerts" - "customizations.dnf" - "customizations.directories" - "customizations.files" - "customizations.firewall" + - "customizations.firstboot" - "customizations.user" - "customizations.sshkey" - "customizations.group" diff --git a/data/distrodefs/fedora/imagetypes.yaml b/data/distrodefs/fedora/imagetypes.yaml index 9bae37a8ec..4018d7d884 100644 --- a/data/distrodefs/fedora/imagetypes.yaml +++ b/data/distrodefs/fedora/imagetypes.yaml @@ -1077,6 +1077,7 @@ - "customizations.disk" - "customizations.files" - "customizations.filesystem" + - "customizations.firstboot" - "customizations.partitioning_mode" - "customizations.fips" - "customizations.firewall" @@ -1101,10 +1102,12 @@ - "groups" - "enabled_modules" - "containers" + - "customizations.cacerts" - "customizations.directories" - "customizations.files" - "customizations.fips" - "customizations.firewall" + - "customizations.firstboot" - "customizations.user" - "customizations.sshkey" - "customizations.group" @@ -1123,9 +1126,11 @@ - "groups" - "enabled_modules" - "containers" + - "customizations.cacerts" - "customizations.directories" - "customizations.files" - "customizations.firewall" + - "customizations.firstboot" - "customizations.user" - "customizations.sshkey" - "customizations.group" @@ -1138,10 +1143,12 @@ # options supported by ostree disk (deployment) image types supported_options_ostree_disk: &supported_options_ostree_disk - "distro" + - "customizations.cacerts" - "customizations.files" - "customizations.directories" - "customizations.disk" - "customizations.filesystem" + - "customizations.firstboot" - "customizations.partitioning_mode" - "customizations.fips" - "customizations.user" @@ -1164,6 +1171,7 @@ - "customizations.files" - "customizations.fips" - "customizations.firewall" + - "customizations.firstboot" - "customizations.user" - "customizations.sshkey" - "customizations.group" @@ -2309,6 +2317,7 @@ image_types: - "containers" - "customizations.installer" - "customizations.cacerts" + - "customizations.firstboot" - "customizations.directories" - "customizations.files" - "customizations.firewall" diff --git a/data/distrodefs/rhel-10/imagetypes.yaml b/data/distrodefs/rhel-10/imagetypes.yaml index 1f88ee9be1..415c95acf7 100644 --- a/data/distrodefs/rhel-10/imagetypes.yaml +++ b/data/distrodefs/rhel-10/imagetypes.yaml @@ -853,6 +853,7 @@ - "customizations.dnf" - "customizations.files" - "customizations.filesystem" + - "customizations.firstboot" - "customizations.partitioning_mode" - "customizations.fips" - "customizations.firewall" @@ -884,6 +885,7 @@ - "customizations.files" - "customizations.fips" - "customizations.firewall" + - "customizations.firstboot" - "customizations.user" - "customizations.sshkey" - "customizations.group" @@ -905,9 +907,11 @@ - "groups" - "enabled_modules" - "containers" + - "customizations.cacerts" - "customizations.directories" - "customizations.files" - "customizations.firewall" + - "customizations.firstboot" - "customizations.user" - "customizations.sshkey" - "customizations.group" @@ -1468,6 +1472,7 @@ image_types: - "customizations.dnf" - "customizations.files" - "customizations.firewall" + - "customizations.firstboot" - "customizations.user" - "customizations.sshkey" - "customizations.group" @@ -1836,6 +1841,7 @@ image_types: - "customizations.dnf" - "customizations.files" - "customizations.filesystem" + - "customizations.firstboot" - "customizations.partitioning_mode" - "customizations.fips" - "customizations.firewall" @@ -1996,10 +2002,12 @@ image_types: - "groups" - "enabled_modules" - "containers" + - "customizations.cacerts" - "customizations.dnf" - "customizations.directories" - "customizations.files" - "customizations.firewall" + - "customizations.firstboot" - "customizations.user" - "customizations.sshkey" - "customizations.group" @@ -2196,6 +2204,7 @@ image_types: - "customizations.directories" - "customizations.files" - "customizations.firewall" + - "customizations.firstboot" - "customizations.user" - "customizations.sshkey" - "customizations.group" @@ -2463,6 +2472,7 @@ image_types: - "customizations.dnf" - "customizations.files" - "customizations.filesystem" + - "customizations.firstboot" - "customizations.partitioning_mode" - "customizations.fips" - "customizations.firewall" diff --git a/data/distrodefs/rhel-7/imagetypes.yaml b/data/distrodefs/rhel-7/imagetypes.yaml index 4ef6a20f2b..be6fdbd09d 100644 --- a/data/distrodefs/rhel-7/imagetypes.yaml +++ b/data/distrodefs/rhel-7/imagetypes.yaml @@ -221,6 +221,7 @@ - "customizations.disk" - "customizations.files" - "customizations.filesystem" + - "customizations.firstboot" - "customizations.partitioning_mode" - "customizations.fips" - "customizations.firewall" diff --git a/data/distrodefs/rhel-8/imagetypes.yaml b/data/distrodefs/rhel-8/imagetypes.yaml index 1311512d1c..a6dfc39643 100644 --- a/data/distrodefs/rhel-8/imagetypes.yaml +++ b/data/distrodefs/rhel-8/imagetypes.yaml @@ -1262,6 +1262,7 @@ - "customizations.dnf" - "customizations.files" - "customizations.filesystem" + - "customizations.firstboot" - "customizations.partitioning_mode" - "customizations.fips" - "customizations.firewall" @@ -1287,11 +1288,13 @@ - "groups" - "enabled_modules" - "containers" + - "customizations.cacerts" - "customizations.dnf" - "customizations.directories" - "customizations.files" - "customizations.fips" - "customizations.firewall" + - "customizations.firstboot" - "customizations.user" - "customizations.sshkey" - "customizations.group" @@ -1306,11 +1309,13 @@ # options supported by ostree disk (deployment) image types supported_options_ostree_disk: &supported_options_ostree_disk - "distro" + - "customizations.cacerts" - "customizations.files" - "customizations.directories" - "customizations.disk" - "customizations.dnf" - "customizations.filesystem" + - "customizations.firstboot" - "customizations.partitioning_mode" - "customizations.fips" - "customizations.user" @@ -1961,6 +1966,7 @@ image_types: - "customizations.directories" - "customizations.files" - "customizations.firewall" + - "customizations.firstboot" - "customizations.user" - "customizations.sshkey" - "customizations.group" @@ -2009,6 +2015,7 @@ image_types: - "customizations.directories" - "customizations.files" - "customizations.firewall" + - "customizations.firstboot" - "customizations.user" - "customizations.sshkey" - "customizations.group" @@ -2386,8 +2393,10 @@ image_types: - "customizations.sshkey" - "customizations.group" - "customizations.fips" + - "customizations.cacerts" - "customizations.files" - "customizations.directories" + - "customizations.firstboot" - "customizations.dnf" required_options: - "customizations.installation_device" @@ -2774,10 +2783,12 @@ image_types: - "groups" - "enabled_modules" - "containers" + - "customizations.cacerts" - "customizations.dnf" - "customizations.directories" - "customizations.files" - "customizations.firewall" + - "customizations.firstboot" - "customizations.user" - "customizations.sshkey" - "customizations.group" diff --git a/data/distrodefs/rhel-9/imagetypes.yaml b/data/distrodefs/rhel-9/imagetypes.yaml index 3e85c5b82a..8a1c1f83c5 100644 --- a/data/distrodefs/rhel-9/imagetypes.yaml +++ b/data/distrodefs/rhel-9/imagetypes.yaml @@ -1330,6 +1330,7 @@ - "customizations.dnf" - "customizations.files" - "customizations.filesystem" + - "customizations.firstboot" - "customizations.partitioning_mode" - "customizations.fips" - "customizations.firewall" @@ -1355,11 +1356,13 @@ - "groups" - "enabled_modules" - "containers" + - "customizations.cacerts" - "customizations.dnf" - "customizations.directories" - "customizations.files" - "customizations.fips" - "customizations.firewall" + - "customizations.firstboot" - "customizations.user" - "customizations.sshkey" - "customizations.group" @@ -1374,11 +1377,13 @@ # options supported by ostree disk (deployment) image types supported_options_ostree_disk: &supported_options_ostree_disk - "distro" + - "customizations.cacerts" - "customizations.files" - "customizations.directories" - "customizations.disk" - "customizations.dnf" - "customizations.filesystem" + - "customizations.firstboot" - "customizations.partitioning_mode" - "customizations.fips" - "customizations.user" @@ -1402,6 +1407,7 @@ - "customizations.files" - "customizations.fips" - "customizations.firewall" + - "customizations.firstboot" - "customizations.user" - "customizations.sshkey" - "customizations.group" @@ -1423,9 +1429,11 @@ - "groups" - "enabled_modules" - "containers" + - "customizations.cacerts" - "customizations.directories" - "customizations.files" - "customizations.firewall" + - "customizations.firstboot" - "customizations.user" - "customizations.sshkey" - "customizations.group" @@ -2006,6 +2014,7 @@ image_types: - "customizations.directories" - "customizations.files" - "customizations.firewall" + - "customizations.firstboot" - "customizations.user" - "customizations.sshkey" - "customizations.group" @@ -2374,6 +2383,7 @@ image_types: - "customizations.dnf" - "customizations.files" - "customizations.filesystem" + - "customizations.firstboot" - "customizations.partitioning_mode" - "customizations.fips" - "customizations.firewall" @@ -2529,10 +2539,12 @@ image_types: - "groups" - "enabled_modules" - "containers" + - "customizations.cacerts" - "customizations.dnf" - "customizations.directories" - "customizations.files" - "customizations.firewall" + - "customizations.firstboot" - "customizations.user" - "customizations.sshkey" - "customizations.group" @@ -2619,6 +2631,7 @@ image_types: - "customizations.directories" - "customizations.files" - "customizations.firewall" + - "customizations.firstboot" - "customizations.user" - "customizations.sshkey" - "customizations.group" @@ -3352,9 +3365,11 @@ image_types: blueprint: supported_options: - "distro" + - "customizations.cacerts" - "customizations.dnf" - "customizations.installation_device" - "customizations.filesystem" + - "customizations.firstboot" - "customizations.disk" - "customizations.fdo" - "customizations.ignition" @@ -3543,6 +3558,7 @@ image_types: - "customizations.dnf" - "customizations.files" - "customizations.filesystem" + - "customizations.firstboot" - "customizations.partitioning_mode" - "customizations.fips" - "customizations.firewall" diff --git a/pkg/customizations/firstboot/firstboot.go b/pkg/customizations/firstboot/firstboot.go new file mode 100644 index 0000000000..d2663f596c --- /dev/null +++ b/pkg/customizations/firstboot/firstboot.go @@ -0,0 +1,142 @@ +package firstboot + +import ( + "errors" + "fmt" + "path/filepath" + "slices" + "strings" + + "github.com/osbuild/blueprint/pkg/blueprint" + "github.com/osbuild/image-builder/pkg/shutil" +) + +const firstbootPrefix = "osbuild-first-boot-" + +type FirstbootOptions struct { + Scripts []Script +} + +type Script struct { + Filename string + Contents string + IgnoreFailure bool + Certs []string + After []string + Before []string +} + +var ErrFirstbootAlreadySet = errors.New("firstboot customization already set") +var ErrFirstbootNameTaken = errors.New("firstboot name already taken") + +func validateCustomName(name string) error { + if name != filepath.Base(name) { + return fmt.Errorf("firstboot name %q is invalid: must be a simple filename without path separators", name) + } + if name == "satellite" || name == "aap" || strings.HasPrefix(name, "custom") { + return fmt.Errorf("firstboot name %q is reserved", name) + } + return nil +} + +func scriptFromCommon(common blueprint.FirstbootCommonCustomization, filename, contents string, certs []string) Script { + return Script{ + Filename: filename, + Contents: contents, + IgnoreFailure: common.IgnoreFailure, + Certs: certs, + After: slices.Clone(common.After), + Before: slices.Clone(common.Before), + } +} + +// FirstbootOptionsFromBP converts blueprint firstboot customizations into the +// internal representation used to generate osbuild stages. +// +// Script basenames are assigned as follows: +// - satellite scripts use osbuild-first-boot-satellite +// - aap scripts use osbuild-first-boot-aap +// - named custom scripts use osbuild-first-boot-{name} +// - unnamed custom scripts use osbuild-first-boot-custom-N +// +// At most one satellite and one aap script are allowed. Custom names must be a +// local path segment, must be unique, and must not be "satellite", "aap", or +// start with "custom". +// +// Returns ErrFirstbootAlreadySet when a second satellite or aap script is +// present, ErrFirstbootNameTaken when a custom name is reused, or an error when +// a custom name is invalid or reserved. +func FirstbootOptionsFromBP(bpFirstboot blueprint.FirstbootCustomization) (*FirstbootOptions, error) { + fo := &FirstbootOptions{} + used := make(map[string]struct{}) + var customN int + var satSet, aapSet bool + + for _, fbsc := range bpFirstboot.Scripts { + cust, sat, aap, err := fbsc.SelectUnion() + if err != nil { + return nil, err + } + + if cust != nil { + var filename string + if cust.Name == "" { + for { + customN++ + filename = fmt.Sprintf("%scustom-%d", firstbootPrefix, customN) + if _, ok := used[filename]; !ok { + break + } + } + } else { + if err := validateCustomName(cust.Name); err != nil { + return nil, err + } + filename = firstbootPrefix + cust.Name + if _, ok := used[filename]; ok { + return nil, fmt.Errorf("%w: %s", ErrFirstbootNameTaken, cust.Name) + } + } + used[filename] = struct{}{} + fo.Scripts = append(fo.Scripts, scriptFromCommon( + cust.FirstbootCommonCustomization, + filename, + cust.Contents, + nil, + )) + } + + if sat != nil { + if satSet { + return nil, fmt.Errorf("%w: satellite", ErrFirstbootAlreadySet) + } + satSet = true + fo.Scripts = append(fo.Scripts, scriptFromCommon( + sat.FirstbootCommonCustomization, + firstbootPrefix+"satellite", + sat.Command, + sat.CACerts, + )) + } + + if aap != nil { + if aapSet { + return nil, fmt.Errorf("%w: aap", ErrFirstbootAlreadySet) + } + aapSet = true + + contents := fmt.Sprintf("#!/usr/bin/bash\ncurl -i --data %s %s\n", + shutil.Quote("host_config_key="+aap.HostConfigKey), + shutil.Quote(aap.JobTemplateURL), + ) + fo.Scripts = append(fo.Scripts, scriptFromCommon( + aap.FirstbootCommonCustomization, + firstbootPrefix+"aap", + contents, + aap.CACerts, + )) + } + } + + return fo, nil +} diff --git a/pkg/customizations/firstboot/firstboot_test.go b/pkg/customizations/firstboot/firstboot_test.go new file mode 100644 index 0000000000..048283c6bc --- /dev/null +++ b/pkg/customizations/firstboot/firstboot_test.go @@ -0,0 +1,191 @@ +package firstboot_test + +import ( + "encoding/json" + "testing" + + "github.com/osbuild/blueprint/pkg/blueprint" + "github.com/osbuild/image-builder/pkg/customizations/firstboot" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestFirstbootOptionsFromBP(t *testing.T) { + tests := []struct { + name string + json string + want firstboot.FirstbootOptions + err string + }{ + { + name: "custom-named", + json: `{"scripts": [{"type":"custom","name":"hello","contents":"echo hello"}]}`, + want: firstboot.FirstbootOptions{ + Scripts: []firstboot.Script{{ + Filename: "osbuild-first-boot-hello", + Contents: "echo hello", + }}, + }, + }, + { + name: "custom-unnamed", + json: `{"scripts": [{"type":"custom","contents":"echo one"}]}`, + want: firstboot.FirstbootOptions{ + Scripts: []firstboot.Script{{ + Filename: "osbuild-first-boot-custom-1", + Contents: "echo one", + }}, + }, + }, + { + name: "custom-two-unnamed", + json: `{"scripts": [ + {"type":"custom","contents":"echo one"}, + {"type":"custom","contents":"echo two"} + ]}`, + want: firstboot.FirstbootOptions{ + Scripts: []firstboot.Script{ + {Filename: "osbuild-first-boot-custom-1", Contents: "echo one"}, + {Filename: "osbuild-first-boot-custom-2", Contents: "echo two"}, + }, + }, + }, + { + name: "satellite", + json: `{"scripts": [{"type":"satellite","command":"echo hello"}]}`, + want: firstboot.FirstbootOptions{ + Scripts: []firstboot.Script{{ + Filename: "osbuild-first-boot-satellite", + Contents: "echo hello", + }}, + }, + }, + { + name: "aap", + json: `{"scripts": [{"type":"aap","host_config_key":"key","job_template_url":"https://aap.example.com/api/v2/job_templates/9/callback/"}]}`, + want: firstboot.FirstbootOptions{ + Scripts: []firstboot.Script{{ + Filename: "osbuild-first-boot-aap", + Contents: "#!/usr/bin/bash\ncurl -i --data 'host_config_key=key' 'https://aap.example.com/api/v2/job_templates/9/callback/'\n", + }}, + }, + }, + { + name: "mixed", + json: `{"scripts": [ + {"type":"satellite","command":"echo sat"}, + {"type":"custom","name":"setup","contents":"echo setup"}, + {"type":"custom","contents":"echo unnamed"}, + {"type":"aap","host_config_key":"key","job_template_url":"https://aap.example.com/api/v2/job_templates/9/callback/"} + ]}`, + want: firstboot.FirstbootOptions{ + Scripts: []firstboot.Script{ + {Filename: "osbuild-first-boot-satellite", Contents: "echo sat"}, + {Filename: "osbuild-first-boot-setup", Contents: "echo setup"}, + {Filename: "osbuild-first-boot-custom-1", Contents: "echo unnamed"}, + {Filename: "osbuild-first-boot-aap", Contents: "#!/usr/bin/bash\ncurl -i --data 'host_config_key=key' 'https://aap.example.com/api/v2/job_templates/9/callback/'\n"}, + }, + }, + }, + { + name: "after-before", + json: `{"scripts": [ + {"type":"custom","name":"first","after":["sshd.service"],"before":["postgresql.service"],"contents":"echo first"}, + {"type":"custom","name":"second","contents":"echo second"} + ]}`, + want: firstboot.FirstbootOptions{ + Scripts: []firstboot.Script{ + { + Filename: "osbuild-first-boot-first", + Contents: "echo first", + After: []string{"sshd.service"}, + Before: []string{"postgresql.service"}, + }, + {Filename: "osbuild-first-boot-second", Contents: "echo second"}, + }, + }, + }, + { + name: "duplicate-satellite", + json: `{"scripts": [ + {"type":"satellite","command":"one"}, + {"type":"satellite","command":"two"} + ]}`, + err: "firstboot customization already set: satellite", + }, + { + name: "duplicate-aap", + json: `{"scripts": [ + {"type":"aap","host_config_key":"k","job_template_url":"https://example.com/callback/"}, + {"type":"aap","host_config_key":"k","job_template_url":"https://example.com/callback/"} + ]}`, + err: "firstboot customization already set: aap", + }, + { + name: "duplicate-custom-name", + json: `{"scripts": [ + {"type":"custom","name":"setup","contents":"one"}, + {"type":"custom","name":"setup","contents":"two"} + ]}`, + err: "firstboot name already taken: setup", + }, + { + name: "invalid-path-parent", + json: `{"scripts": [{"type":"custom","name":"../bad","contents":"bad"}]}`, + err: `firstboot name "../bad" is invalid`, + }, + { + name: "invalid-path-traversal", + json: `{"scripts": [{"type":"custom","name":"../../etc/passwd","contents":"bad"}]}`, + err: `firstboot name "../../etc/passwd" is invalid`, + }, + { + name: "invalid-path-with-slash", + json: `{"scripts": [{"type":"custom","name":"invalid/filename","contents":"bad"}]}`, + err: `firstboot name "invalid/filename" is invalid`, + }, + { + name: "invalid-absolute-path", + json: `{"scripts": [{"type":"custom","name":"/etc/shadow","contents":"bad"}]}`, + err: `firstboot name "/etc/shadow" is invalid`, + }, + { + name: "reserved-satellite", + json: `{"scripts": [{"type":"custom","name":"satellite","contents":"bad"}]}`, + err: `firstboot name "satellite" is reserved`, + }, + { + name: "reserved-aap", + json: `{"scripts": [{"type":"custom","name":"aap","contents":"bad"}]}`, + err: `firstboot name "aap" is reserved`, + }, + { + name: "reserved-custom-prefix", + json: `{"scripts": [{"type":"custom","name":"custom-42","contents":"bad"}]}`, + err: `firstboot name "custom-42" is reserved`, + }, + { + name: "reserved-custom-exact", + json: `{"scripts": [{"type":"custom","name":"custom","contents":"bad"}]}`, + err: `firstboot name "custom" is reserved`, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var input blueprint.FirstbootCustomization + require.NoError(t, json.Unmarshal([]byte(tt.json), &input)) + + got, err := firstboot.FirstbootOptionsFromBP(input) + if tt.err != "" { + require.Error(t, err) + assert.Contains(t, err.Error(), tt.err) + return + } + + require.NoError(t, err) + require.NotNil(t, got) + assert.Equal(t, tt.want, *got) + }) + } +} diff --git a/pkg/distro/generic/images.go b/pkg/distro/generic/images.go index 7924507592..f1fd59eadb 100644 --- a/pkg/distro/generic/images.go +++ b/pkg/distro/generic/images.go @@ -14,6 +14,7 @@ import ( "github.com/osbuild/image-builder/pkg/customizations/anaconda" "github.com/osbuild/image-builder/pkg/customizations/bootc" "github.com/osbuild/image-builder/pkg/customizations/fdo" + "github.com/osbuild/image-builder/pkg/customizations/firstboot" "github.com/osbuild/image-builder/pkg/customizations/fsnode" "github.com/osbuild/image-builder/pkg/customizations/ignition" "github.com/osbuild/image-builder/pkg/customizations/kickstart" @@ -354,6 +355,13 @@ func osCustomizations(t *imageType, osPackageSet rpmmd.PackageSet, options distr osc.CACerts = ca.PEMCerts } + if c != nil && c.Firstboot != nil { + osc.Firstboot, err = firstboot.FirstbootOptionsFromBP(*c.Firstboot) + if err != nil { + return manifest.OSCustomizations{}, fmt.Errorf("firstboot customization: %w", err) + } + } + if imageConfig.InstallWeakDeps != nil { osc.InstallWeakDeps = *imageConfig.InstallWeakDeps } diff --git a/pkg/manifest/os.go b/pkg/manifest/os.go index 71aa77b066..a7f794e9f1 100644 --- a/pkg/manifest/os.go +++ b/pkg/manifest/os.go @@ -15,6 +15,7 @@ import ( "github.com/osbuild/image-builder/pkg/arch" "github.com/osbuild/image-builder/pkg/container" "github.com/osbuild/image-builder/pkg/customizations/bootc" + "github.com/osbuild/image-builder/pkg/customizations/firstboot" "github.com/osbuild/image-builder/pkg/customizations/fsnode" "github.com/osbuild/image-builder/pkg/customizations/ignition" "github.com/osbuild/image-builder/pkg/customizations/oscap" @@ -171,10 +172,10 @@ type OSCustomizations struct { // here are always added at the end of the pipeline. Files []*fsnode.File - CACerts []string - - FIPS bool - Hostonly bool + CACerts []string + Firstboot *firstboot.FirstbootOptions + FIPS bool + Hostonly bool // NoBLS configures the image bootloader with traditional menu entries // instead of BLS. Required for legacy systems like RHEL 7. @@ -542,6 +543,8 @@ func (p *OS) serialize() (osbuild.Pipeline, error) { return osbuild.Pipeline{}, err } + var subscriptionEnabledServices []string + if p.ostreeParentSpec != nil { pipeline.AddStage(osbuild.NewOSTreePasswdStage("org.osbuild.source", p.ostreeParentSpec.Checksum)) } @@ -720,6 +723,19 @@ func (p *OS) serialize() (osbuild.Pipeline, error) { pipeline = prependStage(pipeline, osbuild.NewDracutConfStage(dracutConfConfig)) } + fbCerts, fbDirs, fbFiles, fbUnits, err := osbuild.GenFirstbootFromOptions(p.OSCustomizations.Firstboot) + if err != nil { + return osbuild.Pipeline{}, err + } + + if len(fbDirs) > 0 { + pipeline.AddStages(osbuild.GenDirectoryNodesStages(fbDirs)...) + } + + if len(fbFiles) > 0 { + p.addStagesForAllFilesAndInlineData(&pipeline, fbFiles) + } + for _, systemdUnitConfig := range p.OSCustomizations.SystemdDropin { pipeline.AddStage(osbuild.NewSystemdUnitStage(systemdUnitConfig)) } @@ -727,6 +743,9 @@ func (p *OS) serialize() (osbuild.Pipeline, error) { for _, systemdUnitCreateConfig := range p.OSCustomizations.SystemdUnit { pipeline.AddStage(osbuild.NewSystemdUnitCreateStage(systemdUnitCreateConfig)) } + for _, fbUnit := range fbUnits { + pipeline.AddStage(osbuild.NewSystemdUnitCreateStage(fbUnit)) + } if p.OSCustomizations.Authselect != nil { pipeline.AddStage(osbuild.NewAuthselectStage(p.OSCustomizations.Authselect)) @@ -806,7 +825,7 @@ func (p *OS) serialize() (osbuild.Pipeline, error) { pipeline.AddStage(subStage) pipeline.AddStages(osbuild.GenDirectoryNodesStages(subDirs)...) p.addStagesForAllFilesAndInlineData(&pipeline, subFiles) - p.OSCustomizations.EnabledServices = append(p.OSCustomizations.EnabledServices, subServices...) + subscriptionEnabledServices = subServices } if p.OSCustomizations.RHSMConfig != nil { @@ -959,6 +978,10 @@ func (p *OS) serialize() (osbuild.Pipeline, error) { disabledServices := []string{} maskedServices := []string{} enabledServices = append(enabledServices, p.OSCustomizations.EnabledServices...) + for _, fbUnit := range fbUnits { + enabledServices = append(enabledServices, fbUnit.Filename) + } + enabledServices = append(enabledServices, subscriptionEnabledServices...) disabledServices = append(disabledServices, p.OSCustomizations.DisabledServices...) maskedServices = append(maskedServices, p.OSCustomizations.MaskedServices...) if p.Environment != nil { @@ -984,14 +1007,13 @@ func (p *OS) serialize() (osbuild.Pipeline, error) { } if p.OSCustomizations.WSLDistributionConfig != nil { - // We format in our version string into the name field, if there's no %s in there nothing - // special will happen. - p.OSCustomizations.WSLDistributionConfig.OOBE.DefaultName = fmt.Sprintf( - p.OSCustomizations.WSLDistributionConfig.OOBE.DefaultName, + // Format version into the name field; if there's no %s nothing special happens. + wslDistConfig := *p.OSCustomizations.WSLDistributionConfig + wslDistConfig.OOBE.DefaultName = fmt.Sprintf( + wslDistConfig.OOBE.DefaultName, p.OSVersion, ) - - pipeline.AddStage(osbuild.NewWSLDistributionConfStage(p.OSCustomizations.WSLDistributionConfig)) + pipeline.AddStage(osbuild.NewWSLDistributionConfStage(&wslDistConfig)) } if p.OSCustomizations.FIPS { @@ -1017,8 +1039,10 @@ func (p *OS) serialize() (osbuild.Pipeline, error) { })) } - if len(p.OSCustomizations.CACerts) > 0 { - for _, cc := range p.OSCustomizations.CACerts { + allCACerts := append([]string{}, p.OSCustomizations.CACerts...) + allCACerts = append(allCACerts, fbCerts...) + if len(allCACerts) > 0 { + for _, cc := range allCACerts { files, err := osbuild.NewCAFileNodes(cc) if err != nil { return osbuild.Pipeline{}, err diff --git a/pkg/osbuild/firstboot.go b/pkg/osbuild/firstboot.go new file mode 100644 index 0000000000..31cc8519b3 --- /dev/null +++ b/pkg/osbuild/firstboot.go @@ -0,0 +1,124 @@ +package osbuild + +import ( + "fmt" + "io/fs" + "slices" + + "github.com/osbuild/image-builder/internal/common" + "github.com/osbuild/image-builder/pkg/customizations/firstboot" + "github.com/osbuild/image-builder/pkg/customizations/fsnode" +) + +const ( + firstbootMarkerPath = "/var/local/osbuild-first-boot/.run" + firstbootScriptDir = "/usr/libexec/osbuild-first-boot" +) + +var firstbootBaseAfter = []string{"network-online.target", "osbuild-first-boot.service"} + +// GenFirstbootFromOptions processes the firstboot options and returns a list of CA certificates to +// include in the image, a list of directory nodes, a list of file nodes to create the firstboot scripts, and +// systemd units to run the scripts on first boot. +func GenFirstbootFromOptions(fbo *firstboot.FirstbootOptions) ([]string, []*fsnode.Directory, []*fsnode.File, []*SystemdUnitCreateStageOptions, error) { + if fbo == nil { + return nil, nil, nil, nil, nil + } + + var certs []string + var dirs []*fsnode.Directory + var files []*fsnode.File + var units []*SystemdUnitCreateStageOptions + + if len(fbo.Scripts) > 0 { + d, err := fsnode.NewDirectory(firstbootScriptDir, common.ToPtr(fs.FileMode(0755)), "root", "root", true) + if err != nil { + return nil, nil, nil, nil, fmt.Errorf("error creating firstboot script directory node: %w", err) + } + dirs = append(dirs, d) + + d, err = fsnode.NewDirectory("/var/local/osbuild-first-boot", common.ToPtr(fs.FileMode(0755)), "root", "root", true) + if err != nil { + return nil, nil, nil, nil, fmt.Errorf("error creating firstboot marker directory node: %w", err) + } + dirs = append(dirs, d) + + f, err := fsnode.NewFile(firstbootMarkerPath, common.ToPtr(fs.FileMode(0770)), "root", "root", []byte{}) + if err != nil { + return nil, nil, nil, nil, fmt.Errorf("error creating firstboot marker node: %w", err) + } + files = append(files, f) + } + + var prevUnit string + for i, script := range fbo.Scripts { + unitFilename := script.Filename + ".service" + + exec := fmt.Sprintf("%s/%s", firstbootScriptDir, script.Filename) + f, err := fsnode.NewFile(exec, common.ToPtr(fs.FileMode(0770)), "root", "root", []byte(script.Contents)) + if err != nil { + return nil, nil, nil, nil, fmt.Errorf("error creating firstboot file node %q: %w", exec, err) + } + files = append(files, f) + + execStart := exec + if script.IgnoreFailure { + execStart = "-" + exec + } + + after := append([]string{}, firstbootBaseAfter...) + after = append(after, script.After...) + if prevUnit != "" { + after = append(after, prevUnit) + } + after = dedupeOrdered(after) + + var execStartPre []string + if i == len(fbo.Scripts)-1 { + execStartPre = []string{"/usr/bin/rm " + firstbootMarkerPath} + } + + unit := SystemdUnit{ + Unit: &UnitSection{ + ConditionPathExists: []string{firstbootMarkerPath}, + Wants: []string{"network-online.target"}, + After: after, + Before: slices.Clone(script.Before), + }, + Service: &ServiceSection{ + Type: OneshotServiceType, + ExecStart: []string{execStart}, + ExecStartPre: execStartPre, + RemainAfterExit: true, + }, + Install: &InstallSection{ + WantedBy: []string{"basic.target"}, + }, + } + + units = append(units, &SystemdUnitCreateStageOptions{ + Filename: unitFilename, + Config: unit, + UnitType: SystemUnitType, + UnitPath: UsrUnitPath, + }) + prevUnit = unitFilename + + certs = append(certs, script.Certs...) + } + + return certs, dirs, files, units, nil +} + +func dedupeOrdered(items []string) []string { + seen := make(map[string]struct{}, len(items)) + out := make([]string, 0, len(items)) + for _, item := range items { + if _, ok := seen[item]; ok { + continue + } + seen[item] = struct{}{} + out = append(out, item) + } + return out +} diff --git a/pkg/osbuild/firstboot_test.go b/pkg/osbuild/firstboot_test.go new file mode 100644 index 0000000000..06bb737fea --- /dev/null +++ b/pkg/osbuild/firstboot_test.go @@ -0,0 +1,294 @@ +package osbuild + +import ( + "io/fs" + "testing" + + "github.com/osbuild/image-builder/internal/common" + "github.com/osbuild/image-builder/pkg/customizations/firstboot" + "github.com/osbuild/image-builder/pkg/customizations/fsnode" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func firstbootTestDir(path string) *fsnode.Directory { + d, err := fsnode.NewDirectory(path, common.ToPtr(fs.FileMode(0755)), "root", "root", true) + if err != nil { + panic(err) + } + return d +} + +func firstbootTestFile(path, data string) *fsnode.File { + f, err := fsnode.NewFile(path, common.ToPtr(fs.FileMode(0770)), "root", "root", []byte(data)) + if err != nil { + panic(err) + } + return f +} + +func firstbootTestUnit(filename string, unit *UnitSection, service *ServiceSection) *SystemdUnitCreateStageOptions { + return &SystemdUnitCreateStageOptions{ + Filename: filename, + UnitType: SystemUnitType, + UnitPath: UsrUnitPath, + Config: SystemdUnit{ + Unit: unit, + Service: &ServiceSection{ + Type: OneshotServiceType, + ExecStart: service.ExecStart, + ExecStartPre: service.ExecStartPre, + RemainAfterExit: true, + }, + Install: &InstallSection{ + WantedBy: []string{"basic.target"}, + }, + }, + } +} + +func TestGenFirstbootFromOptions(t *testing.T) { + tests := []struct { + name string + fbo *firstboot.FirstbootOptions + wantCerts []string + wantDirs []*fsnode.Directory + wantFiles []*fsnode.File + wantUnits []*SystemdUnitCreateStageOptions + }{ + { + name: "nil", + fbo: nil, + }, + { + name: "empty-scripts", + fbo: &firstboot.FirstbootOptions{}, + }, + { + name: "single-script", + fbo: &firstboot.FirstbootOptions{ + Scripts: []firstboot.Script{ + { + Filename: "osbuild-first-boot-setup", + Contents: "#!/bin/bash\necho setup\n", + }, + }, + }, + wantDirs: []*fsnode.Directory{ + firstbootTestDir(firstbootScriptDir), + firstbootTestDir("/var/local/osbuild-first-boot"), + }, + wantFiles: []*fsnode.File{ + firstbootTestFile(firstbootMarkerPath, ""), + firstbootTestFile("/usr/libexec/osbuild-first-boot/osbuild-first-boot-setup", "#!/bin/bash\necho setup\n"), + }, + wantUnits: []*SystemdUnitCreateStageOptions{ + firstbootTestUnit("osbuild-first-boot-setup.service", + &UnitSection{ + ConditionPathExists: []string{firstbootMarkerPath}, + Wants: []string{"network-online.target"}, + After: []string{"network-online.target", "osbuild-first-boot.service"}, + }, + &ServiceSection{ + ExecStartPre: []string{"/usr/bin/rm " + firstbootMarkerPath}, + ExecStart: []string{"/usr/libexec/osbuild-first-boot/osbuild-first-boot-setup"}, + }, + ), + }, + }, + { + name: "multiple-scripts", + fbo: &firstboot.FirstbootOptions{ + Scripts: []firstboot.Script{ + { + Filename: "osbuild-first-boot-satellite", + Contents: "#!/usr/bin/bash\ncurl https://sat.example.com/register", + IgnoreFailure: true, + Certs: []string{"cert1", "cert2"}, + }, + { + Filename: "osbuild-first-boot-aap", + Contents: "#!/usr/bin/bash\ncurl -i --data 'host_config_key=host-config-key' 'https://aap.example.com/api/v2/job_templates/9/callback/'\n", + IgnoreFailure: true, + Certs: []string{"cert3", "cert4"}, + After: []string{"sshd.service"}, + }, + { + Filename: "osbuild-first-boot-custom-1", + Contents: "echo 'unnamed'", + }, + }, + }, + wantCerts: []string{"cert1", "cert2", "cert3", "cert4"}, + wantDirs: []*fsnode.Directory{ + firstbootTestDir(firstbootScriptDir), + firstbootTestDir("/var/local/osbuild-first-boot"), + }, + wantFiles: []*fsnode.File{ + firstbootTestFile(firstbootMarkerPath, ""), + firstbootTestFile("/usr/libexec/osbuild-first-boot/osbuild-first-boot-satellite", "#!/usr/bin/bash\ncurl https://sat.example.com/register"), + firstbootTestFile("/usr/libexec/osbuild-first-boot/osbuild-first-boot-aap", "#!/usr/bin/bash\ncurl -i --data 'host_config_key=host-config-key' 'https://aap.example.com/api/v2/job_templates/9/callback/'\n"), + firstbootTestFile("/usr/libexec/osbuild-first-boot/osbuild-first-boot-custom-1", "echo 'unnamed'"), + }, + wantUnits: []*SystemdUnitCreateStageOptions{ + firstbootTestUnit("osbuild-first-boot-satellite.service", + &UnitSection{ + ConditionPathExists: []string{firstbootMarkerPath}, + Wants: []string{"network-online.target"}, + After: []string{"network-online.target", "osbuild-first-boot.service"}, + }, + &ServiceSection{ + ExecStart: []string{"-/usr/libexec/osbuild-first-boot/osbuild-first-boot-satellite"}, + }, + ), + firstbootTestUnit("osbuild-first-boot-aap.service", + &UnitSection{ + ConditionPathExists: []string{firstbootMarkerPath}, + Wants: []string{"network-online.target"}, + After: []string{ + "network-online.target", + "osbuild-first-boot.service", + "sshd.service", + "osbuild-first-boot-satellite.service", + }, + }, + &ServiceSection{ + ExecStart: []string{"-/usr/libexec/osbuild-first-boot/osbuild-first-boot-aap"}, + }, + ), + firstbootTestUnit("osbuild-first-boot-custom-1.service", + &UnitSection{ + ConditionPathExists: []string{firstbootMarkerPath}, + Wants: []string{"network-online.target"}, + After: []string{ + "network-online.target", + "osbuild-first-boot.service", + "osbuild-first-boot-aap.service", + }, + }, + &ServiceSection{ + ExecStartPre: []string{"/usr/bin/rm " + firstbootMarkerPath}, + ExecStart: []string{"/usr/libexec/osbuild-first-boot/osbuild-first-boot-custom-1"}, + }, + ), + }, + }, + { + name: "ignore-failure-and-before", + fbo: &firstboot.FirstbootOptions{ + Scripts: []firstboot.Script{ + { + Filename: "osbuild-first-boot-ignore-errors", + Contents: "echo 'ignore errors'", + IgnoreFailure: true, + Before: []string{"postgresql.service"}, + }, + }, + }, + wantDirs: []*fsnode.Directory{ + firstbootTestDir(firstbootScriptDir), + firstbootTestDir("/var/local/osbuild-first-boot"), + }, + wantFiles: []*fsnode.File{ + firstbootTestFile(firstbootMarkerPath, ""), + firstbootTestFile("/usr/libexec/osbuild-first-boot/osbuild-first-boot-ignore-errors", "echo 'ignore errors'"), + }, + wantUnits: []*SystemdUnitCreateStageOptions{ + firstbootTestUnit("osbuild-first-boot-ignore-errors.service", + &UnitSection{ + ConditionPathExists: []string{firstbootMarkerPath}, + Wants: []string{"network-online.target"}, + After: []string{"network-online.target", "osbuild-first-boot.service"}, + Before: []string{"postgresql.service"}, + }, + &ServiceSection{ + ExecStartPre: []string{"/usr/bin/rm " + firstbootMarkerPath}, + ExecStart: []string{"-/usr/libexec/osbuild-first-boot/osbuild-first-boot-ignore-errors"}, + }, + ), + }, + }, + { + name: "two-scripts-in-order", + fbo: &firstboot.FirstbootOptions{ + Scripts: []firstboot.Script{ + { + Filename: "osbuild-first-boot-one", + Contents: "echo one", + }, + { + Filename: "osbuild-first-boot-two", + Contents: "echo two", + }, + }, + }, + wantDirs: []*fsnode.Directory{ + firstbootTestDir(firstbootScriptDir), + firstbootTestDir("/var/local/osbuild-first-boot"), + }, + wantFiles: []*fsnode.File{ + firstbootTestFile(firstbootMarkerPath, ""), + firstbootTestFile("/usr/libexec/osbuild-first-boot/osbuild-first-boot-one", "echo one"), + firstbootTestFile("/usr/libexec/osbuild-first-boot/osbuild-first-boot-two", "echo two"), + }, + wantUnits: []*SystemdUnitCreateStageOptions{ + firstbootTestUnit("osbuild-first-boot-one.service", + &UnitSection{ + ConditionPathExists: []string{firstbootMarkerPath}, + Wants: []string{"network-online.target"}, + After: []string{"network-online.target", "osbuild-first-boot.service"}, + }, + &ServiceSection{ + ExecStart: []string{"/usr/libexec/osbuild-first-boot/osbuild-first-boot-one"}, + }, + ), + firstbootTestUnit("osbuild-first-boot-two.service", + &UnitSection{ + ConditionPathExists: []string{firstbootMarkerPath}, + Wants: []string{"network-online.target"}, + After: []string{ + "network-online.target", + "osbuild-first-boot.service", + "osbuild-first-boot-one.service", + }, + }, + &ServiceSection{ + ExecStartPre: []string{"/usr/bin/rm " + firstbootMarkerPath}, + ExecStart: []string{"/usr/libexec/osbuild-first-boot/osbuild-first-boot-two"}, + }, + ), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + certs, dirs, files, units, err := GenFirstbootFromOptions(tt.fbo) + require.NoError(t, err) + + if tt.fbo == nil { + assert.Nil(t, certs) + assert.Nil(t, dirs) + assert.Nil(t, files) + assert.Nil(t, units) + return + } + + assert.Equal(t, tt.wantCerts, certs) + assert.Equal(t, tt.wantUnits, units) + require.Len(t, dirs, len(tt.wantDirs)) + for i := range tt.wantDirs { + assert.Equal(t, tt.wantDirs[i].Path(), dirs[i].Path()) + } + require.Len(t, files, len(tt.wantFiles)) + for i := range tt.wantFiles { + assert.Equal(t, tt.wantFiles[i].Path(), files[i].Path()) + assert.Equal(t, tt.wantFiles[i].Data(), files[i].Data()) + } + }) + } +} + +func TestFirstbootMarkerPath(t *testing.T) { + assert.Equal(t, "/var/local/osbuild-first-boot/.run", firstbootMarkerPath) +} diff --git a/test/configs/all-customizations.json b/test/configs/all-customizations.json index 7238e1f934..40f3f9d115 100644 --- a/test/configs/all-customizations.json +++ b/test/configs/all-customizations.json @@ -206,6 +206,34 @@ "1337:udp", "42-48:tcp" ] + }, + "firstboot": { + "scripts": [ + { + "type":"satellite", + "command": "#!/bin/bash\ncurl https://localhost/register", + "cacerts": ["-----BEGIN CERTIFICATE-----\nMIIDszCCApugAwIBAgIUJ4lK+JfdJCNgcEVxZDinJfKKbQswDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENhcm9saW5hMRAwDgYD\nVQQHDAdSYWxlaWdoMRAwDgYDVQQKDAdSZWQgSGF0MRwwGgYDVQQDDBNUZXN0IENB\nIGZvciBvc2J1aWxkMCAXDTI0MDkwMzEzMjkyMFoYDzIyOTgwNjE4MTMyOTIwWjBo\nMQswCQYDVQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExEDAOBgNVBAcM\nB1JhbGVpZ2gxEDAOBgNVBAoMB1JlZCBIYXQxHDAaBgNVBAMME1Rlc3QgQ0EgZm9y\nIG9zYnVpbGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDeA7OcWTrV\ngstoBsUaeJKm8nelg7Lc0WNXH6yOTLsr4td4yHs0YOvFGwgSf+ffV3RAG1mgqnMG\nMgkD2+z+7QhHbHHs3y0d0zfhA2bg0KVvfCWk7fNRPHY0UOePpXk245Bfw3D0VTpl\nF7nePk1I7ZY09snPWUeb2rjKXzYjKjzM0h27+ykV8I8+FbdyPk/pR8whyDqtHLUa\nXfFy2TFloDSYMkHKVd38BnL0bj91x5F+KsZkN4HzfbYwxLbCQfOSgy7q6TWce9kq\nLo6tya9vuvpWFm1dye7L+BodAQAq/dI/JMeCfyTb0eFb+tyzfr5aVIoqqDN+p9ft\ncw4OefpHbhtNAgMBAAGjUzBRMB0GA1UdDgQWBBRV2A9YmusekPzu5Yf08cV0oPL1\nwjAfBgNVHSMEGDAWgBRV2A9YmusekPzu5Yf08cV0oPL1wjAPBgNVHRMBAf8EBTAD\nAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCgQZ2Xfj+NxaKBZgn2KNxS0MTbhzHRz6Rn\nqJs+h8OUz2Crmaf6N+RHlmDRZXUrDjSHpxVT2LxFy7ofRrLYIezFDUYfb920VkkV\nSVcxh1YDFROJalfMoE6wdyR/LnK4MJZS9fUpeCJJc/A0J+9FK9CwcyUrHgJ8XbJh\nMKYyQ+cf6O7wzutuBpMyRqSKS+hVM7BQTmSFvv1eAJlo6klGAmmKiYmAEvcQadH1\ndjrujsA3Cn5vX2L+0yuiLB5/zoxqx5cEy97TuKUYB8OqMMujAXNzF4L3HJDUNba2\nAhEkFozMXwYX73TGbGZ0mawPS5D3v3tYTEmJFf6SnVCmUW1fs57g\n-----END CERTIFICATE-----\n"], + "ignore_failure": true + }, + { + "type":"custom", + "name":"script1", + "contents":"#!/bin/bash\ntouch /tmp/script1_done\n" + }, + { + "type":"custom", + "name":"script2", + "after":["osbuild-first-boot-script1.service"], + "contents":"#!/bin/bash\ntouch /tmp/script2_done\n" + }, + { + "type":"aap", + "name":"aap", + "host_config_key":"key", + "job_template_url":"https://localhost/api/v2/job_templates/9/callback/", + "ignore_failure": true + } + ] } } } diff --git a/test/data/manifest-checksums/centos_10-aarch64-ami-all_customizations b/test/data/manifest-checksums/centos_10-aarch64-ami-all_customizations index 05a9eb3829..c666a8451f 100644 --- a/test/data/manifest-checksums/centos_10-aarch64-ami-all_customizations +++ b/test/data/manifest-checksums/centos_10-aarch64-ami-all_customizations @@ -1 +1 @@ -8f5ae4e44115520262627254d6a53e27c68522216e4026f32df80b6d09e003aa +2127e35b3de5a097af0e26d097920dbace6b50d4ef91fe9a27191d71270f5704 diff --git a/test/data/manifest-checksums/centos_10-x86_64-ami-all_customizations b/test/data/manifest-checksums/centos_10-x86_64-ami-all_customizations index a46974735e..f2378b5d76 100644 --- a/test/data/manifest-checksums/centos_10-x86_64-ami-all_customizations +++ b/test/data/manifest-checksums/centos_10-x86_64-ami-all_customizations @@ -1 +1 @@ -7f31de06455f365ba07090601e3309c9646bfe9722d83b7feec42b72682e9521 +6290c91554f8873008f554af6a8bcc41f7889ec55d61a57bb4ee01df59c15b0e diff --git a/test/data/manifest-checksums/centos_9-aarch64-ami-all_customizations b/test/data/manifest-checksums/centos_9-aarch64-ami-all_customizations index ae37ec16ea..32d677343c 100644 --- a/test/data/manifest-checksums/centos_9-aarch64-ami-all_customizations +++ b/test/data/manifest-checksums/centos_9-aarch64-ami-all_customizations @@ -1 +1 @@ -321dceb9441153b965bd90585366eeec39f073166e0afa3d6bdbed2950160095 +2d68bf584808ed213df2a845819196309683ee0110afdcd61d36ffdad543fd1f diff --git a/test/data/manifest-checksums/centos_9-x86_64-ami-all_customizations b/test/data/manifest-checksums/centos_9-x86_64-ami-all_customizations index 9bf01d2f7f..f14e851f6b 100644 --- a/test/data/manifest-checksums/centos_9-x86_64-ami-all_customizations +++ b/test/data/manifest-checksums/centos_9-x86_64-ami-all_customizations @@ -1 +1 @@ -ca7183dbc117d2450cd089602c9d0abbb7a24e2aa9ac1a45d956f1dd19a3225e +e907fc01a27f0f52e634487d73be855d6862186d6d2f043059addc86bf6b4264 diff --git a/test/data/manifest-checksums/eln_11-aarch64-ami-all_customizations b/test/data/manifest-checksums/eln_11-aarch64-ami-all_customizations index ae9e20988d..429b6c161b 100644 --- a/test/data/manifest-checksums/eln_11-aarch64-ami-all_customizations +++ b/test/data/manifest-checksums/eln_11-aarch64-ami-all_customizations @@ -1 +1 @@ -45c5170cb7e597524be6fe5750114459c4b08424c312080098c66bf2417bf47d +d606f8536f6c0541c31e5f6d548040e6b679e2bf64bc4280619e268d0b5cc607 diff --git a/test/data/manifest-checksums/eln_11-x86_64-ami-all_customizations b/test/data/manifest-checksums/eln_11-x86_64-ami-all_customizations index 16318b64db..0a75584a62 100644 --- a/test/data/manifest-checksums/eln_11-x86_64-ami-all_customizations +++ b/test/data/manifest-checksums/eln_11-x86_64-ami-all_customizations @@ -1 +1 @@ -9227c46ebfa871901a2ba98eb6277285a6fce7e65f02b8adaae3d585d2ad9c1a +e6197d1d0699d2ddea35eb50a05e6f84d998b66d7319195a4fe09e2ec05700ba diff --git a/test/data/manifest-checksums/fedora_43-aarch64-generic_ami-all_customizations b/test/data/manifest-checksums/fedora_43-aarch64-generic_ami-all_customizations index a2c8d575a9..db066afa42 100644 --- a/test/data/manifest-checksums/fedora_43-aarch64-generic_ami-all_customizations +++ b/test/data/manifest-checksums/fedora_43-aarch64-generic_ami-all_customizations @@ -1 +1 @@ -d80989380b23e650b47bc8d8dc55ff50dc30162f37114d911bde72b643c67d2b +2d60381d9921ab0fe3b4c7908470cf655ab55335a0ac4289b98cfc06255bab8d diff --git a/test/data/manifest-checksums/fedora_43-aarch64-generic_qcow2-all_customizations b/test/data/manifest-checksums/fedora_43-aarch64-generic_qcow2-all_customizations index 12261f233d..b205020ca2 100644 --- a/test/data/manifest-checksums/fedora_43-aarch64-generic_qcow2-all_customizations +++ b/test/data/manifest-checksums/fedora_43-aarch64-generic_qcow2-all_customizations @@ -1 +1 @@ -ace0a7d15aa3db9af15ae75220c137f5097ee85f08497c71cd72a058ebdc4a2e +d148ad5a9e4898c903528c4b988b02251bdaa9e99f2883a13fd93094ca818837 diff --git a/test/data/manifest-checksums/fedora_43-aarch64-server_qcow2-all_customizations b/test/data/manifest-checksums/fedora_43-aarch64-server_qcow2-all_customizations index 1e35fa2e07..f2bf86c626 100644 --- a/test/data/manifest-checksums/fedora_43-aarch64-server_qcow2-all_customizations +++ b/test/data/manifest-checksums/fedora_43-aarch64-server_qcow2-all_customizations @@ -1 +1 @@ -755e587717e6deaa61777c45160c2d48b924318ec2c52c6c1b9739dbf4393b83 +10305730672fbc8c70a5411c30935452ea16f1c589e24a7f2c9865696e8197f4 diff --git a/test/data/manifest-checksums/fedora_43-ppc64le-generic_qcow2-all_customizations b/test/data/manifest-checksums/fedora_43-ppc64le-generic_qcow2-all_customizations index 2c0dda8dc4..02e08bce76 100644 --- a/test/data/manifest-checksums/fedora_43-ppc64le-generic_qcow2-all_customizations +++ b/test/data/manifest-checksums/fedora_43-ppc64le-generic_qcow2-all_customizations @@ -1 +1 @@ -3f8a88a7412a5f34106c86b1090ce3ea04c08d9ce945e1cbe5fe6d8ed75c3567 +0d32ec6cb6e977608ac5604cd3450db883872cbdcf05fed90d028c884c8032f7 diff --git a/test/data/manifest-checksums/fedora_43-ppc64le-server_qcow2-all_customizations b/test/data/manifest-checksums/fedora_43-ppc64le-server_qcow2-all_customizations index 88ad9df90d..3e0d18f2df 100644 --- a/test/data/manifest-checksums/fedora_43-ppc64le-server_qcow2-all_customizations +++ b/test/data/manifest-checksums/fedora_43-ppc64le-server_qcow2-all_customizations @@ -1 +1 @@ -e5c04ebdb078a75a135c4c5339628c4523c3ac35f4ff3372ce3c03c9be38c6ce +dab17281e3109bc315d78aa63a6926a4614ae6dc5329a7101e766aed19d8184b diff --git a/test/data/manifest-checksums/fedora_43-s390x-generic_qcow2-all_customizations b/test/data/manifest-checksums/fedora_43-s390x-generic_qcow2-all_customizations index 749e380ae6..1b591edee4 100644 --- a/test/data/manifest-checksums/fedora_43-s390x-generic_qcow2-all_customizations +++ b/test/data/manifest-checksums/fedora_43-s390x-generic_qcow2-all_customizations @@ -1 +1 @@ -3a4f662cd63a1c9532baa77e5933f882c1e0ad16315181c99ff04ebbc2c8650e +83a7436b2db1269e91bc7372af6cf1c395c026cb779d50e71559b7da8d287921 diff --git a/test/data/manifest-checksums/fedora_43-s390x-server_qcow2-all_customizations b/test/data/manifest-checksums/fedora_43-s390x-server_qcow2-all_customizations index 5e48c43c01..d857f5d547 100644 --- a/test/data/manifest-checksums/fedora_43-s390x-server_qcow2-all_customizations +++ b/test/data/manifest-checksums/fedora_43-s390x-server_qcow2-all_customizations @@ -1 +1 @@ -273aadc818cc5c4c5d766767d2a8e54acd93107a4e955d7511e90148cbc55706 +64d88198e933bff7b66bc206d1b5e4f0382dc1f230ac1a8e579396d08f4c1983 diff --git a/test/data/manifest-checksums/fedora_43-x86_64-generic_ami-all_customizations b/test/data/manifest-checksums/fedora_43-x86_64-generic_ami-all_customizations index d819eae7b1..4217a896ca 100644 --- a/test/data/manifest-checksums/fedora_43-x86_64-generic_ami-all_customizations +++ b/test/data/manifest-checksums/fedora_43-x86_64-generic_ami-all_customizations @@ -1 +1 @@ -efe36954ae118427eae7df23fb27cd168e33323e04acf0d2859be86ba70c3354 +31f442d468b8dceeaefb65b6dee41d928205d4d91507aa8372cdfd05dc2d3e5d diff --git a/test/data/manifest-checksums/fedora_43-x86_64-generic_qcow2-all_customizations b/test/data/manifest-checksums/fedora_43-x86_64-generic_qcow2-all_customizations index 6569ac20d3..52ad8768e5 100644 --- a/test/data/manifest-checksums/fedora_43-x86_64-generic_qcow2-all_customizations +++ b/test/data/manifest-checksums/fedora_43-x86_64-generic_qcow2-all_customizations @@ -1 +1 @@ -b72ff1815e9217fd4522b9c85fcbbf4b9f1fa88acf9b6d5a5c6d4f0f69e72006 +270394efeccfa24026fc481b8a206af6ebd91effa2673e2b2ec9b4a36d08f8ca diff --git a/test/data/manifest-checksums/fedora_43-x86_64-server_qcow2-all_customizations b/test/data/manifest-checksums/fedora_43-x86_64-server_qcow2-all_customizations index 60a2d7c945..9627c1006c 100644 --- a/test/data/manifest-checksums/fedora_43-x86_64-server_qcow2-all_customizations +++ b/test/data/manifest-checksums/fedora_43-x86_64-server_qcow2-all_customizations @@ -1 +1 @@ -8c74312ebbbe9c7e46417f959a1ab040ace75fc334a9b46751a8042d2f33f250 +f86621bd1476d66443aa9d65885910aceee41f0bcb4a33505a6e5062cb111b3e diff --git a/test/data/manifest-checksums/fedora_44-aarch64-generic_ami-all_customizations b/test/data/manifest-checksums/fedora_44-aarch64-generic_ami-all_customizations index fa05c7a384..6bcd76ed3c 100644 --- a/test/data/manifest-checksums/fedora_44-aarch64-generic_ami-all_customizations +++ b/test/data/manifest-checksums/fedora_44-aarch64-generic_ami-all_customizations @@ -1 +1 @@ -4073e5f9ee99bdf5af8d0f7029546ed99e4c9f7ca4c5765e5fa32d8df53c08b3 +ca98c991dc6b23f07f38d1ee66157f9fd743936b5bf43b1561851189c992e55c diff --git a/test/data/manifest-checksums/fedora_44-aarch64-generic_qcow2-all_customizations b/test/data/manifest-checksums/fedora_44-aarch64-generic_qcow2-all_customizations index dbf5c69316..acd99ec32e 100644 --- a/test/data/manifest-checksums/fedora_44-aarch64-generic_qcow2-all_customizations +++ b/test/data/manifest-checksums/fedora_44-aarch64-generic_qcow2-all_customizations @@ -1 +1 @@ -33e24c2f015b688211154e2cae1e16f107a5a2158b885f97c6b00b613b73e71a +31943b38298b9362a73288b4168b1e9f30c18ff86c1fd4145845610c7883be8b diff --git a/test/data/manifest-checksums/fedora_44-aarch64-server_qcow2-all_customizations b/test/data/manifest-checksums/fedora_44-aarch64-server_qcow2-all_customizations index dacaa89f2c..10c4dd21ff 100644 --- a/test/data/manifest-checksums/fedora_44-aarch64-server_qcow2-all_customizations +++ b/test/data/manifest-checksums/fedora_44-aarch64-server_qcow2-all_customizations @@ -1 +1 @@ -2b3d7da3dacbc52df418a55aeaeda4859319f1c673f734e25e392c809ba80565 +780cbd5f7a964e12b188c6de6c4f81e921d5d2a0d88dde0093e410e22dab8bf5 diff --git a/test/data/manifest-checksums/fedora_44-ppc64le-generic_qcow2-all_customizations b/test/data/manifest-checksums/fedora_44-ppc64le-generic_qcow2-all_customizations index 098f0a1051..3c369ae96a 100644 --- a/test/data/manifest-checksums/fedora_44-ppc64le-generic_qcow2-all_customizations +++ b/test/data/manifest-checksums/fedora_44-ppc64le-generic_qcow2-all_customizations @@ -1 +1 @@ -b125ce76f7241002fe1aec7a0d123541aab5801e2f52a53580fbcb1b5a07ce0b +d355e66b8042e10cd16a436cba44d0a9890efc77d9617876aa0f8f7d229b977b diff --git a/test/data/manifest-checksums/fedora_44-ppc64le-server_qcow2-all_customizations b/test/data/manifest-checksums/fedora_44-ppc64le-server_qcow2-all_customizations index 7da6228c98..02b5eb0a8c 100644 --- a/test/data/manifest-checksums/fedora_44-ppc64le-server_qcow2-all_customizations +++ b/test/data/manifest-checksums/fedora_44-ppc64le-server_qcow2-all_customizations @@ -1 +1 @@ -d767306f6be0d1413e49741b67815257f65aca1b9b974fc55076816c0b74d0b0 +5739290ebce48cab4766903990013f5fb22caa7d512c700b041bf6dfca53a481 diff --git a/test/data/manifest-checksums/fedora_44-s390x-generic_qcow2-all_customizations b/test/data/manifest-checksums/fedora_44-s390x-generic_qcow2-all_customizations index 444ddf1e9c..a843e8587f 100644 --- a/test/data/manifest-checksums/fedora_44-s390x-generic_qcow2-all_customizations +++ b/test/data/manifest-checksums/fedora_44-s390x-generic_qcow2-all_customizations @@ -1 +1 @@ -8227aa14a12e6c9e693be7eb630e50c616a876b6eb27f3cd5e027b591789cd90 +0d40e042f8982b399695059d79c8ee09b64978d9947d5f6233203fcfb6ae66d2 diff --git a/test/data/manifest-checksums/fedora_44-s390x-server_qcow2-all_customizations b/test/data/manifest-checksums/fedora_44-s390x-server_qcow2-all_customizations index 3bdeb45493..b35dd496f4 100644 --- a/test/data/manifest-checksums/fedora_44-s390x-server_qcow2-all_customizations +++ b/test/data/manifest-checksums/fedora_44-s390x-server_qcow2-all_customizations @@ -1 +1 @@ -b6b501730c202b10a904211b86758ec983fa67d9e0d9bc09b7a246ecb44d9692 +32b482ff3c439543cbed0a109e7432a577d8707ffe395647b61390c886d86ec2 diff --git a/test/data/manifest-checksums/fedora_44-x86_64-generic_ami-all_customizations b/test/data/manifest-checksums/fedora_44-x86_64-generic_ami-all_customizations index e3ac7703fe..3a1ada3d5b 100644 --- a/test/data/manifest-checksums/fedora_44-x86_64-generic_ami-all_customizations +++ b/test/data/manifest-checksums/fedora_44-x86_64-generic_ami-all_customizations @@ -1 +1 @@ -80cfb5ee8bb6eb8363c8a2829df4e48e6361dea164bc16fb5c8846cd11ea4656 +6609bb4b9819a6c44815a145e2c75b66cfa5d89fab5e57926b0f59c63a2b43f2 diff --git a/test/data/manifest-checksums/fedora_44-x86_64-generic_qcow2-all_customizations b/test/data/manifest-checksums/fedora_44-x86_64-generic_qcow2-all_customizations index 3bf6c23a96..e9a2c8d4ac 100644 --- a/test/data/manifest-checksums/fedora_44-x86_64-generic_qcow2-all_customizations +++ b/test/data/manifest-checksums/fedora_44-x86_64-generic_qcow2-all_customizations @@ -1 +1 @@ -c63d90e711880ce1bc959ccb340e2f98219d42eb1daf6e4692005a7db8641699 +29a6005fdde8be5efd21d721bf83fd16411a11aa9c6e45c16e0fe4dd89a5343a diff --git a/test/data/manifest-checksums/fedora_44-x86_64-server_qcow2-all_customizations b/test/data/manifest-checksums/fedora_44-x86_64-server_qcow2-all_customizations index 422e774649..3de368fdcf 100644 --- a/test/data/manifest-checksums/fedora_44-x86_64-server_qcow2-all_customizations +++ b/test/data/manifest-checksums/fedora_44-x86_64-server_qcow2-all_customizations @@ -1 +1 @@ -b8a7afbc8d0685d4085ed7e30a76026374836c4242c690bd6207afbfb3a494f1 +d0d1bf3b6bda20fe37de698fe73d6f58cde2a26eedf70ac5754e31e9ff09307d diff --git a/test/data/manifest-checksums/fedora_45-aarch64-generic_ami-all_customizations b/test/data/manifest-checksums/fedora_45-aarch64-generic_ami-all_customizations index bae1d49ad2..0b9c2ceb65 100644 --- a/test/data/manifest-checksums/fedora_45-aarch64-generic_ami-all_customizations +++ b/test/data/manifest-checksums/fedora_45-aarch64-generic_ami-all_customizations @@ -1 +1 @@ -ccdb88a6081b93df5e62854e959aa6e92fedd3ca8b9780b75c0b1e0817dc9538 +3f3275386e285337e48654a2194543d2bb843a7a60ae6f67572033faee28eb95 diff --git a/test/data/manifest-checksums/fedora_45-aarch64-generic_qcow2-all_customizations b/test/data/manifest-checksums/fedora_45-aarch64-generic_qcow2-all_customizations index cf9500cc20..aeaa49b164 100644 --- a/test/data/manifest-checksums/fedora_45-aarch64-generic_qcow2-all_customizations +++ b/test/data/manifest-checksums/fedora_45-aarch64-generic_qcow2-all_customizations @@ -1 +1 @@ -e0e232709ef35890b8c82c99da013030f2bce46e0c8548cdf5782657f0de4ecc +0bed905481d90a934acb083755a2e21e3f1eaed475dfb3d58110f62c06233d60 diff --git a/test/data/manifest-checksums/fedora_45-aarch64-server_qcow2-all_customizations b/test/data/manifest-checksums/fedora_45-aarch64-server_qcow2-all_customizations index 406bb2e9ec..d62a2440f2 100644 --- a/test/data/manifest-checksums/fedora_45-aarch64-server_qcow2-all_customizations +++ b/test/data/manifest-checksums/fedora_45-aarch64-server_qcow2-all_customizations @@ -1 +1 @@ -d4dcb09ab35bc31e737ff0aabb03b8b843164005aba10b1c18737deedc1097e8 +9e5bf4020735b59c475dd3d0436944245639caf74d614bf6a2d1ec39bdd4495e diff --git a/test/data/manifest-checksums/fedora_45-ppc64le-generic_qcow2-all_customizations b/test/data/manifest-checksums/fedora_45-ppc64le-generic_qcow2-all_customizations index 729f812535..e07730c25c 100644 --- a/test/data/manifest-checksums/fedora_45-ppc64le-generic_qcow2-all_customizations +++ b/test/data/manifest-checksums/fedora_45-ppc64le-generic_qcow2-all_customizations @@ -1 +1 @@ -63c69e9a390944fed64f68d3216af5eee363bed96fc86e798eb7cec47a32083c +c3f931ee0af8de7d26fadb8c847685d7fdb9351c6c85a85b6e67bb2c73ca3ceb diff --git a/test/data/manifest-checksums/fedora_45-ppc64le-server_qcow2-all_customizations b/test/data/manifest-checksums/fedora_45-ppc64le-server_qcow2-all_customizations index cb224a1c03..bbcd2c15b1 100644 --- a/test/data/manifest-checksums/fedora_45-ppc64le-server_qcow2-all_customizations +++ b/test/data/manifest-checksums/fedora_45-ppc64le-server_qcow2-all_customizations @@ -1 +1 @@ -41e3944aa8e191f46166bdb1c8270aae4496b6cd04f10100d5f085bb6a8f7c8c +d7a472876e06b6167a0f470fc0da5194a070244558defa2ac8c0cc39f3358560 diff --git a/test/data/manifest-checksums/fedora_45-s390x-generic_qcow2-all_customizations b/test/data/manifest-checksums/fedora_45-s390x-generic_qcow2-all_customizations index ce140cba34..f361ef1ca3 100644 --- a/test/data/manifest-checksums/fedora_45-s390x-generic_qcow2-all_customizations +++ b/test/data/manifest-checksums/fedora_45-s390x-generic_qcow2-all_customizations @@ -1 +1 @@ -134eb5ac9f67e68fa66431ac89422db882f904357b92b84f2db6b6007c62e5ec +497f33b5ab88498583fad817841f9d8972082e9a25c54c1ea9764c9ca16319a5 diff --git a/test/data/manifest-checksums/fedora_45-s390x-server_qcow2-all_customizations b/test/data/manifest-checksums/fedora_45-s390x-server_qcow2-all_customizations index 881c414306..17c1e83040 100644 --- a/test/data/manifest-checksums/fedora_45-s390x-server_qcow2-all_customizations +++ b/test/data/manifest-checksums/fedora_45-s390x-server_qcow2-all_customizations @@ -1 +1 @@ -a51d2b5812d3c12f4fafe73472c93db1392c8aca13a29c50c7b620d2e05f978a +56537ee6e945521b5fa7fcc542554797a948e91c851c6f47d9415e196dcbf8fc diff --git a/test/data/manifest-checksums/fedora_45-x86_64-generic_ami-all_customizations b/test/data/manifest-checksums/fedora_45-x86_64-generic_ami-all_customizations index a5e132db98..51b3c1b00f 100644 --- a/test/data/manifest-checksums/fedora_45-x86_64-generic_ami-all_customizations +++ b/test/data/manifest-checksums/fedora_45-x86_64-generic_ami-all_customizations @@ -1 +1 @@ -1fb2a2deaa199155369ff0842948a6e211a8a0c408b88eb83f04a0d96f78b50d +a9cce2e814cd7af7536d895b0973d69f76ac743060641d663fe47eae5c577c3f diff --git a/test/data/manifest-checksums/fedora_45-x86_64-generic_qcow2-all_customizations b/test/data/manifest-checksums/fedora_45-x86_64-generic_qcow2-all_customizations index e3a4921128..f18f52bcdf 100644 --- a/test/data/manifest-checksums/fedora_45-x86_64-generic_qcow2-all_customizations +++ b/test/data/manifest-checksums/fedora_45-x86_64-generic_qcow2-all_customizations @@ -1 +1 @@ -3af5304c70a89c46e3d7fe5cce0e09d995e85ca846028b4fb78cd7a8e91bd681 +d40ef83d764c152a79e35806d75e10fef5551e63e724bbdbcb0e1e4c2b6a4773 diff --git a/test/data/manifest-checksums/fedora_45-x86_64-server_qcow2-all_customizations b/test/data/manifest-checksums/fedora_45-x86_64-server_qcow2-all_customizations index 8979fb1e50..57ac48b098 100644 --- a/test/data/manifest-checksums/fedora_45-x86_64-server_qcow2-all_customizations +++ b/test/data/manifest-checksums/fedora_45-x86_64-server_qcow2-all_customizations @@ -1 +1 @@ -d352829e2208b45ac0467603f9c89505ff8d669dce09baaade84f50669f4beae +2a9ff62f76027ee3c099bf430209b46b74cfb49431d440baed447adcca3484d3 diff --git a/test/data/manifest-checksums/rhel_10.0-aarch64-ami-all_customizations b/test/data/manifest-checksums/rhel_10.0-aarch64-ami-all_customizations index cfbf56cc28..bd969b80c0 100644 --- a/test/data/manifest-checksums/rhel_10.0-aarch64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_10.0-aarch64-ami-all_customizations @@ -1 +1 @@ -094a1057c35698778f741c21b3a807b75867b14196e515db4f15dd0528426365 +2a11af18ba566c04ebb02bff4fd014c66e5e019e7ec6debd06ad4b50cab7b803 diff --git a/test/data/manifest-checksums/rhel_10.0-x86_64-ami-all_customizations b/test/data/manifest-checksums/rhel_10.0-x86_64-ami-all_customizations index 03fd6a9bfe..6b93c4d97f 100644 --- a/test/data/manifest-checksums/rhel_10.0-x86_64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_10.0-x86_64-ami-all_customizations @@ -1 +1 @@ -2e60fdb49c871072b63f9c195dd54c909cc85f8d16c96d6718b9a4ef981c3792 +5c256596ae8535b3523da6145ff41328d3399fcba601385bf1ea967180e036a6 diff --git a/test/data/manifest-checksums/rhel_10.2-aarch64-ami-all_customizations b/test/data/manifest-checksums/rhel_10.2-aarch64-ami-all_customizations index 3c8e10ebc5..f45e14e110 100644 --- a/test/data/manifest-checksums/rhel_10.2-aarch64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_10.2-aarch64-ami-all_customizations @@ -1 +1 @@ -61239e9fd79002014c0cd1158b65d0bde26983b1f7882bcb1c47719615f9f8b0 +b48c83bcc6b718f059c90d0c08c10d016d9a7a5d9aff31d5b4c90de9c118dd4c diff --git a/test/data/manifest-checksums/rhel_10.2-x86_64-ami-all_customizations b/test/data/manifest-checksums/rhel_10.2-x86_64-ami-all_customizations index 634f2fd5f9..ed2351f2ec 100644 --- a/test/data/manifest-checksums/rhel_10.2-x86_64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_10.2-x86_64-ami-all_customizations @@ -1 +1 @@ -ec9bc247b2ece0f48ce60ef5863466411dabbdb3f667385a7755473c9fafff5b +3f7ad3d4722e2d0c2b3dc689c42267e69b12e8b23f43eebc35523c1fa875d6a1 diff --git a/test/data/manifest-checksums/rhel_10.3-aarch64-ami-all_customizations b/test/data/manifest-checksums/rhel_10.3-aarch64-ami-all_customizations index 5177d39568..ccac1465a6 100644 --- a/test/data/manifest-checksums/rhel_10.3-aarch64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_10.3-aarch64-ami-all_customizations @@ -1 +1 @@ -494528ed351ac8fd819f57997eb81f0dae7d52f69a59888be0805965ec7a6d4c +5babcb910da392628a3207f3959537723df369579d2f252a75fd332a2691943a diff --git a/test/data/manifest-checksums/rhel_10.3-x86_64-ami-all_customizations b/test/data/manifest-checksums/rhel_10.3-x86_64-ami-all_customizations index 0ddd9627f0..9e423f50f8 100644 --- a/test/data/manifest-checksums/rhel_10.3-x86_64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_10.3-x86_64-ami-all_customizations @@ -1 +1 @@ -a26a8ad0fbccd62fab2d929358cd6c351310f18f96c874ec5d7ded3d408b72be +72d91932c10be02ac1a3b9629742211d7a09e2b2dce93f0a02d334bc55d4aae9 diff --git a/test/data/manifest-checksums/rhel_8.10-aarch64-ami-all_customizations b/test/data/manifest-checksums/rhel_8.10-aarch64-ami-all_customizations index 0c3744ab2f..0169143b19 100644 --- a/test/data/manifest-checksums/rhel_8.10-aarch64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_8.10-aarch64-ami-all_customizations @@ -1 +1 @@ -54eae1744bd53e7e1823c6fbd11659392c989c8b13a1f2a58ee55aadd33870a7 +704e47c264f7337d73fb21183bc56503194e66984e95f33a1ba2a5b7580b3f4e diff --git a/test/data/manifest-checksums/rhel_8.10-x86_64-ami-all_customizations b/test/data/manifest-checksums/rhel_8.10-x86_64-ami-all_customizations index 9281e425ee..fa95649928 100644 --- a/test/data/manifest-checksums/rhel_8.10-x86_64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_8.10-x86_64-ami-all_customizations @@ -1 +1 @@ -e45bd09fb3503b838f8315399f9b25bf3be865db9bf1ee7a3b07f708ea14261d +7851664ed3ca114c2ba4cc4d9b22a0a702fc92769c8e734bd701aa317cd007e0 diff --git a/test/data/manifest-checksums/rhel_8.4-aarch64-ami-all_customizations b/test/data/manifest-checksums/rhel_8.4-aarch64-ami-all_customizations index 2ce99eba4c..eb5d2856ba 100644 --- a/test/data/manifest-checksums/rhel_8.4-aarch64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_8.4-aarch64-ami-all_customizations @@ -1 +1 @@ -db93f46d4800eb45c89fb7085cc11cd417bda1b24e8d5e76eefd2ff6828100c6 +3e3e1f52565c06b456ad7c52f8d723e7336cceef9dc891df21589e5ec63246be diff --git a/test/data/manifest-checksums/rhel_8.4-x86_64-ami-all_customizations b/test/data/manifest-checksums/rhel_8.4-x86_64-ami-all_customizations index 666092f235..bac61adc87 100644 --- a/test/data/manifest-checksums/rhel_8.4-x86_64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_8.4-x86_64-ami-all_customizations @@ -1 +1 @@ -4f56bf84c931380f6f171d48b7d2974af9759c1ec14f66e1fcdce5db553a5cbb +a3811f2ae875ef7a9d64cac616c1f826ef2335549637baa2d3df6a651576b1f3 diff --git a/test/data/manifest-checksums/rhel_8.6-aarch64-ami-all_customizations b/test/data/manifest-checksums/rhel_8.6-aarch64-ami-all_customizations index b1cdcbddee..cda73bb2a1 100644 --- a/test/data/manifest-checksums/rhel_8.6-aarch64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_8.6-aarch64-ami-all_customizations @@ -1 +1 @@ -581f142c240cec50eb5a3e67a35f0491412323f6eba070d37253057c377923a4 +cd91e258e307fc5abc177d4c1d0a26841368fcf9be2ff5ae3b6bd22e51a548d4 diff --git a/test/data/manifest-checksums/rhel_8.6-x86_64-ami-all_customizations b/test/data/manifest-checksums/rhel_8.6-x86_64-ami-all_customizations index 42a62dccd1..473e39e553 100644 --- a/test/data/manifest-checksums/rhel_8.6-x86_64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_8.6-x86_64-ami-all_customizations @@ -1 +1 @@ -eafbd32405b53a0b1712c8069c7302347a1243d541861b8bee0c3c352705377e +132599c62d0eee9b964bfc28ffd69dae6c0f57730d334df1dee62c1cb1242a16 diff --git a/test/data/manifest-checksums/rhel_8.8-aarch64-ami-all_customizations b/test/data/manifest-checksums/rhel_8.8-aarch64-ami-all_customizations index 6cc45fda94..c5b0e083cd 100644 --- a/test/data/manifest-checksums/rhel_8.8-aarch64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_8.8-aarch64-ami-all_customizations @@ -1 +1 @@ -4e2f6a5e3dd66eb80e29df3c5770db3ddcb67e0706f2238c62d23f937b973f36 +7d46f3b9ca44b93b249a42ecd69a3aa068e9cba5c202601ec9a1e17ceae418fa diff --git a/test/data/manifest-checksums/rhel_8.8-x86_64-ami-all_customizations b/test/data/manifest-checksums/rhel_8.8-x86_64-ami-all_customizations index 7943e82d28..511e02d1c1 100644 --- a/test/data/manifest-checksums/rhel_8.8-x86_64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_8.8-x86_64-ami-all_customizations @@ -1 +1 @@ -819a217e48e458ac8d1acfe555b584ed8e45dae7af0a7c35c8bed75684c9fa64 +5151a7634e37b536d7e54e4addf812b132bafa40a12bb22ed7a22ddbb76e2795 diff --git a/test/data/manifest-checksums/rhel_9.0-aarch64-ami-all_customizations b/test/data/manifest-checksums/rhel_9.0-aarch64-ami-all_customizations index 787d062527..03a17216f2 100644 --- a/test/data/manifest-checksums/rhel_9.0-aarch64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_9.0-aarch64-ami-all_customizations @@ -1 +1 @@ -19830de394e2c880eae0719d204241372670bec37219457a2d363d417f16651a +4d4b7bb3768bec5ec06a809d66420eabe2b5aa6d8946611ef14788459525c17e diff --git a/test/data/manifest-checksums/rhel_9.0-x86_64-ami-all_customizations b/test/data/manifest-checksums/rhel_9.0-x86_64-ami-all_customizations index ce803a398a..cb503a14ef 100644 --- a/test/data/manifest-checksums/rhel_9.0-x86_64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_9.0-x86_64-ami-all_customizations @@ -1 +1 @@ -f5e41793df34d723566a21739648c1a957ade47b9d4b8ad3a285fa5f1d843def +8f22f7b6576d234f6441c7f355c24985a373a0a2cc656db741ab60f12d648dea diff --git a/test/data/manifest-checksums/rhel_9.2-aarch64-ami-all_customizations b/test/data/manifest-checksums/rhel_9.2-aarch64-ami-all_customizations index 27a967c406..a55a612d8a 100644 --- a/test/data/manifest-checksums/rhel_9.2-aarch64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_9.2-aarch64-ami-all_customizations @@ -1 +1 @@ -956177e7acc3e6b019e2cb7c6bdfa4a7edbe662d7bd4a79825738f5de01de8f7 +d8f47fabc1af9ce75d4a1ca2e47ba6ff995011ffdee98759521a8ca24e16ecb3 diff --git a/test/data/manifest-checksums/rhel_9.2-x86_64-ami-all_customizations b/test/data/manifest-checksums/rhel_9.2-x86_64-ami-all_customizations index 45c5efbaa1..ab0006023f 100644 --- a/test/data/manifest-checksums/rhel_9.2-x86_64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_9.2-x86_64-ami-all_customizations @@ -1 +1 @@ -ff0e3fd950eec1c219ffe5dcaac891b1482ef93e1595a5a7b477a6c558a73a1e +4a83285315132852cdb846061882c56c3c64d4c7595775b2b90acaf18c8781f7 diff --git a/test/data/manifest-checksums/rhel_9.4-aarch64-ami-all_customizations b/test/data/manifest-checksums/rhel_9.4-aarch64-ami-all_customizations index bf2ca5d33b..311f9f1c2d 100644 --- a/test/data/manifest-checksums/rhel_9.4-aarch64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_9.4-aarch64-ami-all_customizations @@ -1 +1 @@ -e5d37c620e3a1341e9f40fd332a381f2cf0aa0793e0f7e4e70a49446760a4d7a +063669ea0f4c885ac54a609666b8da3d040858d770e685a693653e04ace5211b diff --git a/test/data/manifest-checksums/rhel_9.4-x86_64-ami-all_customizations b/test/data/manifest-checksums/rhel_9.4-x86_64-ami-all_customizations index 72484bdf2d..f3cd86af79 100644 --- a/test/data/manifest-checksums/rhel_9.4-x86_64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_9.4-x86_64-ami-all_customizations @@ -1 +1 @@ -bd07a91450274f98726c32088a0f7519969c0a1e29f1fc34babd2d89be6187de +c7393b4cbc1e4547d2fa1d6b65d4419e521e77fd4d409a215b0c17cf11a4c22a diff --git a/test/data/manifest-checksums/rhel_9.6-aarch64-ami-all_customizations b/test/data/manifest-checksums/rhel_9.6-aarch64-ami-all_customizations index 3be2f05653..84858b4bea 100644 --- a/test/data/manifest-checksums/rhel_9.6-aarch64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_9.6-aarch64-ami-all_customizations @@ -1 +1 @@ -b93faf561361035a09a49f03bb7945910393893188aa9f47b3deb859d5ac69c7 +9107f9ede9b4495a49978309f4270fadf3acadc44559fbcc163dea8c36c97c77 diff --git a/test/data/manifest-checksums/rhel_9.6-x86_64-ami-all_customizations b/test/data/manifest-checksums/rhel_9.6-x86_64-ami-all_customizations index ad9fe52cbc..9b3b800402 100644 --- a/test/data/manifest-checksums/rhel_9.6-x86_64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_9.6-x86_64-ami-all_customizations @@ -1 +1 @@ -128293cd3a5e51b8b6538dd34938c4861bde5da9f1e92112b296ab82ea9d335c +3e6a9943b508e8aa62d7e9126846d00f35e25bf45da1941dd92b6d2b2c92e804 diff --git a/test/data/manifest-checksums/rhel_9.8-aarch64-ami-all_customizations b/test/data/manifest-checksums/rhel_9.8-aarch64-ami-all_customizations index 8f66cf60c0..08c3f737c9 100644 --- a/test/data/manifest-checksums/rhel_9.8-aarch64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_9.8-aarch64-ami-all_customizations @@ -1 +1 @@ -af1225e3f6d705ae6b2845df86ebdb6ce5810fb5a605e14a2b1450d6214b1993 +8c7378b514921f7adb60f365b5a1823fce736d5d1eb9b865740b5cd0cb1e1780 diff --git a/test/data/manifest-checksums/rhel_9.8-x86_64-ami-all_customizations b/test/data/manifest-checksums/rhel_9.8-x86_64-ami-all_customizations index d434922984..50bccbf0cc 100644 --- a/test/data/manifest-checksums/rhel_9.8-x86_64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_9.8-x86_64-ami-all_customizations @@ -1 +1 @@ -e5cc300882691370d7f219cc2beb72b3bfe437e8f66f38737154d0015af93f8f +7246c93668e9fe71b565821faf37cd118f16e4491b3b3cc479888f6b895ee301 diff --git a/test/data/manifest-checksums/rhel_9.9-aarch64-ami-all_customizations b/test/data/manifest-checksums/rhel_9.9-aarch64-ami-all_customizations index b144396f1f..b5e1d9481e 100644 --- a/test/data/manifest-checksums/rhel_9.9-aarch64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_9.9-aarch64-ami-all_customizations @@ -1 +1 @@ -9ca2647a3a9ee7882635eae89a3bb508a0902663596186d0a5f96eb95c500903 +45b4eacae70c30c4cdd250e7dcb7891c3575cb230af0527374fd42f51591fd96 diff --git a/test/data/manifest-checksums/rhel_9.9-x86_64-ami-all_customizations b/test/data/manifest-checksums/rhel_9.9-x86_64-ami-all_customizations index 4d04bed473..2680af1dca 100644 --- a/test/data/manifest-checksums/rhel_9.9-x86_64-ami-all_customizations +++ b/test/data/manifest-checksums/rhel_9.9-x86_64-ami-all_customizations @@ -1 +1 @@ -d4f0708626680757e093452a0d1f29a84030be8b7b09d8d0f2d772eb688888b3 +9568d2dfbe0033d66f2ec2bda1ac790d03d6bb769bffa928691b31e7fab2e825