From e2bd3506e2f99897ee24011f605faf60b87a4298 Mon Sep 17 00:00:00 2001 From: Antonio Murdaca Date: Thu, 24 Feb 2022 12:29:33 +0100 Subject: [PATCH] distro/rhel86: add fido dracut module and enable customizing onboarding This patch also introduces customizations to fully enable onboarding options for FDO. Co-Authored-By: Christian Kellner --- internal/blueprint/customizations.go | 17 +++++++++ internal/distro/rhel86/distro.go | 48 ++++++++++++++++++++++--- internal/distro/rhel86/package_sets.go | 2 ++ internal/distro/rhel86/pipelines.go | 20 +++++++---- internal/distro/rhel86/stage_options.go | 17 +++++++-- 5 files changed, 92 insertions(+), 12 deletions(-) diff --git a/internal/blueprint/customizations.go b/internal/blueprint/customizations.go index 1d4b443c9..d7814a35d 100644 --- a/internal/blueprint/customizations.go +++ b/internal/blueprint/customizations.go @@ -20,6 +20,16 @@ type Customizations struct { Services *ServicesCustomization `json:"services,omitempty" toml:"services,omitempty"` Filesystem []FilesystemCustomization `json:"filesystem,omitempty" toml:"filesystem,omitempty"` InstallationDevice string `json:"installation_device,omitempty" toml:"installation_device,omitempty"` + FDO *FDOCustomization `json:"fdo,omitempty" toml:"fdo,omitempty"` +} + +type FDOCustomization struct { + ManufacturingServerURL string `json:"manufacturing_server_url,omitempty" toml:"manufacturing_server_url,omitempty"` + DiunPubKeyInsecure string `json:"diun_pub_key_insecure,omitempty" toml:"diun_pub_key_insecure,omitempty"` + // This is the output of: + // echo "sha256:$(openssl x509 -fingerprint -sha256 -noout -in diun_cert.pem | cut -d"=" -f2 | sed 's/://g')" + DiunPubKeyHash string `json:"diun_pub_key_hash,omitempty" toml:"diun_pub_key_hash,omitempty"` + DiunPubKeyRootCerts string `json:"diun_pub_key_root_certs,omitempty" toml:"diun_pub_key_root_certs,omitempty"` } type KernelCustomization struct { @@ -337,3 +347,10 @@ func (c *Customizations) GetInstallationDevice() string { } return c.InstallationDevice } + +func (c *Customizations) GetFDO() *FDOCustomization { + if c == nil { + return nil + } + return c.FDO +} diff --git a/internal/distro/rhel86/distro.go b/internal/distro/rhel86/distro.go index 4ca80a08d..45be74d4d 100644 --- a/internal/distro/rhel86/distro.go +++ b/internal/distro/rhel86/distro.go @@ -449,20 +449,30 @@ func (t *imageType) Manifest(customizations *blueprint.Customizations, allPackageSpecs = append(allPackageSpecs, specs...) } + // handle OSTree commit inputs var commits []ostreeCommit if options.OSTree.Parent != "" && options.OSTree.URL != "" { commits = []ostreeCommit{{Checksum: options.OSTree.Parent, URL: options.OSTree.URL}} } + + // handle inline sources + inlineData := []string{} + + // FDO root certs, if any, are transmitted via an inline source + if fdo := customizations.GetFDO(); fdo != nil && fdo.DiunPubKeyRootCerts != "" { + inlineData = append(inlineData, fdo.DiunPubKeyRootCerts) + } + return json.Marshal( osbuild.Manifest{ Version: "2", Pipelines: pipelines, - Sources: t.sources(allPackageSpecs, commits), + Sources: t.sources(allPackageSpecs, commits, inlineData), }, ) } -func (t *imageType) sources(packages []rpmmd.PackageSpec, ostreeCommits []ostreeCommit) osbuild.Sources { +func (t *imageType) sources(packages []rpmmd.PackageSpec, ostreeCommits []ostreeCommit, inlineData []string) osbuild.Sources { sources := osbuild.Sources{} curl := &osbuild.CurlSource{ Items: make(map[string]osbuild.CurlSourceItem), @@ -492,6 +502,16 @@ func (t *imageType) sources(packages []rpmmd.PackageSpec, ostreeCommits []ostree if len(ostree.Items) > 0 { sources["org.osbuild.ostree"] = ostree } + + if len(inlineData) > 0 { + ils := osbuild.NewInlineSource() + for _, data := range inlineData { + ils.AddItem(data) + } + + sources["org.osbuild.inline"] = ils + } + return sources } @@ -522,12 +542,31 @@ func (t *imageType) checkOptions(customizations *blueprint.Customizations, optio } if t.name == "edge-simplified-installer" { - if err := customizations.CheckAllowed("InstallationDevice"); err != nil { + if err := customizations.CheckAllowed("InstallationDevice", "FDO"); err != nil { return fmt.Errorf("boot ISO image type %q contains unsupported blueprint customizations: %v", t.name, err) } if customizations.GetInstallationDevice() == "" { return fmt.Errorf("boot ISO image type %q requires specifying an installation device to install to", t.name) } + if customizations.GetFDO() == nil { + return fmt.Errorf("boot ISO image type %q requires specifying FDO configuration to install to", t.name) + } + if customizations.GetFDO().ManufacturingServerURL == "" { + return fmt.Errorf("boot ISO image type %q requires specifying FDO.ManufacturingServerURL configuration to install to", t.name) + } + var diunSet int + if customizations.GetFDO().DiunPubKeyHash != "" { + diunSet++ + } + if customizations.GetFDO().DiunPubKeyInsecure != "" { + diunSet++ + } + if customizations.GetFDO().DiunPubKeyRootCerts != "" { + diunSet++ + } + if diunSet != 1 { + return fmt.Errorf("boot ISO image type %q requires specifying one of [FDO.DiunPubKeyHash,FDO.DiunPubKeyInsecure,FDO.DiunPubKeyRootCerts] configuration to install to", t.name) + } } else if customizations != nil { return fmt.Errorf("boot ISO image type %q does not support blueprint customizations", t.name) } @@ -620,7 +659,8 @@ func newDistro(distroName string) distro.Distro { // Shared Services edgeServices := []string{ - "NetworkManager.service", "firewalld.service", "sshd.service", + // TODO(runcom): move fdo-client-linuxapp.service to presets? + "NetworkManager.service", "firewalld.service", "sshd.service", "fdo-client-linuxapp.service", } // Image Definitions diff --git a/internal/distro/rhel86/package_sets.go b/internal/distro/rhel86/package_sets.go index 3ecd5fd57..85b0dbde3 100644 --- a/internal/distro/rhel86/package_sets.go +++ b/internal/distro/rhel86/package_sets.go @@ -451,6 +451,7 @@ func edgeCommitPackageSet(t *imageType) rpmmd.PackageSet { "container-selinux", "skopeo", "criu", "slirp4netns", "fuse-overlayfs", "clevis", "clevis-dracut", "clevis-luks", "greenboot", "greenboot-default-health-checks", + "fdo-client", "fdo-owner-cli", }, Exclude: []string{"rng-tools"}, } @@ -744,6 +745,7 @@ func edgeSimplifiedInstallerPackageSet(t *imageType) rpmmd.PackageSet { "cloud-utils-growpart", "coreos-installer", "coreos-installer-dracut", + "fdo-init", "coreutils", "device-mapper-multipath", "dnsmasq", diff --git a/internal/distro/rhel86/pipelines.go b/internal/distro/rhel86/pipelines.go index dc0754302..bab9a57d9 100644 --- a/internal/distro/rhel86/pipelines.go +++ b/internal/distro/rhel86/pipelines.go @@ -670,9 +670,9 @@ func edgeSimplifiedInstallerPipelines(t *imageType, customizations *blueprint.Cu // create boot ISO with raw image d := t.arch.distro archName := t.arch.name - installerTreePipeline := simplifiedInstallerTreePipeline(repos, installerPackages, kernelVer, archName, d.product, d.osVersion, "edge") + installerTreePipeline := simplifiedInstallerTreePipeline(repos, installerPackages, kernelVer, archName, d.product, d.osVersion, "edge", customizations.GetFDO()) isolabel := fmt.Sprintf(d.isolabelTmpl, archName) - efibootTreePipeline := simplifiedInstallerEFIBootTreePipeline(installDevice, kernelVer, archName, d.vendor, d.product, d.osVersion, isolabel) + efibootTreePipeline := simplifiedInstallerEFIBootTreePipeline(installDevice, kernelVer, archName, d.vendor, d.product, d.osVersion, isolabel, customizations.GetFDO()) bootISOTreePipeline := simplifiedInstallerBootISOTreePipeline(imgPipelineName, kernelVer) pipelines = append(pipelines, *installerTreePipeline, *efibootTreePipeline, *bootISOTreePipeline) @@ -774,22 +774,30 @@ func simplifiedInstallerBootISOTreePipeline(archivePipelineName, kver string) *o return p } -func simplifiedInstallerEFIBootTreePipeline(installDevice, kernelVer, arch, vendor, product, osVersion, isolabel string) *osbuild.Pipeline { +func simplifiedInstallerEFIBootTreePipeline(installDevice, kernelVer, arch, vendor, product, osVersion, isolabel string, fdo *blueprint.FDOCustomization) *osbuild.Pipeline { p := new(osbuild.Pipeline) p.Name = "efiboot-tree" p.Build = "name:build" - p.AddStage(osbuild.NewGrubISOStage(grubISOStageOptions(installDevice, kernelVer, arch, vendor, product, osVersion, isolabel))) + p.AddStage(osbuild.NewGrubISOStage(grubISOStageOptions(installDevice, kernelVer, arch, vendor, product, osVersion, isolabel, fdo))) return p } -func simplifiedInstallerTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, kernelVer, arch, product, osVersion, variant string) *osbuild.Pipeline { +func simplifiedInstallerTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, kernelVer, arch, product, osVersion, variant string, fdo *blueprint.FDOCustomization) *osbuild.Pipeline { p := new(osbuild.Pipeline) p.Name = "coi-tree" p.Build = "name:build" p.AddStage(osbuild.NewRPMStage(rpmStageOptions(repos), osbuild.NewRpmStageSourceFilesInputs(packages))) p.AddStage(osbuild.NewBuildstampStage(buildStampStageOptions(arch, product, osVersion, variant))) p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: "en_US.UTF-8"})) - p.AddStage(osbuild.NewDracutStage(dracutStageOptions(kernelVer, arch, []string{"coreos-installer"}))) + dracutStageOptions := dracutStageOptions(kernelVer, arch, []string{ + "coreos-installer", + "fdo", + }) + if fdo.DiunPubKeyRootCerts != "" { + p.AddStage(osbuild.NewFDOStageForRootCerts(fdo.DiunPubKeyRootCerts)) + dracutStageOptions.Install = []string{"/fdo_diun_pub_key_root_certs.pem"} + } + p.AddStage(osbuild.NewDracutStage(dracutStageOptions)) return p } diff --git a/internal/distro/rhel86/stage_options.go b/internal/distro/rhel86/stage_options.go index 1bddbcacb..48f55f9f2 100644 --- a/internal/distro/rhel86/stage_options.go +++ b/internal/distro/rhel86/stage_options.go @@ -303,7 +303,7 @@ func bootISOMonoStageOptions(kernelVer, arch, vendor, product, osVersion, isolab } } -func grubISOStageOptions(installDevice, kernelVer, arch, vendor, product, osVersion, isolabel string) *osbuild.GrubISOStageOptions { +func grubISOStageOptions(installDevice, kernelVer, arch, vendor, product, osVersion, isolabel string, fdo *blueprint.FDOCustomization) *osbuild.GrubISOStageOptions { var architectures []string if arch == "x86_64" { @@ -314,7 +314,7 @@ func grubISOStageOptions(installDevice, kernelVer, arch, vendor, product, osVers panic("unsupported architecture") } - return &osbuild.GrubISOStageOptions{ + grubISOStageOptions := &osbuild.GrubISOStageOptions{ Product: osbuild.Product{ Name: product, Version: osVersion, @@ -331,6 +331,19 @@ func grubISOStageOptions(installDevice, kernelVer, arch, vendor, product, osVers Architectures: architectures, Vendor: vendor, } + + grubISOStageOptions.Kernel.Opts = append(grubISOStageOptions.Kernel.Opts, "fdo.manufacturing_server_url="+fdo.ManufacturingServerURL) + if fdo.DiunPubKeyInsecure != "" { + grubISOStageOptions.Kernel.Opts = append(grubISOStageOptions.Kernel.Opts, "fdo.diun_pub_key_insecure="+fdo.DiunPubKeyInsecure) + } + if fdo.DiunPubKeyHash != "" { + grubISOStageOptions.Kernel.Opts = append(grubISOStageOptions.Kernel.Opts, "fdo.diun_pub_key_hash="+fdo.DiunPubKeyHash) + } + if fdo.DiunPubKeyRootCerts != "" { + grubISOStageOptions.Kernel.Opts = append(grubISOStageOptions.Kernel.Opts, "fdo.diun_pub_key_root_certs=/fdo_diun_root_certs.pem") + } + + return grubISOStageOptions } func discinfoStageOptions(arch string) *osbuild.DiscinfoStageOptions {