From deccaf9548fa44bd4cdfaa364a5c49bdfa413557 Mon Sep 17 00:00:00 2001 From: Achilleas Koutsou Date: Tue, 10 Jun 2025 15:43:18 +0200 Subject: [PATCH] go.mod: update osbuild/images to v0.151.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tag v0.149.0 Tagger: imagebuilder-bot Changes with 0.149.0 ---------------- * Update dependencies 2025-05-25 (osbuild/images#1560) * Author: SchutzBot, Reviewers: Simon de Vlieger, Tomáš Hozza * Update osbuild dependency commit ID to latest (osbuild/images#1522) * Author: SchutzBot, Reviewers: Simon de Vlieger, Tomáš Hozza * Update snapshots to 20250515 (osbuild/images#1524) * Author: SchutzBot, Reviewers: Simon de Vlieger, Tomáš Hozza * `vagrant-libvirt` implementation (HMS-6116) (osbuild/images#1548) * Author: Simon de Vlieger, Reviewers: Achilleas Koutsou, Tomáš Hozza * fedora: tweaks after all imageTypes are YAML (osbuild/images#1518) * Author: Michael Vogt, Reviewers: Simon de Vlieger, Tomáš Hozza * gha: do not break gobump output (osbuild/images#1561) * Author: Lukáš Zapletal, Reviewers: Simon de Vlieger, Tomáš Hozza * repositories: AlmaLinux 10 (osbuild/images#1567) * Author: Simon de Vlieger, Reviewers: Achilleas Koutsou, Lukáš Zapletal, Neal Gompa (ニール・ゴンパ) * vagrant: image config for default vagrant user (HMS-6116) (osbuild/images#1565) * Author: Simon de Vlieger, Reviewers: Achilleas Koutsou, Michael Vogt — Somewhere on the Internet, 2025-05-27 --- tag v0.150.0 Tagger: imagebuilder-bot Changes with 0.150.0 ---------------- * Replace hardcoded kickstart %post scripts with new stage options and bootc switch with custom kickstart content (HMS-6051) (osbuild/images#1527) * Author: Achilleas Koutsou, Reviewers: Simon de Vlieger, Tomáš Hozza * test: install yamllint for tests (osbuild/images#1572) * Author: Achilleas Koutsou, Reviewers: Lukáš Zapletal, Simon de Vlieger, Tomáš Hozza — Somewhere on the Internet, 2025-06-02 --- tag v0.151.0 Tagger: imagebuilder-bot Changes with 0.151.0 ---------------- * Introduce new Azure CVM image type (HMS-5636) (osbuild/images#1318) * Author: Achilleas Koutsou, Reviewers: Nobody * Many: support using string with unit for byte-sized partitioning fields in YAML distro definitions (osbuild/images#1579) * Author: Tomáš Hozza, Reviewers: Achilleas Koutsou, Brian C. Lane * Update osbuild dependency commit ID to latest (osbuild/images#1587) * Author: SchutzBot, Reviewers: Achilleas Koutsou, Tomáš Hozza * Update snapshots to 20250601 (osbuild/images#1573) * Author: SchutzBot, Reviewers: Achilleas Koutsou, Lukáš Zapletal * bootc: Make installed rootfs configurable (osbuild/images#1555) * Author: Mbarak Bujra, Reviewers: Michael Vogt, Tomáš Hozza * distro: create new ImageConfig.DNFConfig (osbuild/images#1583) * Author: Michael Vogt, Reviewers: Simon de Vlieger, Tomáš Hozza * distro: make "fedora" a "generic" distro (osbuild/images#1563) * Author: Michael Vogt, Reviewers: Nobody * image: If using a separate build container, copy bootc customization to it (osbuild/images#1571) * Author: Alexander Larsson, Reviewers: Achilleas Koutsou, Tomáš Hozza * manifest/ostree: explicitly include shadow-utils (osbuild/images#1585) * Author: Simon de Vlieger, Reviewers: Achilleas Koutsou, Michael Vogt * osbuild/tar: explicit compression (HMS-8573, HMS-6116) (osbuild/images#1581) * Author: Simon de Vlieger, Reviewers: Achilleas Koutsou, Tomáš Hozza * tests: bump fedora versions to 41 (osbuild/images#1438) * Author: Lukáš Zapletal, Reviewers: Brian C. Lane, Michael Vogt — Somewhere on the Internet, 2025-06-09 --- --- go.mod | 8 +- go.sum | 16 +- internal/store/json_test.go | 3 +- .../image/v5/signature/fulcio_cert.go | 28 +- .../containers/image/v5/signature/pki_cert.go | 74 +++ .../v5/signature/policy_config_sigstore.go | 192 ++++++- .../v5/signature/policy_eval_sigstore.go | 99 +++- .../image/v5/signature/policy_types.go | 37 +- .../image/v5/tarball/tarball_src.go | 61 ++- .../containers/image/v5/version/version.go | 2 +- vendor/github.com/containers/storage/Makefile | 2 +- vendor/github.com/containers/storage/VERSION | 2 +- .../storage/pkg/idmap/idmapped_utils.go | 5 +- .../osbuild/images/data/dependencies/osbuild | 2 +- .../data/repositories/almalinux-10.0.json | 66 +++ .../data/repositories/almalinux-10.json | 66 +++ .../osbuild/images/internal/common/helpers.go | 14 + .../osbuild/images/pkg/datasizes/parse.go | 26 +- .../osbuild/images/pkg/disk/btrfs.go | 21 + .../osbuild/images/pkg/disk/disk.go | 18 + .../github.com/osbuild/images/pkg/disk/lvm.go | 5 + .../osbuild/images/pkg/disk/partition.go | 6 + .../images/pkg/disk/partition_table.go | 24 +- .../images/pkg/distro/defs/distros.yaml | 61 +++ .../images/pkg/distro/defs/fedora/distro.yaml | 129 ++++- .../osbuild/images/pkg/distro/defs/loader.go | 376 +++++++++---- .../pkg/distro/defs/rhel-10/distro.yaml | 496 ++++++++++-------- .../images/pkg/distro/defs/rhel-7/distro.yaml | 8 +- .../images/pkg/distro/defs/rhel-8/distro.yaml | 24 +- .../images/pkg/distro/defs/rhel-9/distro.yaml | 40 +- .../images/pkg/distro/fedora/distro.go | 290 ---------- .../images/pkg/distro/fedora/package_sets.go | 80 --- .../images/pkg/distro/fedora/version.go | 15 - .../images/pkg/distro/generic/distro.go | 238 +++++++++ .../images/pkg/distro/generic/imagedefs.go | 48 ++ .../pkg/distro/{fedora => generic}/images.go | 114 ++-- .../distro/{fedora => generic}/imagetype.go | 157 +++--- .../osbuild/images/pkg/distro/id.go | 6 +- .../osbuild/images/pkg/distro/image_config.go | 33 +- .../images/pkg/distro/installer_config.go | 3 + .../osbuild/images/pkg/distro/rhel/images.go | 11 + .../images/pkg/distro/rhel/rhel10/azure.go | 21 + .../images/pkg/distro/rhel/rhel10/distro.go | 12 + .../pkg/distro/rhel/rhel10/package_sets.go | 4 +- .../distro/rhel/rhel10/partition_tables.go | 2 +- .../pkg/distro/rhel/rhel7/package_sets.go | 2 +- .../pkg/distro/rhel/rhel7/partition_tables.go | 2 +- .../images/pkg/distro/rhel/rhel8/gce.go | 12 +- .../pkg/distro/rhel/rhel8/package_sets.go | 2 +- .../pkg/distro/rhel/rhel8/partition_tables.go | 2 +- .../images/pkg/distro/rhel/rhel8/sap.go | 5 +- .../images/pkg/distro/rhel/rhel9/azure.go | 177 +++++-- .../images/pkg/distro/rhel/rhel9/distro.go | 16 + .../images/pkg/distro/rhel/rhel9/gce.go | 12 +- .../images/pkg/distro/rhel/rhel9/options.go | 10 + .../pkg/distro/rhel/rhel9/package_sets.go | 2 +- .../pkg/distro/rhel/rhel9/partition_tables.go | 2 +- .../images/pkg/distro/rhel/rhel9/sap.go | 4 +- .../images/pkg/distrofactory/distrofactory.go | 4 +- .../images/pkg/distroidparser/idparser.go | 2 - .../pkg/image/anaconda_container_installer.go | 6 + .../osbuild/images/pkg/image/bootc_disk.go | 42 ++ .../osbuild/images/pkg/image/disk.go | 11 + .../manifest/anaconda_installer_iso_tree.go | 119 +++-- .../osbuild/images/pkg/manifest/build.go | 43 ++ .../osbuild/images/pkg/manifest/os.go | 260 ++++++--- .../images/pkg/manifest/ostree_deployment.go | 5 + .../osbuild/images/pkg/manifest/tar.go | 32 +- .../osbuild/images/pkg/manifest/vagrant.go | 58 ++ .../images/pkg/osbuild/kickstart_stage.go | 9 + .../osbuild/images/pkg/osbuild/rpm_stage.go | 9 + .../osbuild/images/pkg/osbuild/tar_stage.go | 34 ++ .../images/pkg/osbuild/vagrant_stage.go | 54 ++ .../osbuild/images/pkg/platform/aarch64.go | 8 + .../osbuild/images/pkg/platform/platform.go | 49 ++ .../osbuild/images/pkg/platform/ppc64le.go | 4 + .../osbuild/images/pkg/platform/riscv64.go | 4 + .../osbuild/images/pkg/platform/s390x.go | 4 + .../osbuild/images/pkg/platform/x86_64.go | 36 +- .../osbuild/images/pkg/platform/yaml.go | 6 + .../osbuild/images/pkg/runner/yaml.go | 17 + vendor/modules.txt | 10 +- 82 files changed, 2844 insertions(+), 1175 deletions(-) create mode 100644 vendor/github.com/containers/image/v5/signature/pki_cert.go create mode 100644 vendor/github.com/osbuild/images/data/repositories/almalinux-10.0.json create mode 100644 vendor/github.com/osbuild/images/data/repositories/almalinux-10.json create mode 100644 vendor/github.com/osbuild/images/pkg/distro/defs/distros.yaml delete mode 100644 vendor/github.com/osbuild/images/pkg/distro/fedora/distro.go delete mode 100644 vendor/github.com/osbuild/images/pkg/distro/fedora/package_sets.go delete mode 100644 vendor/github.com/osbuild/images/pkg/distro/fedora/version.go create mode 100644 vendor/github.com/osbuild/images/pkg/distro/generic/distro.go create mode 100644 vendor/github.com/osbuild/images/pkg/distro/generic/imagedefs.go rename vendor/github.com/osbuild/images/pkg/distro/{fedora => generic}/images.go (91%) rename vendor/github.com/osbuild/images/pkg/distro/{fedora => generic}/imagetype.go (80%) create mode 100644 vendor/github.com/osbuild/images/pkg/manifest/vagrant.go create mode 100644 vendor/github.com/osbuild/images/pkg/osbuild/vagrant_stage.go create mode 100644 vendor/github.com/osbuild/images/pkg/runner/yaml.go diff --git a/go.mod b/go.mod index 917007980..731af51a3 100644 --- a/go.mod +++ b/go.mod @@ -46,7 +46,7 @@ require ( github.com/openshift-online/ocm-sdk-go v0.1.438 github.com/oracle/oci-go-sdk/v54 v54.0.0 github.com/osbuild/blueprint v1.6.0 - github.com/osbuild/images v0.148.0 + github.com/osbuild/images v0.151.0 github.com/osbuild/osbuild-composer/pkg/splunk_logger v0.0.0-20240814102216-0239db53236d github.com/osbuild/pulp-client v0.1.0 github.com/prometheus/client_golang v1.20.5 @@ -114,11 +114,11 @@ require ( github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect github.com/containerd/typeurl/v2 v2.2.3 // indirect - github.com/containers/common v0.62.0 // indirect - github.com/containers/image/v5 v5.34.0 // indirect + github.com/containers/common v0.62.3 // indirect + github.com/containers/image/v5 v5.34.3 // indirect github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect github.com/containers/ocicrypt v1.2.1 // indirect - github.com/containers/storage v1.57.1 // indirect + github.com/containers/storage v1.57.2 // indirect github.com/coreos/go-semver v0.3.1 // indirect github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f // indirect github.com/cyphar/filepath-securejoin v0.3.6 // indirect diff --git a/go.sum b/go.sum index 2e97986b6..69cf93152 100644 --- a/go.sum +++ b/go.sum @@ -180,16 +180,16 @@ github.com/containerd/stargz-snapshotter/estargz v0.16.3 h1:7evrXtoh1mSbGj/pfRcc github.com/containerd/stargz-snapshotter/estargz v0.16.3/go.mod h1:uyr4BfYfOj3G9WBVE8cOlQmXAbPN9VEQpBBeJIuOipU= github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40= github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk= -github.com/containers/common v0.62.0 h1:Sl9WE5h7Y/F3bejrMAA4teP1EcY9ygqJmW4iwSloZ10= -github.com/containers/common v0.62.0/go.mod h1:Yec+z8mrSq4rydHofrnDCBqAcNA/BGrSg1kfFUL6F6s= -github.com/containers/image/v5 v5.34.0 h1:HPqQaDUsox/3mC1pbOyLAIQEp0JhQqiUZ+6JiFIZLDI= -github.com/containers/image/v5 v5.34.0/go.mod h1:/WnvUSEfdqC/ahMRd4YJDBLrpYWkGl018rB77iB3FDo= +github.com/containers/common v0.62.3 h1:aOGryqXfW6aKBbHbqOveH7zB+ihavUN03X/2pUSvWFI= +github.com/containers/common v0.62.3/go.mod h1:3R8kDox2prC9uj/a2hmXj/YjZz5sBEUNrcDiw51S0Lo= +github.com/containers/image/v5 v5.34.3 h1:/cMgfyA4Y7ILH7nzWP/kqpkE5Df35Ek4bp5ZPvJOVmI= +github.com/containers/image/v5 v5.34.3/go.mod h1:MG++slvQSZVq5ejAcLdu4APGsKGMb0YHHnAo7X28fdE= github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA= github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY= github.com/containers/ocicrypt v1.2.1 h1:0qIOTT9DoYwcKmxSt8QJt+VzMY18onl9jUXsxpVhSmM= github.com/containers/ocicrypt v1.2.1/go.mod h1:aD0AAqfMp0MtwqWgHM1bUwe1anx0VazI108CRrSKINQ= -github.com/containers/storage v1.57.1 h1:hKPoFsuBcB3qTzBxa4IFpZMRzUuL5Xhv/BE44W0XHx8= -github.com/containers/storage v1.57.1/go.mod h1:i/Hb4lu7YgFr9G0K6BMjqW0BLJO1sFsnWQwj2UoWCUM= +github.com/containers/storage v1.57.2 h1:2roCtTyE9pzIaBDHibK72DTnYkPmwWaq5uXxZdaWK4U= +github.com/containers/storage v1.57.2/go.mod h1:i/Hb4lu7YgFr9G0K6BMjqW0BLJO1sFsnWQwj2UoWCUM= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= @@ -579,8 +579,8 @@ github.com/oracle/oci-go-sdk/v54 v54.0.0 h1:CDLjeSejv2aDpElAJrhKpi6zvT/zhZCZuXch github.com/oracle/oci-go-sdk/v54 v54.0.0/go.mod h1:+t+yvcFGVp+3ZnztnyxqXfQDsMlq8U25faBLa+mqCMc= github.com/osbuild/blueprint v1.6.0 h1:HUV1w/dMxpgqOgVtHhfTZE3zRmWQkuW/qTfx9smKImI= github.com/osbuild/blueprint v1.6.0/go.mod h1:0d3dlY8aSJ6jM6NHwBmJFF1VIySsp/GsDpcJQ0yrOqM= -github.com/osbuild/images v0.148.0 h1:jRLpl/z50FF7Vylio7oD7GddKftiqf2RZZV1h5U8XhI= -github.com/osbuild/images v0.148.0/go.mod h1:jY21PhkxIozII4M0xCqZL7poLtFwDJlEGj88pb3lalQ= +github.com/osbuild/images v0.151.0 h1:r+8xbz0FGyUskl996eObrgymEqgLWwhtVa23Pj0Zp8U= +github.com/osbuild/images v0.151.0/go.mod h1:ZiEO1WWKuRvPSaiXsmqn+7krAIZ+qXiiOfBQed0H7lY= github.com/osbuild/osbuild-composer/pkg/splunk_logger v0.0.0-20240814102216-0239db53236d h1:r9BFPDv0uuA9k1947Jybcxs36c/pTywWS1gjeizvtcQ= github.com/osbuild/osbuild-composer/pkg/splunk_logger v0.0.0-20240814102216-0239db53236d/go.mod h1:zR1iu/hOuf+OQNJlk70tju9IqzzM4ycq0ectkFBm94U= github.com/osbuild/pulp-client v0.1.0 h1:L0C4ezBJGTamN3BKdv+rKLuq/WxXJbsFwz/Hj7aEmJ8= diff --git a/internal/store/json_test.go b/internal/store/json_test.go index 2db819f1b..3345af911 100644 --- a/internal/store/json_test.go +++ b/internal/store/json_test.go @@ -15,7 +15,6 @@ import ( "github.com/osbuild/blueprint/pkg/blueprint" "github.com/osbuild/images/pkg/arch" "github.com/osbuild/images/pkg/distro" - "github.com/osbuild/images/pkg/distro/fedora" "github.com/osbuild/images/pkg/distro/test_distro" "github.com/osbuild/images/pkg/distrofactory" "github.com/osbuild/images/pkg/rpmmd" @@ -308,7 +307,7 @@ func Test_upgrade(t *testing.T) { cleanup := setupTestHostDistro("fedora-37", arch.ARCH_X86_64.String()) t.Cleanup(cleanup) - factory := distrofactory.New(fedora.DistroFactory) + factory := distrofactory.NewDefault() store := newStoreFromV0(storeStruct, factory, nil) assert.Equal(1, len(store.blueprints)) diff --git a/vendor/github.com/containers/image/v5/signature/fulcio_cert.go b/vendor/github.com/containers/image/v5/signature/fulcio_cert.go index 31dfdd342..a3c204804 100644 --- a/vendor/github.com/containers/image/v5/signature/fulcio_cert.go +++ b/vendor/github.com/containers/image/v5/signature/fulcio_cert.go @@ -108,19 +108,10 @@ func (f *fulcioTrustRoot) verifyFulcioCertificateAtTime(relevantTime time.Time, } } - untrustedLeafCerts, err := cryptoutils.UnmarshalCertificatesFromPEM(untrustedCertificateBytes) + untrustedCertificate, err := parseLeafCertFromPEM(untrustedCertificateBytes) if err != nil { - return nil, internal.NewInvalidSignatureError(fmt.Sprintf("parsing leaf certificate: %v", err)) + return nil, err } - switch len(untrustedLeafCerts) { - case 0: - return nil, internal.NewInvalidSignatureError("no certificate found in signature certificate data") - case 1: - break // OK - default: - return nil, internal.NewInvalidSignatureError("unexpected multiple certificates present in signature certificate data") - } - untrustedCertificate := untrustedLeafCerts[0] // Go rejects Subject Alternative Name that has no DNSNames, EmailAddresses, IPAddresses and URIs; // we match SAN ourselves, so override that. @@ -195,6 +186,21 @@ func (f *fulcioTrustRoot) verifyFulcioCertificateAtTime(relevantTime time.Time, return untrustedCertificate.PublicKey, nil } +func parseLeafCertFromPEM(untrustedCertificateBytes []byte) (*x509.Certificate, error) { + untrustedLeafCerts, err := cryptoutils.UnmarshalCertificatesFromPEM(untrustedCertificateBytes) + if err != nil { + return nil, internal.NewInvalidSignatureError(fmt.Sprintf("parsing leaf certificate: %v", err)) + } + switch len(untrustedLeafCerts) { + case 0: + return nil, internal.NewInvalidSignatureError("no certificate found in signature certificate data") + case 1: // OK + return untrustedLeafCerts[0], nil + default: + return nil, internal.NewInvalidSignatureError("unexpected multiple certificates present in signature certificate data") + } +} + func verifyRekorFulcio(rekorPublicKeys []*ecdsa.PublicKey, fulcioTrustRoot *fulcioTrustRoot, untrustedRekorSET []byte, untrustedCertificateBytes []byte, untrustedIntermediateChainBytes []byte, untrustedBase64Signature string, untrustedPayloadBytes []byte) (crypto.PublicKey, error) { diff --git a/vendor/github.com/containers/image/v5/signature/pki_cert.go b/vendor/github.com/containers/image/v5/signature/pki_cert.go new file mode 100644 index 000000000..20624540f --- /dev/null +++ b/vendor/github.com/containers/image/v5/signature/pki_cert.go @@ -0,0 +1,74 @@ +package signature + +import ( + "crypto" + "crypto/x509" + "errors" + "fmt" + "slices" + + "github.com/containers/image/v5/signature/internal" + "github.com/sigstore/sigstore/pkg/cryptoutils" +) + +type pkiTrustRoot struct { + caRootsCertificates *x509.CertPool + caIntermediateCertificates *x509.CertPool + subjectEmail string + subjectHostname string +} + +func (p *pkiTrustRoot) validate() error { + if p.subjectEmail == "" && p.subjectHostname == "" { + return errors.New("Internal inconsistency: PKI use set up without subject email or subject hostname") + } + return nil +} + +func verifyPKI(pkiTrustRoot *pkiTrustRoot, untrustedCertificateBytes []byte, untrustedIntermediateChainBytes []byte) (crypto.PublicKey, error) { + var untrustedIntermediatePool *x509.CertPool + if pkiTrustRoot.caIntermediateCertificates != nil { + untrustedIntermediatePool = pkiTrustRoot.caIntermediateCertificates.Clone() + } else { + untrustedIntermediatePool = x509.NewCertPool() + } + if len(untrustedIntermediateChainBytes) > 0 { + untrustedIntermediateChain, err := cryptoutils.UnmarshalCertificatesFromPEM(untrustedIntermediateChainBytes) + if err != nil { + return nil, internal.NewInvalidSignatureError(fmt.Sprintf("loading certificate chain: %v", err)) + } + if len(untrustedIntermediateChain) > 1 { + for _, untrustedIntermediateCert := range untrustedIntermediateChain[:len(untrustedIntermediateChain)-1] { + untrustedIntermediatePool.AddCert(untrustedIntermediateCert) + } + } + } + + untrustedCertificate, err := parseLeafCertFromPEM(untrustedCertificateBytes) + if err != nil { + return nil, err + } + + if _, err := untrustedCertificate.Verify(x509.VerifyOptions{ + Intermediates: untrustedIntermediatePool, + Roots: pkiTrustRoot.caRootsCertificates, + KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageCodeSigning}, + }); err != nil { + return nil, internal.NewInvalidSignatureError(fmt.Sprintf("veryfing leaf certificate failed: %v", err)) + } + + if pkiTrustRoot.subjectEmail != "" { + if !slices.Contains(untrustedCertificate.EmailAddresses, pkiTrustRoot.subjectEmail) { + return nil, internal.NewInvalidSignatureError(fmt.Sprintf("Required email %q not found (got %q)", + pkiTrustRoot.subjectEmail, + untrustedCertificate.EmailAddresses)) + } + } + if pkiTrustRoot.subjectHostname != "" { + if err = untrustedCertificate.VerifyHostname(pkiTrustRoot.subjectHostname); err != nil { + return nil, internal.NewInvalidSignatureError(fmt.Sprintf("Unexpected subject hostname: %v", err)) + } + } + + return untrustedCertificate.PublicKey, nil +} diff --git a/vendor/github.com/containers/image/v5/signature/policy_config_sigstore.go b/vendor/github.com/containers/image/v5/signature/policy_config_sigstore.go index 965901e18..6393b66ea 100644 --- a/vendor/github.com/containers/image/v5/signature/policy_config_sigstore.go +++ b/vendor/github.com/containers/image/v5/signature/policy_config_sigstore.go @@ -71,6 +71,17 @@ func PRSigstoreSignedWithFulcio(fulcio PRSigstoreSignedFulcio) PRSigstoreSignedO } } +// PRSigstoreSignedWithPKI specifies a value for the "pki" field when calling NewPRSigstoreSigned. +func PRSigstoreSignedWithPKI(p PRSigstoreSignedPKI) PRSigstoreSignedOption { + return func(pr *prSigstoreSigned) error { + if pr.PKI != nil { + return InvalidPolicyFormatError(`"pki" already specified`) + } + pr.PKI = p + return nil + } +} + // PRSigstoreSignedWithRekorPublicKeyPath specifies a value for the "rekorPublicKeyPath" field when calling NewPRSigstoreSigned. func PRSigstoreSignedWithRekorPublicKeyPath(rekorPublicKeyPath string) PRSigstoreSignedOption { return func(pr *prSigstoreSigned) error { @@ -159,8 +170,11 @@ func newPRSigstoreSigned(options ...PRSigstoreSignedOption) (*prSigstoreSigned, if res.Fulcio != nil { keySources++ } + if res.PKI != nil { + keySources++ + } if keySources != 1 { - return nil, InvalidPolicyFormatError("exactly one of keyPath, keyPaths, keyData, keyDatas and fulcio must be specified") + return nil, InvalidPolicyFormatError("exactly one of keyPath, keyPaths, keyData, keyDatas, fulcio, and pki must be specified") } rekorSources := 0 @@ -182,6 +196,9 @@ func newPRSigstoreSigned(options ...PRSigstoreSignedOption) (*prSigstoreSigned, if res.Fulcio != nil && rekorSources == 0 { return nil, InvalidPolicyFormatError("At least one of rekorPublickeyPath, rekorPublicKeyPaths, rekorPublickeyData and rekorPublicKeyDatas must be specified if fulcio is used") } + if res.PKI != nil && rekorSources > 0 { + return nil, InvalidPolicyFormatError("rekorPublickeyPath, rekorPublicKeyPaths, rekorPublickeyData and rekorPublicKeyDatas are not supported for pki") + } if res.SignedIdentity == nil { return nil, InvalidPolicyFormatError("signedIdentity not specified") @@ -218,9 +235,10 @@ var _ json.Unmarshaler = (*prSigstoreSigned)(nil) func (pr *prSigstoreSigned) UnmarshalJSON(data []byte) error { *pr = prSigstoreSigned{} var tmp prSigstoreSigned - var gotKeyPath, gotKeyPaths, gotKeyData, gotKeyDatas, gotFulcio bool + var gotKeyPath, gotKeyPaths, gotKeyData, gotKeyDatas, gotFulcio, gotPKI bool var gotRekorPublicKeyPath, gotRekorPublicKeyPaths, gotRekorPublicKeyData, gotRekorPublicKeyDatas bool var fulcio prSigstoreSignedFulcio + var pki prSigstoreSignedPKI var signedIdentity json.RawMessage if err := internal.ParanoidUnmarshalJSONObject(data, func(key string) any { switch key { @@ -253,6 +271,9 @@ func (pr *prSigstoreSigned) UnmarshalJSON(data []byte) error { case "rekorPublicKeyDatas": gotRekorPublicKeyDatas = true return &tmp.RekorPublicKeyDatas + case "pki": + gotPKI = true + return &pki case "signedIdentity": return &signedIdentity default: @@ -303,6 +324,9 @@ func (pr *prSigstoreSigned) UnmarshalJSON(data []byte) error { if gotRekorPublicKeyDatas { opts = append(opts, PRSigstoreSignedWithRekorPublicKeyDatas(tmp.RekorPublicKeyDatas)) } + if gotPKI { + opts = append(opts, PRSigstoreSignedWithPKI(&pki)) + } opts = append(opts, PRSigstoreSignedWithSignedIdentity(tmp.SignedIdentity)) res, err := newPRSigstoreSigned(opts...) @@ -440,3 +464,167 @@ func (f *prSigstoreSignedFulcio) UnmarshalJSON(data []byte) error { *f = *res return nil } + +// PRSigstoreSignedPKIOption is a way to pass values to NewPRSigstoreSignedPKI +type PRSigstoreSignedPKIOption func(*prSigstoreSignedPKI) error + +// PRSigstoreSignedPKIWithCARootsPath specifies a value for the "caRootsPath" field when calling NewPRSigstoreSignedPKI +func PRSigstoreSignedPKIWithCARootsPath(caRootsPath string) PRSigstoreSignedPKIOption { + return func(p *prSigstoreSignedPKI) error { + if p.CARootsPath != "" { + return InvalidPolicyFormatError(`"caRootsPath" already specified`) + } + p.CARootsPath = caRootsPath + return nil + } +} + +// PRSigstoreSignedPKIWithCARootsData specifies a value for the "caRootsData" field when calling NewPRSigstoreSignedPKI +func PRSigstoreSignedPKIWithCARootsData(caRootsData []byte) PRSigstoreSignedPKIOption { + return func(p *prSigstoreSignedPKI) error { + if p.CARootsData != nil { + return InvalidPolicyFormatError(`"caRootsData" already specified`) + } + p.CARootsData = caRootsData + return nil + } +} + +// PRSigstoreSignedPKIWithCAIntermediatesPath specifies a value for the "caIntermediatesPath" field when calling NewPRSigstoreSignedPKI +func PRSigstoreSignedPKIWithCAIntermediatesPath(caIntermediatesPath string) PRSigstoreSignedPKIOption { + return func(p *prSigstoreSignedPKI) error { + if p.CAIntermediatesPath != "" { + return InvalidPolicyFormatError(`"caIntermediatesPath" already specified`) + } + p.CAIntermediatesPath = caIntermediatesPath + return nil + } +} + +// PRSigstoreSignedPKIWithCAIntermediatesData specifies a value for the "caIntermediatesData" field when calling NewPRSigstoreSignedPKI +func PRSigstoreSignedPKIWithCAIntermediatesData(caIntermediatesData []byte) PRSigstoreSignedPKIOption { + return func(p *prSigstoreSignedPKI) error { + if p.CAIntermediatesData != nil { + return InvalidPolicyFormatError(`"caIntermediatesData" already specified`) + } + p.CAIntermediatesData = caIntermediatesData + return nil + } +} + +// PRSigstoreSignedPKIWithSubjectEmail specifies a value for the "subjectEmail" field when calling NewPRSigstoreSignedPKI +func PRSigstoreSignedPKIWithSubjectEmail(subjectEmail string) PRSigstoreSignedPKIOption { + return func(p *prSigstoreSignedPKI) error { + if p.SubjectEmail != "" { + return InvalidPolicyFormatError(`"subjectEmail" already specified`) + } + p.SubjectEmail = subjectEmail + return nil + } +} + +// PRSigstoreSignedPKIWithSubjectHostname specifies a value for the "subjectHostname" field when calling NewPRSigstoreSignedPKI +func PRSigstoreSignedPKIWithSubjectHostname(subjectHostname string) PRSigstoreSignedPKIOption { + return func(p *prSigstoreSignedPKI) error { + if p.SubjectHostname != "" { + return InvalidPolicyFormatError(`"subjectHostname" already specified`) + } + p.SubjectHostname = subjectHostname + return nil + } +} + +// newPRSigstoreSignedPKI is NewPRSigstoreSignedPKI, except it returns the private type +func newPRSigstoreSignedPKI(options ...PRSigstoreSignedPKIOption) (*prSigstoreSignedPKI, error) { + res := prSigstoreSignedPKI{} + for _, o := range options { + if err := o(&res); err != nil { + return nil, err + } + } + + if res.CARootsPath != "" && res.CARootsData != nil { + return nil, InvalidPolicyFormatError("caRootsPath and caRootsData cannot be used simultaneously") + } + if res.CARootsPath == "" && res.CARootsData == nil { + return nil, InvalidPolicyFormatError("At least one of caRootsPath and caRootsData must be specified") + } + + if res.CAIntermediatesPath != "" && res.CAIntermediatesData != nil { + return nil, InvalidPolicyFormatError("caIntermediatesPath and caIntermediatesData cannot be used simultaneously") + } + + if res.SubjectEmail == "" && res.SubjectHostname == "" { + return nil, InvalidPolicyFormatError("At least one of subjectEmail, subjectHostname must be specified") + } + + return &res, nil +} + +// NewPRSigstoreSignedPKI returns a PRSigstoreSignedPKI based on options. +func NewPRSigstoreSignedPKI(options ...PRSigstoreSignedPKIOption) (PRSigstoreSignedPKI, error) { + return newPRSigstoreSignedPKI(options...) +} + +// Compile-time check that prSigstoreSignedPKI implements json.Unmarshaler. +var _ json.Unmarshaler = (*prSigstoreSignedPKI)(nil) + +func (p *prSigstoreSignedPKI) UnmarshalJSON(data []byte) error { + *p = prSigstoreSignedPKI{} + var tmp prSigstoreSignedPKI + var gotCARootsPath, gotCARootsData, gotCAIntermediatesPath, gotCAIntermediatesData, gotSubjectEmail, gotSubjectHostname bool + if err := internal.ParanoidUnmarshalJSONObject(data, func(key string) any { + switch key { + case "caRootsPath": + gotCARootsPath = true + return &tmp.CARootsPath + case "caRootsData": + gotCARootsData = true + return &tmp.CARootsData + case "caIntermediatesPath": + gotCAIntermediatesPath = true + return &tmp.CAIntermediatesPath + case "caIntermediatesData": + gotCAIntermediatesData = true + return &tmp.CAIntermediatesData + case "subjectEmail": + gotSubjectEmail = true + return &tmp.SubjectEmail + case "subjectHostname": + gotSubjectHostname = true + return &tmp.SubjectHostname + default: + return nil + } + }); err != nil { + return err + } + + var opts []PRSigstoreSignedPKIOption + if gotCARootsPath { + opts = append(opts, PRSigstoreSignedPKIWithCARootsPath(tmp.CARootsPath)) + } + if gotCARootsData { + opts = append(opts, PRSigstoreSignedPKIWithCARootsData(tmp.CARootsData)) + } + if gotCAIntermediatesPath { + opts = append(opts, PRSigstoreSignedPKIWithCAIntermediatesPath(tmp.CAIntermediatesPath)) + } + if gotCAIntermediatesData { + opts = append(opts, PRSigstoreSignedPKIWithCAIntermediatesData(tmp.CAIntermediatesData)) + } + if gotSubjectEmail { + opts = append(opts, PRSigstoreSignedPKIWithSubjectEmail(tmp.SubjectEmail)) + } + if gotSubjectHostname { + opts = append(opts, PRSigstoreSignedPKIWithSubjectHostname(tmp.SubjectHostname)) + } + + res, err := newPRSigstoreSignedPKI(opts...) + if err != nil { + return err + } + + *p = *res + return nil +} diff --git a/vendor/github.com/containers/image/v5/signature/policy_eval_sigstore.go b/vendor/github.com/containers/image/v5/signature/policy_eval_sigstore.go index 9c553771c..faede787a 100644 --- a/vendor/github.com/containers/image/v5/signature/policy_eval_sigstore.go +++ b/vendor/github.com/containers/image/v5/signature/policy_eval_sigstore.go @@ -97,11 +97,64 @@ func (f *prSigstoreSignedFulcio) prepareTrustRoot() (*fulcioTrustRoot, error) { return &fulcio, nil } +// prepareTrustRoot creates a pkiTrustRoot from the input data. +// (This also prevents external implementations of this interface, ensuring that prSigstoreSignedPKI is the only one.) +func (p *prSigstoreSignedPKI) prepareTrustRoot() (*pkiTrustRoot, error) { + caRootsCertPEMs, err := loadBytesFromConfigSources(configBytesSources{ + inconsistencyErrorMessage: `Internal inconsistency: both "caRootsPath" and "caRootsData" specified`, + path: p.CARootsPath, + data: p.CARootsData, + }) + if err != nil { + return nil, err + } + if len(caRootsCertPEMs) != 1 { + return nil, errors.New(`Internal inconsistency: PKI specified with not exactly one of "caRootsPath" nor "caRootsData"`) + } + rootsCerts := x509.NewCertPool() + if ok := rootsCerts.AppendCertsFromPEM(caRootsCertPEMs[0]); !ok { + return nil, errors.New("error loading PKI CA Roots certificates") + } + pki := pkiTrustRoot{ + caRootsCertificates: rootsCerts, + subjectEmail: p.SubjectEmail, + subjectHostname: p.SubjectHostname, + } + caIntermediateCertPEMs, err := loadBytesFromConfigSources(configBytesSources{ + inconsistencyErrorMessage: `Internal inconsistency: both "caIntermediatesPath" and "caIntermediatesData" specified`, + path: p.CAIntermediatesPath, + data: p.CAIntermediatesData, + }) + if err != nil { + return nil, err + } + if caIntermediateCertPEMs != nil { + if len(caIntermediateCertPEMs) != 1 { + return nil, errors.New(`Internal inconsistency: PKI specified with invalid value from "caIntermediatesPath" or "caIntermediatesData"`) + } + intermediatePool := x509.NewCertPool() + trustedIntermediates, err := cryptoutils.UnmarshalCertificatesFromPEM(caIntermediateCertPEMs[0]) + if err != nil { + return nil, internal.NewInvalidSignatureError(fmt.Sprintf("loading trusted intermediate certificates: %v", err)) + } + for _, trustedIntermediateCert := range trustedIntermediates { + intermediatePool.AddCert(trustedIntermediateCert) + } + pki.caIntermediateCertificates = intermediatePool + } + + if err := pki.validate(); err != nil { + return nil, err + } + return &pki, nil +} + // sigstoreSignedTrustRoot contains an already parsed version of the prSigstoreSigned policy type sigstoreSignedTrustRoot struct { publicKeys []crypto.PublicKey fulcio *fulcioTrustRoot rekorPublicKeys []*ecdsa.PublicKey + pki *pkiTrustRoot } func (pr *prSigstoreSigned) prepareTrustRoot() (*sigstoreSignedTrustRoot, error) { @@ -166,6 +219,14 @@ func (pr *prSigstoreSigned) prepareTrustRoot() (*sigstoreSignedTrustRoot, error) } } + if pr.PKI != nil { + p, err := pr.PKI.prepareTrustRoot() + if err != nil { + return nil, err + } + res.pki = p + } + return &res, nil } @@ -189,13 +250,23 @@ func (pr *prSigstoreSigned) isSignatureAccepted(ctx context.Context, image priva } untrustedPayload := sig.UntrustedPayload() + keySources := 0 + if trustRoot.publicKeys != nil { + keySources++ + } + if trustRoot.fulcio != nil { + keySources++ + } + if trustRoot.pki != nil { + keySources++ + } + var publicKeys []crypto.PublicKey switch { - case trustRoot.publicKeys != nil && trustRoot.fulcio != nil: // newPRSigstoreSigned rejects such combinations. - return sarRejected, errors.New("Internal inconsistency: Both a public key and Fulcio CA specified") - case trustRoot.publicKeys == nil && trustRoot.fulcio == nil: // newPRSigstoreSigned rejects such combinations. - return sarRejected, errors.New("Internal inconsistency: Neither a public key nor a Fulcio CA specified") - + case keySources > 1: // newPRSigstoreSigned rejects more than one key sources. + return sarRejected, errors.New("Internal inconsistency: More than one of public key, Fulcio, or PKI specified") + case keySources == 0: // newPRSigstoreSigned rejects empty key sources. + return sarRejected, errors.New("Internal inconsistency: A public key, Fulcio, or PKI must be specified.") case trustRoot.publicKeys != nil: if trustRoot.rekorPublicKeys != nil { untrustedSET, ok := untrustedAnnotations[signature.SigstoreSETAnnotationKey] @@ -254,6 +325,24 @@ func (pr *prSigstoreSigned) isSignatureAccepted(ctx context.Context, image priva return sarRejected, err } publicKeys = []crypto.PublicKey{pk} + + case trustRoot.pki != nil: + if trustRoot.rekorPublicKeys != nil { // newPRSigstoreSigned rejects such combinations. + return sarRejected, errors.New("Internal inconsistency: PKI specified with a Rekor public key") + } + untrustedCert, ok := untrustedAnnotations[signature.SigstoreCertificateAnnotationKey] + if !ok { + return sarRejected, fmt.Errorf("missing %s annotation", signature.SigstoreCertificateAnnotationKey) + } + var untrustedIntermediateChainBytes []byte + if untrustedIntermediateChain, ok := untrustedAnnotations[signature.SigstoreIntermediateCertificateChainAnnotationKey]; ok { + untrustedIntermediateChainBytes = []byte(untrustedIntermediateChain) + } + pk, err := verifyPKI(trustRoot.pki, []byte(untrustedCert), untrustedIntermediateChainBytes) + if err != nil { + return sarRejected, err + } + publicKeys = []crypto.PublicKey{pk} } if len(publicKeys) == 0 { diff --git a/vendor/github.com/containers/image/v5/signature/policy_types.go b/vendor/github.com/containers/image/v5/signature/policy_types.go index 32aa1c0ad..2db0c4591 100644 --- a/vendor/github.com/containers/image/v5/signature/policy_types.go +++ b/vendor/github.com/containers/image/v5/signature/policy_types.go @@ -111,16 +111,16 @@ type prSignedBaseLayer struct { type prSigstoreSigned struct { prCommon - // KeyPath is a pathname to a local file containing the trusted key. Exactly one of KeyPath, KeyPaths, KeyData, KeyDatas and Fulcio must be specified. + // KeyPath is a pathname to a local file containing the trusted key. Exactly one of KeyPath, KeyPaths, KeyData, KeyDatas, Fulcio, and PKI must be specified. KeyPath string `json:"keyPath,omitempty"` - // KeyPaths is a set of pathnames to local files containing the trusted key(s). Exactly one of KeyPath, KeyPaths, KeyData, KeyDatas and Fulcio must be specified. + // KeyPaths is a set of pathnames to local files containing the trusted key(s). Exactly one of KeyPath, KeyPaths, KeyData, KeyDatas, Fulcio, and PKI must be specified. KeyPaths []string `json:"keyPaths,omitempty"` - // KeyData contains the trusted key, base64-encoded. Exactly one of KeyPath, KeyPaths, KeyData, KeyDatas and Fulcio must be specified. + // KeyData contains the trusted key, base64-encoded. Exactly one of KeyPath, KeyPaths, KeyData, KeyDatas, Fulcio, and PKI must be specified. KeyData []byte `json:"keyData,omitempty"` - // KeyDatas is a set of trusted keys, base64-encoded. Exactly one of KeyPath, KeyPaths, KeyData, KeyDatas and Fulcio must be specified. + // KeyDatas is a set of trusted keys, base64-encoded. Exactly one of KeyPath, KeyPaths, KeyData, KeyDatas, Fulcio, and PKI must be specified. KeyDatas [][]byte `json:"keyDatas,omitempty"` - // Fulcio specifies which Fulcio-generated certificates are accepted. Exactly one of KeyPath, KeyPaths, KeyData, KeyDatas and Fulcio must be specified. + // Fulcio specifies which Fulcio-generated certificates are accepted. Exactly one of KeyPath, KeyPaths, KeyData, KeyDatas, Fulcio, and PKI must be specified. // If Fulcio is specified, one of RekorPublicKeyPath or RekorPublicKeyData must be specified as well. Fulcio PRSigstoreSignedFulcio `json:"fulcio,omitempty"` @@ -141,6 +141,9 @@ type prSigstoreSigned struct { // otherwise it is optional (and Rekor inclusion is not required if a Rekor public key is not specified). RekorPublicKeyDatas [][]byte `json:"rekorPublicKeyDatas,omitempty"` + // PKI specifies which PKI-generated certificates are accepted. Exactly one of KeyPath, KeyPaths, KeyData, KeyDatas, Fulcio, and PKI must be specified. + PKI PRSigstoreSignedPKI `json:"pki,omitempty"` + // SignedIdentity specifies what image identity the signature must be claiming about the image. // Defaults to "matchRepoDigestOrExact" if not specified. // Note that /usr/bin/cosign interoperability might require using repo-only matching. @@ -167,6 +170,30 @@ type prSigstoreSignedFulcio struct { SubjectEmail string `json:"subjectEmail,omitempty"` } +// PRSigstoreSignedPKI contains PKI configuration options for a "sigstoreSigned" PolicyRequirement. +type PRSigstoreSignedPKI interface { + // prepareTrustRoot creates a pkiTrustRoot from the input data. + // (This also prevents external implementations of this interface, ensuring that prSigstoreSignedPKI is the only one.) + prepareTrustRoot() (*pkiTrustRoot, error) +} + +// prSigstoreSignedPKI contains non-fulcio certificate PKI configuration options for prSigstoreSigned +type prSigstoreSignedPKI struct { + // CARootsPath a path to a file containing accepted CA root certificates, in PEM format. Exactly one of CARootsPath and CARootsData must be specified. + CARootsPath string `json:"caRootsPath"` + // CARootsData contains accepted CA root certificates in PEM format, all of that base64-encoded. Exactly one of CARootsPath and CARootsData must be specified. + CARootsData []byte `json:"caRootsData"` + // CAIntermediatesPath a path to a file containing accepted CA intermediate certificates, in PEM format. Only one of CAIntermediatesPath or CAIntermediatesData can be specified, not both. + CAIntermediatesPath string `json:"caIntermediatesPath"` + // CAIntermediatesData contains accepted CA intermediate certificates in PEM format, all of that base64-encoded. Only one of CAIntermediatesPath or CAIntermediatesData can be specified, not both. + CAIntermediatesData []byte `json:"caIntermediatesData"` + + // SubjectEmail specifies the expected email address imposed on the subject to which the certificate was issued. At least one of SubjectEmail and SubjectHostname must be specified. + SubjectEmail string `json:"subjectEmail"` + // SubjectHostname specifies the expected hostname imposed on the subject to which the certificate was issued. At least one of SubjectEmail and SubjectHostname must be specified. + SubjectHostname string `json:"subjectHostname"` +} + // PolicyReferenceMatch specifies a set of image identities accepted in PolicyRequirement. // The type is public, but its implementation is private. diff --git a/vendor/github.com/containers/image/v5/tarball/tarball_src.go b/vendor/github.com/containers/image/v5/tarball/tarball_src.go index 7d4a83bc9..283a32d0e 100644 --- a/vendor/github.com/containers/image/v5/tarball/tarball_src.go +++ b/vendor/github.com/containers/image/v5/tarball/tarball_src.go @@ -14,8 +14,9 @@ import ( "github.com/containers/image/v5/internal/imagesource/impl" "github.com/containers/image/v5/internal/imagesource/stubs" + "github.com/containers/image/v5/pkg/compression" + compressionTypes "github.com/containers/image/v5/pkg/compression/types" "github.com/containers/image/v5/types" - "github.com/klauspost/pgzip" digest "github.com/opencontainers/go-digest" imgspecs "github.com/opencontainers/image-spec/specs-go" imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" @@ -82,31 +83,47 @@ func (r *tarballReference) NewImageSource(ctx context.Context, sys *types.System } } - // Default to assuming the layer is compressed. - layerType := imgspecv1.MediaTypeImageLayerGzip - // Set up to digest the file as it is. blobIDdigester := digest.Canonical.Digester() reader = io.TeeReader(reader, blobIDdigester.Hash()) - // Set up to digest the file after we maybe decompress it. - diffIDdigester := digest.Canonical.Digester() - uncompressed, err := pgzip.NewReader(reader) - if err == nil { - // It is compressed, so the diffID is the digest of the uncompressed version - reader = io.TeeReader(uncompressed, diffIDdigester.Hash()) - } else { - // It is not compressed, so the diffID and the blobID are going to be the same - diffIDdigester = blobIDdigester - layerType = imgspecv1.MediaTypeImageLayer - uncompressed = nil - } - // TODO: This can take quite some time, and should ideally be cancellable using ctx.Done(). - if _, err := io.Copy(io.Discard, reader); err != nil { - return nil, fmt.Errorf("error reading %q: %w", filename, err) - } - if uncompressed != nil { - uncompressed.Close() + var layerType string + var diffIDdigester digest.Digester + // If necessary, digest the file after we decompress it. + if err := func() error { // A scope for defer + format, decompressor, reader, err := compression.DetectCompressionFormat(reader) + if err != nil { + return err + } + if decompressor != nil { + uncompressed, err := decompressor(reader) + if err != nil { + return err + } + defer uncompressed.Close() + // It is compressed, so the diffID is the digest of the uncompressed version + diffIDdigester = digest.Canonical.Digester() + reader = io.TeeReader(uncompressed, diffIDdigester.Hash()) + switch format.Name() { + case compressionTypes.GzipAlgorithmName: + layerType = imgspecv1.MediaTypeImageLayerGzip + case compressionTypes.ZstdAlgorithmName: + layerType = imgspecv1.MediaTypeImageLayerZstd + default: // This is incorrect, but we have no good options, and it is what this transport was historically doing. + layerType = imgspecv1.MediaTypeImageLayerGzip + } + } else { + // It is not compressed, so the diffID and the blobID are going to be the same + diffIDdigester = blobIDdigester + layerType = imgspecv1.MediaTypeImageLayer + } + // TODO: This can take quite some time, and should ideally be cancellable using ctx.Done(). + if _, err := io.Copy(io.Discard, reader); err != nil { + return fmt.Errorf("error reading %q: %w", filename, err) + } + return nil + }(); err != nil { + return nil, err } // Grab our uncompressed and possibly-compressed digests and sizes. diff --git a/vendor/github.com/containers/image/v5/version/version.go b/vendor/github.com/containers/image/v5/version/version.go index 0322755ba..611324a2e 100644 --- a/vendor/github.com/containers/image/v5/version/version.go +++ b/vendor/github.com/containers/image/v5/version/version.go @@ -8,7 +8,7 @@ const ( // VersionMinor is for functionality in a backwards-compatible manner VersionMinor = 34 // VersionPatch is for backwards-compatible bug fixes - VersionPatch = 0 + VersionPatch = 3 // VersionDev indicates development branch. Releases will be empty string. VersionDev = "" diff --git a/vendor/github.com/containers/storage/Makefile b/vendor/github.com/containers/storage/Makefile index 888fef842..518fd7f6e 100644 --- a/vendor/github.com/containers/storage/Makefile +++ b/vendor/github.com/containers/storage/Makefile @@ -35,7 +35,7 @@ TESTFLAGS := $(shell $(GO) test -race $(BUILDFLAGS) ./pkg/stringutils 2>&1 > /de # N/B: This value is managed by Renovate, manual changes are # possible, as long as they don't disturb the formatting # (i.e. DO NOT ADD A 'v' prefix!) -GOLANGCI_LINT_VERSION := 1.63.4 +GOLANGCI_LINT_VERSION := 1.64.5 default all: local-binary docs local-validate local-cross ## validate all checks, build and cross-build\nbinaries and docs diff --git a/vendor/github.com/containers/storage/VERSION b/vendor/github.com/containers/storage/VERSION index b4cf7c0db..0af844be0 100644 --- a/vendor/github.com/containers/storage/VERSION +++ b/vendor/github.com/containers/storage/VERSION @@ -1 +1 @@ -1.57.1 +1.57.2 diff --git a/vendor/github.com/containers/storage/pkg/idmap/idmapped_utils.go b/vendor/github.com/containers/storage/pkg/idmap/idmapped_utils.go index db31da768..4a75b70fd 100644 --- a/vendor/github.com/containers/storage/pkg/idmap/idmapped_utils.go +++ b/vendor/github.com/containers/storage/pkg/idmap/idmapped_utils.go @@ -33,8 +33,9 @@ func CreateIDMappedMount(source, target string, pid int) error { if err := unix.MountSetattr(targetDirFd, "", unix.AT_EMPTY_PATH|unix.AT_RECURSIVE, &unix.MountAttr{ - Attr_set: unix.MOUNT_ATTR_IDMAP, - Userns_fd: uint64(userNsFile.Fd()), + Attr_set: unix.MOUNT_ATTR_IDMAP, + Userns_fd: uint64(userNsFile.Fd()), + Propagation: unix.MS_PRIVATE, }); err != nil { return &os.PathError{Op: "mount_setattr", Path: source, Err: err} } diff --git a/vendor/github.com/osbuild/images/data/dependencies/osbuild b/vendor/github.com/osbuild/images/data/dependencies/osbuild index 5d1277e79..c663e4d09 100644 --- a/vendor/github.com/osbuild/images/data/dependencies/osbuild +++ b/vendor/github.com/osbuild/images/data/dependencies/osbuild @@ -1 +1 @@ -147 \ No newline at end of file +151 \ No newline at end of file diff --git a/vendor/github.com/osbuild/images/data/repositories/almalinux-10.0.json b/vendor/github.com/osbuild/images/data/repositories/almalinux-10.0.json new file mode 100644 index 000000000..e9a9a8b57 --- /dev/null +++ b/vendor/github.com/osbuild/images/data/repositories/almalinux-10.0.json @@ -0,0 +1,66 @@ +{ + "aarch64": [ + { + "name": "baseos", + "baseurl": "https://repo.almalinux.org/almalinux/10.0/BaseOS/aarch64/os/", + "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGaP6O8BEACvg8IlAxGayV8zOi9Ex+Pd8lrj2BrBzloG8ri84ORp9o8ojq7l\nykKmIElHe11cQD2Lf/a4lcQQ4Ec3baiD786X6K2eVSlBEAnZMzfjDg8R63SfsBuu\n8Yk+lUyqlBrDnSDYaPruOAzLIz2r82ikIC1jDbipZsMFPFHPI4/hayyWxJ3oGxRe\n0mbtYLB9ElEKngt+/hfo7JLklakbznyIRuVEF3VrZb91XC6r/idqfJoNyBXSKidj\nz0IwqOhgkLUk84rzltDo3AzwGqusd7PEuhOmqinOhp0hMdXsztD4TVyhw82iXu/O\nonOAObZTZYfM6Z8btmDqkoo0aT+oPPCuZ3yC/caU9dhvCSXET/CGoXc3hL55u9PV\nqmcVm/mwvuEImEAvxVc0/dBzEUk+FwW8KsaN3HoUKrC4/NqgmaQz8/42np7u2j+B\nOOJ4hAckNEdWd8rB86CYN00sdxnvLBsp8V3IwEqXLhGOoBsagy61Z8hKCM+siOGn\nxmbbybgaLOs+DPlxt9LrtgLJHODwmD96oysUPJuA0lv8KMiSpId0tSpp9Wn/wHBG\nkRgxGYfzQu7WRvRZqQaleft1JTXXOjNzPur0RkJyb3yFwAoxpePyo/WrupM41OHW\n58cEqdC6riCnJcS4U84RLj+hwvufBVB7areQ75sETnKeyozZW+P16E1t/wARAQAB\ntChBbG1hTGludXggT1MgMTAgPHBhY2thZ2VyQGFsbWFsaW51eC5vcmc+iQJMBBMB\nCgA2FiEE7m23uY9b9e3Z2g3l3uXBHMKh5XIFAmaP6O8CGwMECwkIBwQVCgkIBRYC\nAwEAAh4FAheAAAoJEN7lwRzCoeVy32AP/A2+KI+JhmsxnactSptkAWGyAAf1YBWW\nJs2sc9OJdKj7uIkzszCx7c7VIVeF/VLijIYpM/zwUgir5S5SimzQmY+FumwbKIml\nK5RBsoSog22i7Edho0MLa1pa6qvnKS0nkl9DEcu8EbMUhucWbxGnCG/22EEMTrY+\nSi1IZNkDGtlBHHBKMC+STbqqTxtdy4tAd2NYwWh3sBIh6PF7T4NLRAugu7PZQr5K\namS4z2lV3ebshGjieA0Zoznwh0AXgN0gZ/0pC/LXI25gcgtrvkCyL8Fe0AyZUMd8\nUvZXaRSsm3SkCUIlGjPrvuItn1D7tHmqVSCDKXDM2TqjfiRm1JF+2OFCBNvGz19V\nLxWd/Gf+0qw0dtKxRMKzGh0mxXY40hjtmYZulrPxhG5itNDjStovgrevM1HBsXs9\nikrkOGQ0pFcqizTn4ZKAmMozEMuIuV89Vof2bBCg7pHT1FmXVdAaYJxb6a7A/CgN\nqHjoh8AxBiGw/Q2NM4YJlUVhHqqd+/lUG3WJqACNEnqSlZkYQ3HqNNaKhHVbD4mN\nq/g6v+f8aWWDZDsI6IAfbJUB+KPEnIvQJQleWuHrq7kcUMhEq3dwBMIoTVEHhUUr\nRQKToSEM1rN7PcanaXQM2gy141dS7tFLxhapG8ug75LkIUnEOpPMtUjvrU1ZELGq\n36vVHBB+dTDg\n=tJCw\n-----END PGP PUBLIC KEY BLOCK-----\n", + "check_gpg": true, + "rhsm": false + }, + { + "name": "appstream", + "baseurl": "https://repo.almalinux.org/almalinux/10.0/AppStream/aarch64/os/", + "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGaP6O8BEACvg8IlAxGayV8zOi9Ex+Pd8lrj2BrBzloG8ri84ORp9o8ojq7l\nykKmIElHe11cQD2Lf/a4lcQQ4Ec3baiD786X6K2eVSlBEAnZMzfjDg8R63SfsBuu\n8Yk+lUyqlBrDnSDYaPruOAzLIz2r82ikIC1jDbipZsMFPFHPI4/hayyWxJ3oGxRe\n0mbtYLB9ElEKngt+/hfo7JLklakbznyIRuVEF3VrZb91XC6r/idqfJoNyBXSKidj\nz0IwqOhgkLUk84rzltDo3AzwGqusd7PEuhOmqinOhp0hMdXsztD4TVyhw82iXu/O\nonOAObZTZYfM6Z8btmDqkoo0aT+oPPCuZ3yC/caU9dhvCSXET/CGoXc3hL55u9PV\nqmcVm/mwvuEImEAvxVc0/dBzEUk+FwW8KsaN3HoUKrC4/NqgmaQz8/42np7u2j+B\nOOJ4hAckNEdWd8rB86CYN00sdxnvLBsp8V3IwEqXLhGOoBsagy61Z8hKCM+siOGn\nxmbbybgaLOs+DPlxt9LrtgLJHODwmD96oysUPJuA0lv8KMiSpId0tSpp9Wn/wHBG\nkRgxGYfzQu7WRvRZqQaleft1JTXXOjNzPur0RkJyb3yFwAoxpePyo/WrupM41OHW\n58cEqdC6riCnJcS4U84RLj+hwvufBVB7areQ75sETnKeyozZW+P16E1t/wARAQAB\ntChBbG1hTGludXggT1MgMTAgPHBhY2thZ2VyQGFsbWFsaW51eC5vcmc+iQJMBBMB\nCgA2FiEE7m23uY9b9e3Z2g3l3uXBHMKh5XIFAmaP6O8CGwMECwkIBwQVCgkIBRYC\nAwEAAh4FAheAAAoJEN7lwRzCoeVy32AP/A2+KI+JhmsxnactSptkAWGyAAf1YBWW\nJs2sc9OJdKj7uIkzszCx7c7VIVeF/VLijIYpM/zwUgir5S5SimzQmY+FumwbKIml\nK5RBsoSog22i7Edho0MLa1pa6qvnKS0nkl9DEcu8EbMUhucWbxGnCG/22EEMTrY+\nSi1IZNkDGtlBHHBKMC+STbqqTxtdy4tAd2NYwWh3sBIh6PF7T4NLRAugu7PZQr5K\namS4z2lV3ebshGjieA0Zoznwh0AXgN0gZ/0pC/LXI25gcgtrvkCyL8Fe0AyZUMd8\nUvZXaRSsm3SkCUIlGjPrvuItn1D7tHmqVSCDKXDM2TqjfiRm1JF+2OFCBNvGz19V\nLxWd/Gf+0qw0dtKxRMKzGh0mxXY40hjtmYZulrPxhG5itNDjStovgrevM1HBsXs9\nikrkOGQ0pFcqizTn4ZKAmMozEMuIuV89Vof2bBCg7pHT1FmXVdAaYJxb6a7A/CgN\nqHjoh8AxBiGw/Q2NM4YJlUVhHqqd+/lUG3WJqACNEnqSlZkYQ3HqNNaKhHVbD4mN\nq/g6v+f8aWWDZDsI6IAfbJUB+KPEnIvQJQleWuHrq7kcUMhEq3dwBMIoTVEHhUUr\nRQKToSEM1rN7PcanaXQM2gy141dS7tFLxhapG8ug75LkIUnEOpPMtUjvrU1ZELGq\n36vVHBB+dTDg\n=tJCw\n-----END PGP PUBLIC KEY BLOCK-----\n", + "check_gpg": true, + "rhsm": false + } + ], + "ppc64le": [ + { + "name": "baseos", + "baseurl": "https://repo.almalinux.org/almalinux/10.0/BaseOS/ppc64le/os/", + "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGaP6O8BEACvg8IlAxGayV8zOi9Ex+Pd8lrj2BrBzloG8ri84ORp9o8ojq7l\nykKmIElHe11cQD2Lf/a4lcQQ4Ec3baiD786X6K2eVSlBEAnZMzfjDg8R63SfsBuu\n8Yk+lUyqlBrDnSDYaPruOAzLIz2r82ikIC1jDbipZsMFPFHPI4/hayyWxJ3oGxRe\n0mbtYLB9ElEKngt+/hfo7JLklakbznyIRuVEF3VrZb91XC6r/idqfJoNyBXSKidj\nz0IwqOhgkLUk84rzltDo3AzwGqusd7PEuhOmqinOhp0hMdXsztD4TVyhw82iXu/O\nonOAObZTZYfM6Z8btmDqkoo0aT+oPPCuZ3yC/caU9dhvCSXET/CGoXc3hL55u9PV\nqmcVm/mwvuEImEAvxVc0/dBzEUk+FwW8KsaN3HoUKrC4/NqgmaQz8/42np7u2j+B\nOOJ4hAckNEdWd8rB86CYN00sdxnvLBsp8V3IwEqXLhGOoBsagy61Z8hKCM+siOGn\nxmbbybgaLOs+DPlxt9LrtgLJHODwmD96oysUPJuA0lv8KMiSpId0tSpp9Wn/wHBG\nkRgxGYfzQu7WRvRZqQaleft1JTXXOjNzPur0RkJyb3yFwAoxpePyo/WrupM41OHW\n58cEqdC6riCnJcS4U84RLj+hwvufBVB7areQ75sETnKeyozZW+P16E1t/wARAQAB\ntChBbG1hTGludXggT1MgMTAgPHBhY2thZ2VyQGFsbWFsaW51eC5vcmc+iQJMBBMB\nCgA2FiEE7m23uY9b9e3Z2g3l3uXBHMKh5XIFAmaP6O8CGwMECwkIBwQVCgkIBRYC\nAwEAAh4FAheAAAoJEN7lwRzCoeVy32AP/A2+KI+JhmsxnactSptkAWGyAAf1YBWW\nJs2sc9OJdKj7uIkzszCx7c7VIVeF/VLijIYpM/zwUgir5S5SimzQmY+FumwbKIml\nK5RBsoSog22i7Edho0MLa1pa6qvnKS0nkl9DEcu8EbMUhucWbxGnCG/22EEMTrY+\nSi1IZNkDGtlBHHBKMC+STbqqTxtdy4tAd2NYwWh3sBIh6PF7T4NLRAugu7PZQr5K\namS4z2lV3ebshGjieA0Zoznwh0AXgN0gZ/0pC/LXI25gcgtrvkCyL8Fe0AyZUMd8\nUvZXaRSsm3SkCUIlGjPrvuItn1D7tHmqVSCDKXDM2TqjfiRm1JF+2OFCBNvGz19V\nLxWd/Gf+0qw0dtKxRMKzGh0mxXY40hjtmYZulrPxhG5itNDjStovgrevM1HBsXs9\nikrkOGQ0pFcqizTn4ZKAmMozEMuIuV89Vof2bBCg7pHT1FmXVdAaYJxb6a7A/CgN\nqHjoh8AxBiGw/Q2NM4YJlUVhHqqd+/lUG3WJqACNEnqSlZkYQ3HqNNaKhHVbD4mN\nq/g6v+f8aWWDZDsI6IAfbJUB+KPEnIvQJQleWuHrq7kcUMhEq3dwBMIoTVEHhUUr\nRQKToSEM1rN7PcanaXQM2gy141dS7tFLxhapG8ug75LkIUnEOpPMtUjvrU1ZELGq\n36vVHBB+dTDg\n=tJCw\n-----END PGP PUBLIC KEY BLOCK-----\n", + "check_gpg": true, + "rhsm": false + }, + { + "name": "appstream", + "baseurl": "https://repo.almalinux.org/almalinux/10.0/AppStream/ppc64le/os/", + "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGaP6O8BEACvg8IlAxGayV8zOi9Ex+Pd8lrj2BrBzloG8ri84ORp9o8ojq7l\nykKmIElHe11cQD2Lf/a4lcQQ4Ec3baiD786X6K2eVSlBEAnZMzfjDg8R63SfsBuu\n8Yk+lUyqlBrDnSDYaPruOAzLIz2r82ikIC1jDbipZsMFPFHPI4/hayyWxJ3oGxRe\n0mbtYLB9ElEKngt+/hfo7JLklakbznyIRuVEF3VrZb91XC6r/idqfJoNyBXSKidj\nz0IwqOhgkLUk84rzltDo3AzwGqusd7PEuhOmqinOhp0hMdXsztD4TVyhw82iXu/O\nonOAObZTZYfM6Z8btmDqkoo0aT+oPPCuZ3yC/caU9dhvCSXET/CGoXc3hL55u9PV\nqmcVm/mwvuEImEAvxVc0/dBzEUk+FwW8KsaN3HoUKrC4/NqgmaQz8/42np7u2j+B\nOOJ4hAckNEdWd8rB86CYN00sdxnvLBsp8V3IwEqXLhGOoBsagy61Z8hKCM+siOGn\nxmbbybgaLOs+DPlxt9LrtgLJHODwmD96oysUPJuA0lv8KMiSpId0tSpp9Wn/wHBG\nkRgxGYfzQu7WRvRZqQaleft1JTXXOjNzPur0RkJyb3yFwAoxpePyo/WrupM41OHW\n58cEqdC6riCnJcS4U84RLj+hwvufBVB7areQ75sETnKeyozZW+P16E1t/wARAQAB\ntChBbG1hTGludXggT1MgMTAgPHBhY2thZ2VyQGFsbWFsaW51eC5vcmc+iQJMBBMB\nCgA2FiEE7m23uY9b9e3Z2g3l3uXBHMKh5XIFAmaP6O8CGwMECwkIBwQVCgkIBRYC\nAwEAAh4FAheAAAoJEN7lwRzCoeVy32AP/A2+KI+JhmsxnactSptkAWGyAAf1YBWW\nJs2sc9OJdKj7uIkzszCx7c7VIVeF/VLijIYpM/zwUgir5S5SimzQmY+FumwbKIml\nK5RBsoSog22i7Edho0MLa1pa6qvnKS0nkl9DEcu8EbMUhucWbxGnCG/22EEMTrY+\nSi1IZNkDGtlBHHBKMC+STbqqTxtdy4tAd2NYwWh3sBIh6PF7T4NLRAugu7PZQr5K\namS4z2lV3ebshGjieA0Zoznwh0AXgN0gZ/0pC/LXI25gcgtrvkCyL8Fe0AyZUMd8\nUvZXaRSsm3SkCUIlGjPrvuItn1D7tHmqVSCDKXDM2TqjfiRm1JF+2OFCBNvGz19V\nLxWd/Gf+0qw0dtKxRMKzGh0mxXY40hjtmYZulrPxhG5itNDjStovgrevM1HBsXs9\nikrkOGQ0pFcqizTn4ZKAmMozEMuIuV89Vof2bBCg7pHT1FmXVdAaYJxb6a7A/CgN\nqHjoh8AxBiGw/Q2NM4YJlUVhHqqd+/lUG3WJqACNEnqSlZkYQ3HqNNaKhHVbD4mN\nq/g6v+f8aWWDZDsI6IAfbJUB+KPEnIvQJQleWuHrq7kcUMhEq3dwBMIoTVEHhUUr\nRQKToSEM1rN7PcanaXQM2gy141dS7tFLxhapG8ug75LkIUnEOpPMtUjvrU1ZELGq\n36vVHBB+dTDg\n=tJCw\n-----END PGP PUBLIC KEY BLOCK-----\n", + "check_gpg": true, + "rhsm": false + } + ], + "s390x": [ + { + "name": "baseos", + "baseurl": "https://repo.almalinux.org/almalinux/10.0/BaseOS/s390x/os/", + "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGaP6O8BEACvg8IlAxGayV8zOi9Ex+Pd8lrj2BrBzloG8ri84ORp9o8ojq7l\nykKmIElHe11cQD2Lf/a4lcQQ4Ec3baiD786X6K2eVSlBEAnZMzfjDg8R63SfsBuu\n8Yk+lUyqlBrDnSDYaPruOAzLIz2r82ikIC1jDbipZsMFPFHPI4/hayyWxJ3oGxRe\n0mbtYLB9ElEKngt+/hfo7JLklakbznyIRuVEF3VrZb91XC6r/idqfJoNyBXSKidj\nz0IwqOhgkLUk84rzltDo3AzwGqusd7PEuhOmqinOhp0hMdXsztD4TVyhw82iXu/O\nonOAObZTZYfM6Z8btmDqkoo0aT+oPPCuZ3yC/caU9dhvCSXET/CGoXc3hL55u9PV\nqmcVm/mwvuEImEAvxVc0/dBzEUk+FwW8KsaN3HoUKrC4/NqgmaQz8/42np7u2j+B\nOOJ4hAckNEdWd8rB86CYN00sdxnvLBsp8V3IwEqXLhGOoBsagy61Z8hKCM+siOGn\nxmbbybgaLOs+DPlxt9LrtgLJHODwmD96oysUPJuA0lv8KMiSpId0tSpp9Wn/wHBG\nkRgxGYfzQu7WRvRZqQaleft1JTXXOjNzPur0RkJyb3yFwAoxpePyo/WrupM41OHW\n58cEqdC6riCnJcS4U84RLj+hwvufBVB7areQ75sETnKeyozZW+P16E1t/wARAQAB\ntChBbG1hTGludXggT1MgMTAgPHBhY2thZ2VyQGFsbWFsaW51eC5vcmc+iQJMBBMB\nCgA2FiEE7m23uY9b9e3Z2g3l3uXBHMKh5XIFAmaP6O8CGwMECwkIBwQVCgkIBRYC\nAwEAAh4FAheAAAoJEN7lwRzCoeVy32AP/A2+KI+JhmsxnactSptkAWGyAAf1YBWW\nJs2sc9OJdKj7uIkzszCx7c7VIVeF/VLijIYpM/zwUgir5S5SimzQmY+FumwbKIml\nK5RBsoSog22i7Edho0MLa1pa6qvnKS0nkl9DEcu8EbMUhucWbxGnCG/22EEMTrY+\nSi1IZNkDGtlBHHBKMC+STbqqTxtdy4tAd2NYwWh3sBIh6PF7T4NLRAugu7PZQr5K\namS4z2lV3ebshGjieA0Zoznwh0AXgN0gZ/0pC/LXI25gcgtrvkCyL8Fe0AyZUMd8\nUvZXaRSsm3SkCUIlGjPrvuItn1D7tHmqVSCDKXDM2TqjfiRm1JF+2OFCBNvGz19V\nLxWd/Gf+0qw0dtKxRMKzGh0mxXY40hjtmYZulrPxhG5itNDjStovgrevM1HBsXs9\nikrkOGQ0pFcqizTn4ZKAmMozEMuIuV89Vof2bBCg7pHT1FmXVdAaYJxb6a7A/CgN\nqHjoh8AxBiGw/Q2NM4YJlUVhHqqd+/lUG3WJqACNEnqSlZkYQ3HqNNaKhHVbD4mN\nq/g6v+f8aWWDZDsI6IAfbJUB+KPEnIvQJQleWuHrq7kcUMhEq3dwBMIoTVEHhUUr\nRQKToSEM1rN7PcanaXQM2gy141dS7tFLxhapG8ug75LkIUnEOpPMtUjvrU1ZELGq\n36vVHBB+dTDg\n=tJCw\n-----END PGP PUBLIC KEY BLOCK-----\n", + "check_gpg": true, + "rhsm": false + }, + { + "name": "appstream", + "baseurl": "https://repo.almalinux.org/almalinux/10.0/AppStream/s390x/os/", + "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGaP6O8BEACvg8IlAxGayV8zOi9Ex+Pd8lrj2BrBzloG8ri84ORp9o8ojq7l\nykKmIElHe11cQD2Lf/a4lcQQ4Ec3baiD786X6K2eVSlBEAnZMzfjDg8R63SfsBuu\n8Yk+lUyqlBrDnSDYaPruOAzLIz2r82ikIC1jDbipZsMFPFHPI4/hayyWxJ3oGxRe\n0mbtYLB9ElEKngt+/hfo7JLklakbznyIRuVEF3VrZb91XC6r/idqfJoNyBXSKidj\nz0IwqOhgkLUk84rzltDo3AzwGqusd7PEuhOmqinOhp0hMdXsztD4TVyhw82iXu/O\nonOAObZTZYfM6Z8btmDqkoo0aT+oPPCuZ3yC/caU9dhvCSXET/CGoXc3hL55u9PV\nqmcVm/mwvuEImEAvxVc0/dBzEUk+FwW8KsaN3HoUKrC4/NqgmaQz8/42np7u2j+B\nOOJ4hAckNEdWd8rB86CYN00sdxnvLBsp8V3IwEqXLhGOoBsagy61Z8hKCM+siOGn\nxmbbybgaLOs+DPlxt9LrtgLJHODwmD96oysUPJuA0lv8KMiSpId0tSpp9Wn/wHBG\nkRgxGYfzQu7WRvRZqQaleft1JTXXOjNzPur0RkJyb3yFwAoxpePyo/WrupM41OHW\n58cEqdC6riCnJcS4U84RLj+hwvufBVB7areQ75sETnKeyozZW+P16E1t/wARAQAB\ntChBbG1hTGludXggT1MgMTAgPHBhY2thZ2VyQGFsbWFsaW51eC5vcmc+iQJMBBMB\nCgA2FiEE7m23uY9b9e3Z2g3l3uXBHMKh5XIFAmaP6O8CGwMECwkIBwQVCgkIBRYC\nAwEAAh4FAheAAAoJEN7lwRzCoeVy32AP/A2+KI+JhmsxnactSptkAWGyAAf1YBWW\nJs2sc9OJdKj7uIkzszCx7c7VIVeF/VLijIYpM/zwUgir5S5SimzQmY+FumwbKIml\nK5RBsoSog22i7Edho0MLa1pa6qvnKS0nkl9DEcu8EbMUhucWbxGnCG/22EEMTrY+\nSi1IZNkDGtlBHHBKMC+STbqqTxtdy4tAd2NYwWh3sBIh6PF7T4NLRAugu7PZQr5K\namS4z2lV3ebshGjieA0Zoznwh0AXgN0gZ/0pC/LXI25gcgtrvkCyL8Fe0AyZUMd8\nUvZXaRSsm3SkCUIlGjPrvuItn1D7tHmqVSCDKXDM2TqjfiRm1JF+2OFCBNvGz19V\nLxWd/Gf+0qw0dtKxRMKzGh0mxXY40hjtmYZulrPxhG5itNDjStovgrevM1HBsXs9\nikrkOGQ0pFcqizTn4ZKAmMozEMuIuV89Vof2bBCg7pHT1FmXVdAaYJxb6a7A/CgN\nqHjoh8AxBiGw/Q2NM4YJlUVhHqqd+/lUG3WJqACNEnqSlZkYQ3HqNNaKhHVbD4mN\nq/g6v+f8aWWDZDsI6IAfbJUB+KPEnIvQJQleWuHrq7kcUMhEq3dwBMIoTVEHhUUr\nRQKToSEM1rN7PcanaXQM2gy141dS7tFLxhapG8ug75LkIUnEOpPMtUjvrU1ZELGq\n36vVHBB+dTDg\n=tJCw\n-----END PGP PUBLIC KEY BLOCK-----\n", + "check_gpg": true, + "rhsm": false + } + ], + "x86_64": [ + { + "name": "baseos", + "baseurl": "https://repo.almalinux.org/almalinux/10.0/BaseOS/x86_64/os/", + "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGaP6O8BEACvg8IlAxGayV8zOi9Ex+Pd8lrj2BrBzloG8ri84ORp9o8ojq7l\nykKmIElHe11cQD2Lf/a4lcQQ4Ec3baiD786X6K2eVSlBEAnZMzfjDg8R63SfsBuu\n8Yk+lUyqlBrDnSDYaPruOAzLIz2r82ikIC1jDbipZsMFPFHPI4/hayyWxJ3oGxRe\n0mbtYLB9ElEKngt+/hfo7JLklakbznyIRuVEF3VrZb91XC6r/idqfJoNyBXSKidj\nz0IwqOhgkLUk84rzltDo3AzwGqusd7PEuhOmqinOhp0hMdXsztD4TVyhw82iXu/O\nonOAObZTZYfM6Z8btmDqkoo0aT+oPPCuZ3yC/caU9dhvCSXET/CGoXc3hL55u9PV\nqmcVm/mwvuEImEAvxVc0/dBzEUk+FwW8KsaN3HoUKrC4/NqgmaQz8/42np7u2j+B\nOOJ4hAckNEdWd8rB86CYN00sdxnvLBsp8V3IwEqXLhGOoBsagy61Z8hKCM+siOGn\nxmbbybgaLOs+DPlxt9LrtgLJHODwmD96oysUPJuA0lv8KMiSpId0tSpp9Wn/wHBG\nkRgxGYfzQu7WRvRZqQaleft1JTXXOjNzPur0RkJyb3yFwAoxpePyo/WrupM41OHW\n58cEqdC6riCnJcS4U84RLj+hwvufBVB7areQ75sETnKeyozZW+P16E1t/wARAQAB\ntChBbG1hTGludXggT1MgMTAgPHBhY2thZ2VyQGFsbWFsaW51eC5vcmc+iQJMBBMB\nCgA2FiEE7m23uY9b9e3Z2g3l3uXBHMKh5XIFAmaP6O8CGwMECwkIBwQVCgkIBRYC\nAwEAAh4FAheAAAoJEN7lwRzCoeVy32AP/A2+KI+JhmsxnactSptkAWGyAAf1YBWW\nJs2sc9OJdKj7uIkzszCx7c7VIVeF/VLijIYpM/zwUgir5S5SimzQmY+FumwbKIml\nK5RBsoSog22i7Edho0MLa1pa6qvnKS0nkl9DEcu8EbMUhucWbxGnCG/22EEMTrY+\nSi1IZNkDGtlBHHBKMC+STbqqTxtdy4tAd2NYwWh3sBIh6PF7T4NLRAugu7PZQr5K\namS4z2lV3ebshGjieA0Zoznwh0AXgN0gZ/0pC/LXI25gcgtrvkCyL8Fe0AyZUMd8\nUvZXaRSsm3SkCUIlGjPrvuItn1D7tHmqVSCDKXDM2TqjfiRm1JF+2OFCBNvGz19V\nLxWd/Gf+0qw0dtKxRMKzGh0mxXY40hjtmYZulrPxhG5itNDjStovgrevM1HBsXs9\nikrkOGQ0pFcqizTn4ZKAmMozEMuIuV89Vof2bBCg7pHT1FmXVdAaYJxb6a7A/CgN\nqHjoh8AxBiGw/Q2NM4YJlUVhHqqd+/lUG3WJqACNEnqSlZkYQ3HqNNaKhHVbD4mN\nq/g6v+f8aWWDZDsI6IAfbJUB+KPEnIvQJQleWuHrq7kcUMhEq3dwBMIoTVEHhUUr\nRQKToSEM1rN7PcanaXQM2gy141dS7tFLxhapG8ug75LkIUnEOpPMtUjvrU1ZELGq\n36vVHBB+dTDg\n=tJCw\n-----END PGP PUBLIC KEY BLOCK-----\n", + "check_gpg": true, + "rhsm": false + }, + { + "name": "appstream", + "baseurl": "https://repo.almalinux.org/almalinux/10.0/AppStream/x86_64/os/", + "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGaP6O8BEACvg8IlAxGayV8zOi9Ex+Pd8lrj2BrBzloG8ri84ORp9o8ojq7l\nykKmIElHe11cQD2Lf/a4lcQQ4Ec3baiD786X6K2eVSlBEAnZMzfjDg8R63SfsBuu\n8Yk+lUyqlBrDnSDYaPruOAzLIz2r82ikIC1jDbipZsMFPFHPI4/hayyWxJ3oGxRe\n0mbtYLB9ElEKngt+/hfo7JLklakbznyIRuVEF3VrZb91XC6r/idqfJoNyBXSKidj\nz0IwqOhgkLUk84rzltDo3AzwGqusd7PEuhOmqinOhp0hMdXsztD4TVyhw82iXu/O\nonOAObZTZYfM6Z8btmDqkoo0aT+oPPCuZ3yC/caU9dhvCSXET/CGoXc3hL55u9PV\nqmcVm/mwvuEImEAvxVc0/dBzEUk+FwW8KsaN3HoUKrC4/NqgmaQz8/42np7u2j+B\nOOJ4hAckNEdWd8rB86CYN00sdxnvLBsp8V3IwEqXLhGOoBsagy61Z8hKCM+siOGn\nxmbbybgaLOs+DPlxt9LrtgLJHODwmD96oysUPJuA0lv8KMiSpId0tSpp9Wn/wHBG\nkRgxGYfzQu7WRvRZqQaleft1JTXXOjNzPur0RkJyb3yFwAoxpePyo/WrupM41OHW\n58cEqdC6riCnJcS4U84RLj+hwvufBVB7areQ75sETnKeyozZW+P16E1t/wARAQAB\ntChBbG1hTGludXggT1MgMTAgPHBhY2thZ2VyQGFsbWFsaW51eC5vcmc+iQJMBBMB\nCgA2FiEE7m23uY9b9e3Z2g3l3uXBHMKh5XIFAmaP6O8CGwMECwkIBwQVCgkIBRYC\nAwEAAh4FAheAAAoJEN7lwRzCoeVy32AP/A2+KI+JhmsxnactSptkAWGyAAf1YBWW\nJs2sc9OJdKj7uIkzszCx7c7VIVeF/VLijIYpM/zwUgir5S5SimzQmY+FumwbKIml\nK5RBsoSog22i7Edho0MLa1pa6qvnKS0nkl9DEcu8EbMUhucWbxGnCG/22EEMTrY+\nSi1IZNkDGtlBHHBKMC+STbqqTxtdy4tAd2NYwWh3sBIh6PF7T4NLRAugu7PZQr5K\namS4z2lV3ebshGjieA0Zoznwh0AXgN0gZ/0pC/LXI25gcgtrvkCyL8Fe0AyZUMd8\nUvZXaRSsm3SkCUIlGjPrvuItn1D7tHmqVSCDKXDM2TqjfiRm1JF+2OFCBNvGz19V\nLxWd/Gf+0qw0dtKxRMKzGh0mxXY40hjtmYZulrPxhG5itNDjStovgrevM1HBsXs9\nikrkOGQ0pFcqizTn4ZKAmMozEMuIuV89Vof2bBCg7pHT1FmXVdAaYJxb6a7A/CgN\nqHjoh8AxBiGw/Q2NM4YJlUVhHqqd+/lUG3WJqACNEnqSlZkYQ3HqNNaKhHVbD4mN\nq/g6v+f8aWWDZDsI6IAfbJUB+KPEnIvQJQleWuHrq7kcUMhEq3dwBMIoTVEHhUUr\nRQKToSEM1rN7PcanaXQM2gy141dS7tFLxhapG8ug75LkIUnEOpPMtUjvrU1ZELGq\n36vVHBB+dTDg\n=tJCw\n-----END PGP PUBLIC KEY BLOCK-----\n", + "check_gpg": true, + "rhsm": false + } + ] +} diff --git a/vendor/github.com/osbuild/images/data/repositories/almalinux-10.json b/vendor/github.com/osbuild/images/data/repositories/almalinux-10.json new file mode 100644 index 000000000..da6110cc4 --- /dev/null +++ b/vendor/github.com/osbuild/images/data/repositories/almalinux-10.json @@ -0,0 +1,66 @@ +{ + "aarch64": [ + { + "name": "baseos", + "baseurl": "https://repo.almalinux.org/almalinux/10/BaseOS/aarch64/os/", + "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGaP6O8BEACvg8IlAxGayV8zOi9Ex+Pd8lrj2BrBzloG8ri84ORp9o8ojq7l\nykKmIElHe11cQD2Lf/a4lcQQ4Ec3baiD786X6K2eVSlBEAnZMzfjDg8R63SfsBuu\n8Yk+lUyqlBrDnSDYaPruOAzLIz2r82ikIC1jDbipZsMFPFHPI4/hayyWxJ3oGxRe\n0mbtYLB9ElEKngt+/hfo7JLklakbznyIRuVEF3VrZb91XC6r/idqfJoNyBXSKidj\nz0IwqOhgkLUk84rzltDo3AzwGqusd7PEuhOmqinOhp0hMdXsztD4TVyhw82iXu/O\nonOAObZTZYfM6Z8btmDqkoo0aT+oPPCuZ3yC/caU9dhvCSXET/CGoXc3hL55u9PV\nqmcVm/mwvuEImEAvxVc0/dBzEUk+FwW8KsaN3HoUKrC4/NqgmaQz8/42np7u2j+B\nOOJ4hAckNEdWd8rB86CYN00sdxnvLBsp8V3IwEqXLhGOoBsagy61Z8hKCM+siOGn\nxmbbybgaLOs+DPlxt9LrtgLJHODwmD96oysUPJuA0lv8KMiSpId0tSpp9Wn/wHBG\nkRgxGYfzQu7WRvRZqQaleft1JTXXOjNzPur0RkJyb3yFwAoxpePyo/WrupM41OHW\n58cEqdC6riCnJcS4U84RLj+hwvufBVB7areQ75sETnKeyozZW+P16E1t/wARAQAB\ntChBbG1hTGludXggT1MgMTAgPHBhY2thZ2VyQGFsbWFsaW51eC5vcmc+iQJMBBMB\nCgA2FiEE7m23uY9b9e3Z2g3l3uXBHMKh5XIFAmaP6O8CGwMECwkIBwQVCgkIBRYC\nAwEAAh4FAheAAAoJEN7lwRzCoeVy32AP/A2+KI+JhmsxnactSptkAWGyAAf1YBWW\nJs2sc9OJdKj7uIkzszCx7c7VIVeF/VLijIYpM/zwUgir5S5SimzQmY+FumwbKIml\nK5RBsoSog22i7Edho0MLa1pa6qvnKS0nkl9DEcu8EbMUhucWbxGnCG/22EEMTrY+\nSi1IZNkDGtlBHHBKMC+STbqqTxtdy4tAd2NYwWh3sBIh6PF7T4NLRAugu7PZQr5K\namS4z2lV3ebshGjieA0Zoznwh0AXgN0gZ/0pC/LXI25gcgtrvkCyL8Fe0AyZUMd8\nUvZXaRSsm3SkCUIlGjPrvuItn1D7tHmqVSCDKXDM2TqjfiRm1JF+2OFCBNvGz19V\nLxWd/Gf+0qw0dtKxRMKzGh0mxXY40hjtmYZulrPxhG5itNDjStovgrevM1HBsXs9\nikrkOGQ0pFcqizTn4ZKAmMozEMuIuV89Vof2bBCg7pHT1FmXVdAaYJxb6a7A/CgN\nqHjoh8AxBiGw/Q2NM4YJlUVhHqqd+/lUG3WJqACNEnqSlZkYQ3HqNNaKhHVbD4mN\nq/g6v+f8aWWDZDsI6IAfbJUB+KPEnIvQJQleWuHrq7kcUMhEq3dwBMIoTVEHhUUr\nRQKToSEM1rN7PcanaXQM2gy141dS7tFLxhapG8ug75LkIUnEOpPMtUjvrU1ZELGq\n36vVHBB+dTDg\n=tJCw\n-----END PGP PUBLIC KEY BLOCK-----\n", + "check_gpg": true, + "rhsm": false + }, + { + "name": "appstream", + "baseurl": "https://repo.almalinux.org/almalinux/10/AppStream/aarch64/os/", + "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGaP6O8BEACvg8IlAxGayV8zOi9Ex+Pd8lrj2BrBzloG8ri84ORp9o8ojq7l\nykKmIElHe11cQD2Lf/a4lcQQ4Ec3baiD786X6K2eVSlBEAnZMzfjDg8R63SfsBuu\n8Yk+lUyqlBrDnSDYaPruOAzLIz2r82ikIC1jDbipZsMFPFHPI4/hayyWxJ3oGxRe\n0mbtYLB9ElEKngt+/hfo7JLklakbznyIRuVEF3VrZb91XC6r/idqfJoNyBXSKidj\nz0IwqOhgkLUk84rzltDo3AzwGqusd7PEuhOmqinOhp0hMdXsztD4TVyhw82iXu/O\nonOAObZTZYfM6Z8btmDqkoo0aT+oPPCuZ3yC/caU9dhvCSXET/CGoXc3hL55u9PV\nqmcVm/mwvuEImEAvxVc0/dBzEUk+FwW8KsaN3HoUKrC4/NqgmaQz8/42np7u2j+B\nOOJ4hAckNEdWd8rB86CYN00sdxnvLBsp8V3IwEqXLhGOoBsagy61Z8hKCM+siOGn\nxmbbybgaLOs+DPlxt9LrtgLJHODwmD96oysUPJuA0lv8KMiSpId0tSpp9Wn/wHBG\nkRgxGYfzQu7WRvRZqQaleft1JTXXOjNzPur0RkJyb3yFwAoxpePyo/WrupM41OHW\n58cEqdC6riCnJcS4U84RLj+hwvufBVB7areQ75sETnKeyozZW+P16E1t/wARAQAB\ntChBbG1hTGludXggT1MgMTAgPHBhY2thZ2VyQGFsbWFsaW51eC5vcmc+iQJMBBMB\nCgA2FiEE7m23uY9b9e3Z2g3l3uXBHMKh5XIFAmaP6O8CGwMECwkIBwQVCgkIBRYC\nAwEAAh4FAheAAAoJEN7lwRzCoeVy32AP/A2+KI+JhmsxnactSptkAWGyAAf1YBWW\nJs2sc9OJdKj7uIkzszCx7c7VIVeF/VLijIYpM/zwUgir5S5SimzQmY+FumwbKIml\nK5RBsoSog22i7Edho0MLa1pa6qvnKS0nkl9DEcu8EbMUhucWbxGnCG/22EEMTrY+\nSi1IZNkDGtlBHHBKMC+STbqqTxtdy4tAd2NYwWh3sBIh6PF7T4NLRAugu7PZQr5K\namS4z2lV3ebshGjieA0Zoznwh0AXgN0gZ/0pC/LXI25gcgtrvkCyL8Fe0AyZUMd8\nUvZXaRSsm3SkCUIlGjPrvuItn1D7tHmqVSCDKXDM2TqjfiRm1JF+2OFCBNvGz19V\nLxWd/Gf+0qw0dtKxRMKzGh0mxXY40hjtmYZulrPxhG5itNDjStovgrevM1HBsXs9\nikrkOGQ0pFcqizTn4ZKAmMozEMuIuV89Vof2bBCg7pHT1FmXVdAaYJxb6a7A/CgN\nqHjoh8AxBiGw/Q2NM4YJlUVhHqqd+/lUG3WJqACNEnqSlZkYQ3HqNNaKhHVbD4mN\nq/g6v+f8aWWDZDsI6IAfbJUB+KPEnIvQJQleWuHrq7kcUMhEq3dwBMIoTVEHhUUr\nRQKToSEM1rN7PcanaXQM2gy141dS7tFLxhapG8ug75LkIUnEOpPMtUjvrU1ZELGq\n36vVHBB+dTDg\n=tJCw\n-----END PGP PUBLIC KEY BLOCK-----\n", + "check_gpg": true, + "rhsm": false + } + ], + "ppc64le": [ + { + "name": "baseos", + "baseurl": "https://repo.almalinux.org/almalinux/10/BaseOS/ppc64le/os/", + "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGaP6O8BEACvg8IlAxGayV8zOi9Ex+Pd8lrj2BrBzloG8ri84ORp9o8ojq7l\nykKmIElHe11cQD2Lf/a4lcQQ4Ec3baiD786X6K2eVSlBEAnZMzfjDg8R63SfsBuu\n8Yk+lUyqlBrDnSDYaPruOAzLIz2r82ikIC1jDbipZsMFPFHPI4/hayyWxJ3oGxRe\n0mbtYLB9ElEKngt+/hfo7JLklakbznyIRuVEF3VrZb91XC6r/idqfJoNyBXSKidj\nz0IwqOhgkLUk84rzltDo3AzwGqusd7PEuhOmqinOhp0hMdXsztD4TVyhw82iXu/O\nonOAObZTZYfM6Z8btmDqkoo0aT+oPPCuZ3yC/caU9dhvCSXET/CGoXc3hL55u9PV\nqmcVm/mwvuEImEAvxVc0/dBzEUk+FwW8KsaN3HoUKrC4/NqgmaQz8/42np7u2j+B\nOOJ4hAckNEdWd8rB86CYN00sdxnvLBsp8V3IwEqXLhGOoBsagy61Z8hKCM+siOGn\nxmbbybgaLOs+DPlxt9LrtgLJHODwmD96oysUPJuA0lv8KMiSpId0tSpp9Wn/wHBG\nkRgxGYfzQu7WRvRZqQaleft1JTXXOjNzPur0RkJyb3yFwAoxpePyo/WrupM41OHW\n58cEqdC6riCnJcS4U84RLj+hwvufBVB7areQ75sETnKeyozZW+P16E1t/wARAQAB\ntChBbG1hTGludXggT1MgMTAgPHBhY2thZ2VyQGFsbWFsaW51eC5vcmc+iQJMBBMB\nCgA2FiEE7m23uY9b9e3Z2g3l3uXBHMKh5XIFAmaP6O8CGwMECwkIBwQVCgkIBRYC\nAwEAAh4FAheAAAoJEN7lwRzCoeVy32AP/A2+KI+JhmsxnactSptkAWGyAAf1YBWW\nJs2sc9OJdKj7uIkzszCx7c7VIVeF/VLijIYpM/zwUgir5S5SimzQmY+FumwbKIml\nK5RBsoSog22i7Edho0MLa1pa6qvnKS0nkl9DEcu8EbMUhucWbxGnCG/22EEMTrY+\nSi1IZNkDGtlBHHBKMC+STbqqTxtdy4tAd2NYwWh3sBIh6PF7T4NLRAugu7PZQr5K\namS4z2lV3ebshGjieA0Zoznwh0AXgN0gZ/0pC/LXI25gcgtrvkCyL8Fe0AyZUMd8\nUvZXaRSsm3SkCUIlGjPrvuItn1D7tHmqVSCDKXDM2TqjfiRm1JF+2OFCBNvGz19V\nLxWd/Gf+0qw0dtKxRMKzGh0mxXY40hjtmYZulrPxhG5itNDjStovgrevM1HBsXs9\nikrkOGQ0pFcqizTn4ZKAmMozEMuIuV89Vof2bBCg7pHT1FmXVdAaYJxb6a7A/CgN\nqHjoh8AxBiGw/Q2NM4YJlUVhHqqd+/lUG3WJqACNEnqSlZkYQ3HqNNaKhHVbD4mN\nq/g6v+f8aWWDZDsI6IAfbJUB+KPEnIvQJQleWuHrq7kcUMhEq3dwBMIoTVEHhUUr\nRQKToSEM1rN7PcanaXQM2gy141dS7tFLxhapG8ug75LkIUnEOpPMtUjvrU1ZELGq\n36vVHBB+dTDg\n=tJCw\n-----END PGP PUBLIC KEY BLOCK-----\n", + "check_gpg": true, + "rhsm": false + }, + { + "name": "appstream", + "baseurl": "https://repo.almalinux.org/almalinux/10/AppStream/ppc64le/os/", + "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGaP6O8BEACvg8IlAxGayV8zOi9Ex+Pd8lrj2BrBzloG8ri84ORp9o8ojq7l\nykKmIElHe11cQD2Lf/a4lcQQ4Ec3baiD786X6K2eVSlBEAnZMzfjDg8R63SfsBuu\n8Yk+lUyqlBrDnSDYaPruOAzLIz2r82ikIC1jDbipZsMFPFHPI4/hayyWxJ3oGxRe\n0mbtYLB9ElEKngt+/hfo7JLklakbznyIRuVEF3VrZb91XC6r/idqfJoNyBXSKidj\nz0IwqOhgkLUk84rzltDo3AzwGqusd7PEuhOmqinOhp0hMdXsztD4TVyhw82iXu/O\nonOAObZTZYfM6Z8btmDqkoo0aT+oPPCuZ3yC/caU9dhvCSXET/CGoXc3hL55u9PV\nqmcVm/mwvuEImEAvxVc0/dBzEUk+FwW8KsaN3HoUKrC4/NqgmaQz8/42np7u2j+B\nOOJ4hAckNEdWd8rB86CYN00sdxnvLBsp8V3IwEqXLhGOoBsagy61Z8hKCM+siOGn\nxmbbybgaLOs+DPlxt9LrtgLJHODwmD96oysUPJuA0lv8KMiSpId0tSpp9Wn/wHBG\nkRgxGYfzQu7WRvRZqQaleft1JTXXOjNzPur0RkJyb3yFwAoxpePyo/WrupM41OHW\n58cEqdC6riCnJcS4U84RLj+hwvufBVB7areQ75sETnKeyozZW+P16E1t/wARAQAB\ntChBbG1hTGludXggT1MgMTAgPHBhY2thZ2VyQGFsbWFsaW51eC5vcmc+iQJMBBMB\nCgA2FiEE7m23uY9b9e3Z2g3l3uXBHMKh5XIFAmaP6O8CGwMECwkIBwQVCgkIBRYC\nAwEAAh4FAheAAAoJEN7lwRzCoeVy32AP/A2+KI+JhmsxnactSptkAWGyAAf1YBWW\nJs2sc9OJdKj7uIkzszCx7c7VIVeF/VLijIYpM/zwUgir5S5SimzQmY+FumwbKIml\nK5RBsoSog22i7Edho0MLa1pa6qvnKS0nkl9DEcu8EbMUhucWbxGnCG/22EEMTrY+\nSi1IZNkDGtlBHHBKMC+STbqqTxtdy4tAd2NYwWh3sBIh6PF7T4NLRAugu7PZQr5K\namS4z2lV3ebshGjieA0Zoznwh0AXgN0gZ/0pC/LXI25gcgtrvkCyL8Fe0AyZUMd8\nUvZXaRSsm3SkCUIlGjPrvuItn1D7tHmqVSCDKXDM2TqjfiRm1JF+2OFCBNvGz19V\nLxWd/Gf+0qw0dtKxRMKzGh0mxXY40hjtmYZulrPxhG5itNDjStovgrevM1HBsXs9\nikrkOGQ0pFcqizTn4ZKAmMozEMuIuV89Vof2bBCg7pHT1FmXVdAaYJxb6a7A/CgN\nqHjoh8AxBiGw/Q2NM4YJlUVhHqqd+/lUG3WJqACNEnqSlZkYQ3HqNNaKhHVbD4mN\nq/g6v+f8aWWDZDsI6IAfbJUB+KPEnIvQJQleWuHrq7kcUMhEq3dwBMIoTVEHhUUr\nRQKToSEM1rN7PcanaXQM2gy141dS7tFLxhapG8ug75LkIUnEOpPMtUjvrU1ZELGq\n36vVHBB+dTDg\n=tJCw\n-----END PGP PUBLIC KEY BLOCK-----\n", + "check_gpg": true, + "rhsm": false + } + ], + "s390x": [ + { + "name": "baseos", + "baseurl": "https://repo.almalinux.org/almalinux/10/BaseOS/s390x/os/", + "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGaP6O8BEACvg8IlAxGayV8zOi9Ex+Pd8lrj2BrBzloG8ri84ORp9o8ojq7l\nykKmIElHe11cQD2Lf/a4lcQQ4Ec3baiD786X6K2eVSlBEAnZMzfjDg8R63SfsBuu\n8Yk+lUyqlBrDnSDYaPruOAzLIz2r82ikIC1jDbipZsMFPFHPI4/hayyWxJ3oGxRe\n0mbtYLB9ElEKngt+/hfo7JLklakbznyIRuVEF3VrZb91XC6r/idqfJoNyBXSKidj\nz0IwqOhgkLUk84rzltDo3AzwGqusd7PEuhOmqinOhp0hMdXsztD4TVyhw82iXu/O\nonOAObZTZYfM6Z8btmDqkoo0aT+oPPCuZ3yC/caU9dhvCSXET/CGoXc3hL55u9PV\nqmcVm/mwvuEImEAvxVc0/dBzEUk+FwW8KsaN3HoUKrC4/NqgmaQz8/42np7u2j+B\nOOJ4hAckNEdWd8rB86CYN00sdxnvLBsp8V3IwEqXLhGOoBsagy61Z8hKCM+siOGn\nxmbbybgaLOs+DPlxt9LrtgLJHODwmD96oysUPJuA0lv8KMiSpId0tSpp9Wn/wHBG\nkRgxGYfzQu7WRvRZqQaleft1JTXXOjNzPur0RkJyb3yFwAoxpePyo/WrupM41OHW\n58cEqdC6riCnJcS4U84RLj+hwvufBVB7areQ75sETnKeyozZW+P16E1t/wARAQAB\ntChBbG1hTGludXggT1MgMTAgPHBhY2thZ2VyQGFsbWFsaW51eC5vcmc+iQJMBBMB\nCgA2FiEE7m23uY9b9e3Z2g3l3uXBHMKh5XIFAmaP6O8CGwMECwkIBwQVCgkIBRYC\nAwEAAh4FAheAAAoJEN7lwRzCoeVy32AP/A2+KI+JhmsxnactSptkAWGyAAf1YBWW\nJs2sc9OJdKj7uIkzszCx7c7VIVeF/VLijIYpM/zwUgir5S5SimzQmY+FumwbKIml\nK5RBsoSog22i7Edho0MLa1pa6qvnKS0nkl9DEcu8EbMUhucWbxGnCG/22EEMTrY+\nSi1IZNkDGtlBHHBKMC+STbqqTxtdy4tAd2NYwWh3sBIh6PF7T4NLRAugu7PZQr5K\namS4z2lV3ebshGjieA0Zoznwh0AXgN0gZ/0pC/LXI25gcgtrvkCyL8Fe0AyZUMd8\nUvZXaRSsm3SkCUIlGjPrvuItn1D7tHmqVSCDKXDM2TqjfiRm1JF+2OFCBNvGz19V\nLxWd/Gf+0qw0dtKxRMKzGh0mxXY40hjtmYZulrPxhG5itNDjStovgrevM1HBsXs9\nikrkOGQ0pFcqizTn4ZKAmMozEMuIuV89Vof2bBCg7pHT1FmXVdAaYJxb6a7A/CgN\nqHjoh8AxBiGw/Q2NM4YJlUVhHqqd+/lUG3WJqACNEnqSlZkYQ3HqNNaKhHVbD4mN\nq/g6v+f8aWWDZDsI6IAfbJUB+KPEnIvQJQleWuHrq7kcUMhEq3dwBMIoTVEHhUUr\nRQKToSEM1rN7PcanaXQM2gy141dS7tFLxhapG8ug75LkIUnEOpPMtUjvrU1ZELGq\n36vVHBB+dTDg\n=tJCw\n-----END PGP PUBLIC KEY BLOCK-----\n", + "check_gpg": true, + "rhsm": false + }, + { + "name": "appstream", + "baseurl": "https://repo.almalinux.org/almalinux/10/AppStream/s390x/os/", + "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGaP6O8BEACvg8IlAxGayV8zOi9Ex+Pd8lrj2BrBzloG8ri84ORp9o8ojq7l\nykKmIElHe11cQD2Lf/a4lcQQ4Ec3baiD786X6K2eVSlBEAnZMzfjDg8R63SfsBuu\n8Yk+lUyqlBrDnSDYaPruOAzLIz2r82ikIC1jDbipZsMFPFHPI4/hayyWxJ3oGxRe\n0mbtYLB9ElEKngt+/hfo7JLklakbznyIRuVEF3VrZb91XC6r/idqfJoNyBXSKidj\nz0IwqOhgkLUk84rzltDo3AzwGqusd7PEuhOmqinOhp0hMdXsztD4TVyhw82iXu/O\nonOAObZTZYfM6Z8btmDqkoo0aT+oPPCuZ3yC/caU9dhvCSXET/CGoXc3hL55u9PV\nqmcVm/mwvuEImEAvxVc0/dBzEUk+FwW8KsaN3HoUKrC4/NqgmaQz8/42np7u2j+B\nOOJ4hAckNEdWd8rB86CYN00sdxnvLBsp8V3IwEqXLhGOoBsagy61Z8hKCM+siOGn\nxmbbybgaLOs+DPlxt9LrtgLJHODwmD96oysUPJuA0lv8KMiSpId0tSpp9Wn/wHBG\nkRgxGYfzQu7WRvRZqQaleft1JTXXOjNzPur0RkJyb3yFwAoxpePyo/WrupM41OHW\n58cEqdC6riCnJcS4U84RLj+hwvufBVB7areQ75sETnKeyozZW+P16E1t/wARAQAB\ntChBbG1hTGludXggT1MgMTAgPHBhY2thZ2VyQGFsbWFsaW51eC5vcmc+iQJMBBMB\nCgA2FiEE7m23uY9b9e3Z2g3l3uXBHMKh5XIFAmaP6O8CGwMECwkIBwQVCgkIBRYC\nAwEAAh4FAheAAAoJEN7lwRzCoeVy32AP/A2+KI+JhmsxnactSptkAWGyAAf1YBWW\nJs2sc9OJdKj7uIkzszCx7c7VIVeF/VLijIYpM/zwUgir5S5SimzQmY+FumwbKIml\nK5RBsoSog22i7Edho0MLa1pa6qvnKS0nkl9DEcu8EbMUhucWbxGnCG/22EEMTrY+\nSi1IZNkDGtlBHHBKMC+STbqqTxtdy4tAd2NYwWh3sBIh6PF7T4NLRAugu7PZQr5K\namS4z2lV3ebshGjieA0Zoznwh0AXgN0gZ/0pC/LXI25gcgtrvkCyL8Fe0AyZUMd8\nUvZXaRSsm3SkCUIlGjPrvuItn1D7tHmqVSCDKXDM2TqjfiRm1JF+2OFCBNvGz19V\nLxWd/Gf+0qw0dtKxRMKzGh0mxXY40hjtmYZulrPxhG5itNDjStovgrevM1HBsXs9\nikrkOGQ0pFcqizTn4ZKAmMozEMuIuV89Vof2bBCg7pHT1FmXVdAaYJxb6a7A/CgN\nqHjoh8AxBiGw/Q2NM4YJlUVhHqqd+/lUG3WJqACNEnqSlZkYQ3HqNNaKhHVbD4mN\nq/g6v+f8aWWDZDsI6IAfbJUB+KPEnIvQJQleWuHrq7kcUMhEq3dwBMIoTVEHhUUr\nRQKToSEM1rN7PcanaXQM2gy141dS7tFLxhapG8ug75LkIUnEOpPMtUjvrU1ZELGq\n36vVHBB+dTDg\n=tJCw\n-----END PGP PUBLIC KEY BLOCK-----\n", + "check_gpg": true, + "rhsm": false + } + ], + "x86_64": [ + { + "name": "baseos", + "baseurl": "https://repo.almalinux.org/almalinux/10/BaseOS/x86_64/os/", + "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGaP6O8BEACvg8IlAxGayV8zOi9Ex+Pd8lrj2BrBzloG8ri84ORp9o8ojq7l\nykKmIElHe11cQD2Lf/a4lcQQ4Ec3baiD786X6K2eVSlBEAnZMzfjDg8R63SfsBuu\n8Yk+lUyqlBrDnSDYaPruOAzLIz2r82ikIC1jDbipZsMFPFHPI4/hayyWxJ3oGxRe\n0mbtYLB9ElEKngt+/hfo7JLklakbznyIRuVEF3VrZb91XC6r/idqfJoNyBXSKidj\nz0IwqOhgkLUk84rzltDo3AzwGqusd7PEuhOmqinOhp0hMdXsztD4TVyhw82iXu/O\nonOAObZTZYfM6Z8btmDqkoo0aT+oPPCuZ3yC/caU9dhvCSXET/CGoXc3hL55u9PV\nqmcVm/mwvuEImEAvxVc0/dBzEUk+FwW8KsaN3HoUKrC4/NqgmaQz8/42np7u2j+B\nOOJ4hAckNEdWd8rB86CYN00sdxnvLBsp8V3IwEqXLhGOoBsagy61Z8hKCM+siOGn\nxmbbybgaLOs+DPlxt9LrtgLJHODwmD96oysUPJuA0lv8KMiSpId0tSpp9Wn/wHBG\nkRgxGYfzQu7WRvRZqQaleft1JTXXOjNzPur0RkJyb3yFwAoxpePyo/WrupM41OHW\n58cEqdC6riCnJcS4U84RLj+hwvufBVB7areQ75sETnKeyozZW+P16E1t/wARAQAB\ntChBbG1hTGludXggT1MgMTAgPHBhY2thZ2VyQGFsbWFsaW51eC5vcmc+iQJMBBMB\nCgA2FiEE7m23uY9b9e3Z2g3l3uXBHMKh5XIFAmaP6O8CGwMECwkIBwQVCgkIBRYC\nAwEAAh4FAheAAAoJEN7lwRzCoeVy32AP/A2+KI+JhmsxnactSptkAWGyAAf1YBWW\nJs2sc9OJdKj7uIkzszCx7c7VIVeF/VLijIYpM/zwUgir5S5SimzQmY+FumwbKIml\nK5RBsoSog22i7Edho0MLa1pa6qvnKS0nkl9DEcu8EbMUhucWbxGnCG/22EEMTrY+\nSi1IZNkDGtlBHHBKMC+STbqqTxtdy4tAd2NYwWh3sBIh6PF7T4NLRAugu7PZQr5K\namS4z2lV3ebshGjieA0Zoznwh0AXgN0gZ/0pC/LXI25gcgtrvkCyL8Fe0AyZUMd8\nUvZXaRSsm3SkCUIlGjPrvuItn1D7tHmqVSCDKXDM2TqjfiRm1JF+2OFCBNvGz19V\nLxWd/Gf+0qw0dtKxRMKzGh0mxXY40hjtmYZulrPxhG5itNDjStovgrevM1HBsXs9\nikrkOGQ0pFcqizTn4ZKAmMozEMuIuV89Vof2bBCg7pHT1FmXVdAaYJxb6a7A/CgN\nqHjoh8AxBiGw/Q2NM4YJlUVhHqqd+/lUG3WJqACNEnqSlZkYQ3HqNNaKhHVbD4mN\nq/g6v+f8aWWDZDsI6IAfbJUB+KPEnIvQJQleWuHrq7kcUMhEq3dwBMIoTVEHhUUr\nRQKToSEM1rN7PcanaXQM2gy141dS7tFLxhapG8ug75LkIUnEOpPMtUjvrU1ZELGq\n36vVHBB+dTDg\n=tJCw\n-----END PGP PUBLIC KEY BLOCK-----\n", + "check_gpg": true, + "rhsm": false + }, + { + "name": "appstream", + "baseurl": "https://repo.almalinux.org/almalinux/10/AppStream/x86_64/os/", + "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGaP6O8BEACvg8IlAxGayV8zOi9Ex+Pd8lrj2BrBzloG8ri84ORp9o8ojq7l\nykKmIElHe11cQD2Lf/a4lcQQ4Ec3baiD786X6K2eVSlBEAnZMzfjDg8R63SfsBuu\n8Yk+lUyqlBrDnSDYaPruOAzLIz2r82ikIC1jDbipZsMFPFHPI4/hayyWxJ3oGxRe\n0mbtYLB9ElEKngt+/hfo7JLklakbznyIRuVEF3VrZb91XC6r/idqfJoNyBXSKidj\nz0IwqOhgkLUk84rzltDo3AzwGqusd7PEuhOmqinOhp0hMdXsztD4TVyhw82iXu/O\nonOAObZTZYfM6Z8btmDqkoo0aT+oPPCuZ3yC/caU9dhvCSXET/CGoXc3hL55u9PV\nqmcVm/mwvuEImEAvxVc0/dBzEUk+FwW8KsaN3HoUKrC4/NqgmaQz8/42np7u2j+B\nOOJ4hAckNEdWd8rB86CYN00sdxnvLBsp8V3IwEqXLhGOoBsagy61Z8hKCM+siOGn\nxmbbybgaLOs+DPlxt9LrtgLJHODwmD96oysUPJuA0lv8KMiSpId0tSpp9Wn/wHBG\nkRgxGYfzQu7WRvRZqQaleft1JTXXOjNzPur0RkJyb3yFwAoxpePyo/WrupM41OHW\n58cEqdC6riCnJcS4U84RLj+hwvufBVB7areQ75sETnKeyozZW+P16E1t/wARAQAB\ntChBbG1hTGludXggT1MgMTAgPHBhY2thZ2VyQGFsbWFsaW51eC5vcmc+iQJMBBMB\nCgA2FiEE7m23uY9b9e3Z2g3l3uXBHMKh5XIFAmaP6O8CGwMECwkIBwQVCgkIBRYC\nAwEAAh4FAheAAAoJEN7lwRzCoeVy32AP/A2+KI+JhmsxnactSptkAWGyAAf1YBWW\nJs2sc9OJdKj7uIkzszCx7c7VIVeF/VLijIYpM/zwUgir5S5SimzQmY+FumwbKIml\nK5RBsoSog22i7Edho0MLa1pa6qvnKS0nkl9DEcu8EbMUhucWbxGnCG/22EEMTrY+\nSi1IZNkDGtlBHHBKMC+STbqqTxtdy4tAd2NYwWh3sBIh6PF7T4NLRAugu7PZQr5K\namS4z2lV3ebshGjieA0Zoznwh0AXgN0gZ/0pC/LXI25gcgtrvkCyL8Fe0AyZUMd8\nUvZXaRSsm3SkCUIlGjPrvuItn1D7tHmqVSCDKXDM2TqjfiRm1JF+2OFCBNvGz19V\nLxWd/Gf+0qw0dtKxRMKzGh0mxXY40hjtmYZulrPxhG5itNDjStovgrevM1HBsXs9\nikrkOGQ0pFcqizTn4ZKAmMozEMuIuV89Vof2bBCg7pHT1FmXVdAaYJxb6a7A/CgN\nqHjoh8AxBiGw/Q2NM4YJlUVhHqqd+/lUG3WJqACNEnqSlZkYQ3HqNNaKhHVbD4mN\nq/g6v+f8aWWDZDsI6IAfbJUB+KPEnIvQJQleWuHrq7kcUMhEq3dwBMIoTVEHhUUr\nRQKToSEM1rN7PcanaXQM2gy141dS7tFLxhapG8ug75LkIUnEOpPMtUjvrU1ZELGq\n36vVHBB+dTDg\n=tJCw\n-----END PGP PUBLIC KEY BLOCK-----\n", + "check_gpg": true, + "rhsm": false + } + ] +} diff --git a/vendor/github.com/osbuild/images/internal/common/helpers.go b/vendor/github.com/osbuild/images/internal/common/helpers.go index e3490edd6..a03b69243 100644 --- a/vendor/github.com/osbuild/images/internal/common/helpers.go +++ b/vendor/github.com/osbuild/images/internal/common/helpers.go @@ -2,11 +2,13 @@ package common import ( "bytes" + "encoding/binary" "fmt" "io" "os/exec" "sort" "strings" + "unicode/utf16" ) func PanicOnError(err error) { @@ -68,3 +70,15 @@ func Must[T any](val T, err error) T { } return val } + +// EncodeUTF16le encodes a source string to UTF-16LE. +func EncodeUTF16le(src string) []byte { + runes := []rune(src) + u16data := utf16.Encode(runes) + + dest := make([]byte, 0, len(u16data)*2) + for _, c := range u16data { + dest = binary.LittleEndian.AppendUint16(dest, c) + } + return dest +} diff --git a/vendor/github.com/osbuild/images/pkg/datasizes/parse.go b/vendor/github.com/osbuild/images/pkg/datasizes/parse.go index 926dec0c8..4ca32dd62 100644 --- a/vendor/github.com/osbuild/images/pkg/datasizes/parse.go +++ b/vendor/github.com/osbuild/images/pkg/datasizes/parse.go @@ -1,6 +1,7 @@ package datasizes import ( + "encoding/json" "fmt" "regexp" "strconv" @@ -49,8 +50,31 @@ func Parse(size string) (uint64, error) { } } - // In case the strign didn't match any of the above regexes, return nil + // In case the string didn't match any of the above regexes, return nil // even if a number was found. This is to prevent users from submitting // unknown units. return 0, fmt.Errorf("unknown data size units in string: %s", size) } + +// ParseSizeInJSONMapping will process the given JSON data, assuming it +// contains a mapping. It will convert the value of the given field to a size +// in bytes using the Parse function if the field exists and is a string. +func ParseSizeInJSONMapping(field string, data []byte) ([]byte, error) { + var mapping map[string]any + if err := json.Unmarshal(data, &mapping); err != nil { + return nil, fmt.Errorf("failed to unmarshal JSON data: %w", err) + } + + if rawSize, ok := mapping[field]; ok { + // If the size is a string, parse it and replace the value in the map + if sizeStr, ok := rawSize.(string); ok { + size, err := Parse(sizeStr) + if err != nil { + return nil, fmt.Errorf("failed to parse size field named %q to bytes: %w", field, err) + } + mapping[field] = size + } + } + + return json.Marshal(mapping) +} diff --git a/vendor/github.com/osbuild/images/pkg/disk/btrfs.go b/vendor/github.com/osbuild/images/pkg/disk/btrfs.go index 7cd8a0006..b4ffb3196 100644 --- a/vendor/github.com/osbuild/images/pkg/disk/btrfs.go +++ b/vendor/github.com/osbuild/images/pkg/disk/btrfs.go @@ -6,6 +6,8 @@ import ( "reflect" "github.com/google/uuid" + "github.com/osbuild/images/internal/common" + "github.com/osbuild/images/pkg/datasizes" ) const DefaultBtrfsCompression = "zstd:1" @@ -118,6 +120,25 @@ type BtrfsSubvolume struct { UUID string `json:"uuid,omitempty" yaml:"uuid,omitempty"` } +func (sv *BtrfsSubvolume) UnmarshalJSON(data []byte) (err error) { + data, err = datasizes.ParseSizeInJSONMapping("size", data) + if err != nil { + return fmt.Errorf("error parsing size in btrfs subvolume: %w", err) + } + + type aliasStruct BtrfsSubvolume + var alias aliasStruct + if err := jsonUnmarshalStrict(data, &alias); err != nil { + return fmt.Errorf("cannot unmarshal %q: %w", data, err) + } + *sv = BtrfsSubvolume(alias) + return err +} + +func (sv *BtrfsSubvolume) UnmarshalYAML(unmarshal func(any) error) error { + return common.UnmarshalYAMLviaJSON(sv, unmarshal) +} + func (bs *BtrfsSubvolume) Clone() Entity { if bs == nil { return nil diff --git a/vendor/github.com/osbuild/images/pkg/disk/disk.go b/vendor/github.com/osbuild/images/pkg/disk/disk.go index f624e8ad2..67507d889 100644 --- a/vendor/github.com/osbuild/images/pkg/disk/disk.go +++ b/vendor/github.com/osbuild/images/pkg/disk/disk.go @@ -206,6 +206,24 @@ func (f FSType) String() string { } } +func (f *FSType) UnmarshalJSON(data []byte) error { + var s string + if err := json.Unmarshal(data, &s); err != nil { + return err + } + + new, err := NewFSType(s) + if err != nil { + return err + } + *f = new + return nil +} + +func (f *FSType) UnmarshalYAML(unmarshal func(any) error) error { + return common.UnmarshalYAMLviaJSON(f, unmarshal) +} + func NewFSType(s string) (FSType, error) { switch s { case "": diff --git a/vendor/github.com/osbuild/images/pkg/disk/lvm.go b/vendor/github.com/osbuild/images/pkg/disk/lvm.go index b647b33d7..0a4035244 100644 --- a/vendor/github.com/osbuild/images/pkg/disk/lvm.go +++ b/vendor/github.com/osbuild/images/pkg/disk/lvm.go @@ -246,6 +246,11 @@ func lvname(path string) string { } func (lv *LVMLogicalVolume) UnmarshalJSON(data []byte) (err error) { + data, err = datasizes.ParseSizeInJSONMapping("size", data) + if err != nil { + return fmt.Errorf("error parsing size in LVM LV: %w", err) + } + // keep in sync with lvm.go,partition.go,luks.go type alias LVMLogicalVolume var withoutPayload struct { diff --git a/vendor/github.com/osbuild/images/pkg/disk/partition.go b/vendor/github.com/osbuild/images/pkg/disk/partition.go index 2c1b83ecc..608aabf00 100644 --- a/vendor/github.com/osbuild/images/pkg/disk/partition.go +++ b/vendor/github.com/osbuild/images/pkg/disk/partition.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/osbuild/images/internal/common" + "github.com/osbuild/images/pkg/datasizes" ) type Partition struct { @@ -126,6 +127,11 @@ func (p *Partition) MarshalJSON() ([]byte, error) { } func (p *Partition) UnmarshalJSON(data []byte) (err error) { + data, err = datasizes.ParseSizeInJSONMapping("size", data) + if err != nil { + return fmt.Errorf("error parsing size in partition: %w", err) + } + // keep in sync with lvm.go,partition.go,luks.go type alias Partition var withoutPayload struct { diff --git a/vendor/github.com/osbuild/images/pkg/disk/partition_table.go b/vendor/github.com/osbuild/images/pkg/disk/partition_table.go index 7de9402af..5d69e6ac4 100644 --- a/vendor/github.com/osbuild/images/pkg/disk/partition_table.go +++ b/vendor/github.com/osbuild/images/pkg/disk/partition_table.go @@ -7,6 +7,7 @@ import ( "github.com/google/uuid" + "github.com/osbuild/images/internal/common" "github.com/osbuild/images/pkg/arch" "github.com/osbuild/images/pkg/blueprint" "github.com/osbuild/images/pkg/datasizes" @@ -26,7 +27,7 @@ type PartitionTable struct { SectorSize uint64 `json:"sector_size,omitempty" yaml:"sector_size,omitempty"` // Extra space at the end of the partition table (sectors) ExtraPadding uint64 `json:"extra_padding,omitempty" yaml:"extra_padding,omitempty"` - // Starting offset of the first partition in the table (Mb) + // Starting offset of the first partition in the table (in bytes) StartOffset uint64 `json:"start_offset,omitempty" yaml:"start_offset,omitempty"` } @@ -172,6 +173,27 @@ func NewPartitionTable(basePT *PartitionTable, mountpoints []blueprint.Filesyste return newPT, nil } +func (pt *PartitionTable) UnmarshalJSON(data []byte) (err error) { + for _, field := range []string{"size", "start_offset"} { + data, err = datasizes.ParseSizeInJSONMapping(field, data) + if err != nil { + return fmt.Errorf("error parsing %q in partition table: %w", field, err) + } + } + + type aliasStruct PartitionTable + var alias aliasStruct + if err := jsonUnmarshalStrict(data, &alias); err != nil { + return fmt.Errorf("cannot unmarshal %q: %w", data, err) + } + *pt = PartitionTable(alias) + return err +} + +func (pt *PartitionTable) UnmarshalYAML(unmarshal func(any) error) error { + return common.UnmarshalYAMLviaJSON(pt, unmarshal) +} + func (pt *PartitionTable) Clone() Entity { if pt == nil { return nil diff --git a/vendor/github.com/osbuild/images/pkg/distro/defs/distros.yaml b/vendor/github.com/osbuild/images/pkg/distro/defs/distros.yaml new file mode 100644 index 000000000..cffd669e5 --- /dev/null +++ b/vendor/github.com/osbuild/images/pkg/distro/defs/distros.yaml @@ -0,0 +1,61 @@ +distros: + - &fedora_rawhide + name: fedora-43 + preview: true + os_version: 43 + release_version: 43 + module_platform_id: platform:f43 + product: "Fedora" + ostree_ref_tmpl: "fedora/43/%s/iot" + iso_label_tmpl: "{{.Product}}-{{.OsVersion}}-{{.ImgTypeLabel}}-{{.Arch}}" + default_fs_type: "ext4" + defs_path: fedora + runner: &fedora_runner + name: org.osbuild.fedora43 + build_packages: + - "glibc" # ldconfig + - "systemd" # systemd-tmpfiles and systemd-sysusers + - "python3" # osbuild + oscap_profiles_allowlist: + - "xccdf_org.ssgproject.content_profile_ospp" + - "xccdf_org.ssgproject.content_profile_pci-dss" + - "xccdf_org.ssgproject.content_profile_standard" + bootstrap_containers: + x86_64: "registry.fedoraproject.org/fedora-toolbox:43" + aarch64: "registry.fedoraproject.org/fedora-toolbox:43" + ppc64le: "registry.fedoraproject.org/fedora-toolbox:43" + s390x: "registry.fedoraproject.org/fedora-toolbox:43" + # XXX: remove once fedora containers are part of the upstream + # fedora registry (and can be validated via tls) + riscv64: "ghcr.io/mvo5/fedora-buildroot:43" + # XXX: add repos here too, that requires some churn, see + # https://github.com/osbuild/images/compare/main...mvo5:yaml-distroconfig?expand=1 + # and we will also need to think about backward compat, as currently + # dropping "$distro-$ver.json" files into + # /etc/osbuild-composer/repositories will define what distros are + # available via images and we will need to provide compatibility for + # that. + # + # Having the repos separated means when a new fedora release is out + # we will need to update two places which is clearly a regression from + # before. + - &fedora_stable + <<: *fedora_rawhide + name: "fedora-{{.MajorVersion}}" + match: "fedora-[0-9][0-9]{,[0-9]}" + preview: false + os_version: "{{.MajorVersion}}" + release_version: "{{.MajorVersion}}" + module_platform_id: "platform:f{{.MajorVersion}}" + ostree_ref_tmpl: "fedora/{{.MajorVersion}}/%s/iot" + runner: + <<: *fedora_runner + name: org.osbuild.fedora{{.MajorVersion}} + bootstrap_containers: + x86_64: "registry.fedoraproject.org/fedora-toolbox:{{.MajorVersion}}" + aarch64: "registry.fedoraproject.org/fedora-toolbox:{{.MajorVersion}}" + ppc64le: "registry.fedoraproject.org/fedora-toolbox:{{.MajorVersion}}" + s390x: "registry.fedoraproject.org/fedora-toolbox:{{.MajorVersion}}" + # XXX: remove once fedora containers are part of the upstream + # fedora registry (and can be validated via tls) + riscv64: "ghcr.io/mvo5/fedora-buildroot:{{.MajorVersion}}" diff --git a/vendor/github.com/osbuild/images/pkg/distro/defs/fedora/distro.yaml b/vendor/github.com/osbuild/images/pkg/distro/defs/fedora/distro.yaml index 33b72edc9..99255076d 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/defs/fedora/distro.yaml +++ b/vendor/github.com/osbuild/images/pkg/distro/defs/fedora/distro.yaml @@ -66,6 +66,7 @@ - "efibootmgr" - "grub2-efi-x64" - "shim-x64" + bootloader: "grub2" x86_64_bios_platform: &x86_64_bios_platform <<: *x86_64_uefi_platform bios_platform: "i386-pc" @@ -77,6 +78,7 @@ build_packages: bios: - "grub2-pc" + bootloader: "grub2" # XXX: the name is not 100% accurate, this platform is also used for iot-container, iot-commit x86_64_installer_platform: &x86_64_installer_platform <<: *x86_64_bios_platform @@ -88,6 +90,7 @@ - "iwlwifi-dvm-firmware" - "iwlwifi-mvm-firmware" - "microcode_ctl" + bootloader: "grub2" aarch64_platform: &aarch64_platform arch: "aarch64" uefi_vendor: "fedora" @@ -100,6 +103,7 @@ - "grub2-efi-aa64" - "grub2-tools" - "shim-aa64" + bootloader: "grub2" aarch64_installer_platform: &aarch64_installer_platform arch: "aarch64" uefi_vendor: "fedora" @@ -112,6 +116,7 @@ - "iwlwifi-mvm-firmware" - "realtek-firmware" - "uboot-images-armv8" + bootloader: "grub2" ppc64le_bios_platform: &ppc64le_bios_platform arch: "ppc64le" bios_platform: "powerpc-ieee1275" @@ -127,6 +132,7 @@ bios: - "grub2-ppc64le" - "grub2-ppc64le-modules" + bootloader: "grub2" s390x_zipl_platform: &s390x_zipl_platform arch: "s390x" zipl_support: true @@ -140,6 +146,7 @@ build_packages: zipl: - "s390utils-base" + bootloader: "zipl" riscv64_uefi_platform: &riscv64_uefi_platform arch: "riscv64" uefi_vendor: "uefi" @@ -153,15 +160,25 @@ - "grub2-efi-riscv64" - "grub2-efi-riscv64-modules" - "shim-unsigned-riscv64" + bootloader: "grub2" + installer_config: &default_installer_config additional_dracut_modules: - "net-lib" + squashfs_rootfs: true condition: version_less_than: "42": + # config is fully replaced additional_dracut_modules: - "ifcfg" + squashfs_rootfs: true + "41": + # config is fully replaced + additional_dracut_modules: + - "ifcfg" + squashfs_rootfs: false image_config: iot_enabled_services: &image_config_iot_enabled_services @@ -237,12 +254,12 @@ # the invidual partitions for easier composibility partitions: - &default_partition_table_part_bios - size: 1_048_576 # 1 MiB + size: "1 MiB" bootable: true type: *bios_boot_partition_guid uuid: *bios_boot_partition_uuid - &default_partition_table_part_efi - size: 209_715_200 # 200 MiB + size: "200 MiB" type: *efi_system_partition_guid uuid: *efi_system_partition_uuid payload_type: "filesystem" @@ -255,7 +272,7 @@ fstab_freq: 0 fstab_passno: 2 - &default_partition_table_part_boot - size: 1_073_741_824 # 1 * datasizes.GibiByte, + size: "1 GiB" type: *filesystem_data_guid uuid: *data_partition_uuid payload_type: "filesystem" @@ -267,7 +284,7 @@ fstab_freq: 0 fstab_passno: 0 - &default_partition_table_part_root - size: 2_147_483_648 # 2 * datasizes.GibiByte, + size: "2 GiB" type: *filesystem_data_guid uuid: *root_partition_uuid payload_type: "filesystem" @@ -280,7 +297,7 @@ fstab_passno: 0 # iot partitions - &iot_base_partition_table_part_efi - size: 525_336_576 # 501 * datasizes.MebiByte + size: "501 MiB" type: *efi_system_partition_guid uuid: *efi_system_partition_uuid payload_type: "filesystem" @@ -293,7 +310,7 @@ fstab_freq: 0 fstab_passno: 2 - &iot_base_partition_table_part_boot - size: 1_073_741_824 # 1 * datasizes.GibiByte, + size: "1 GiB" type: *filesystem_data_guid uuid: *data_partition_uuid payload_type: "filesystem" @@ -305,7 +322,7 @@ fstab_freq: 1 fstab_passno: 2 - &iot_base_partition_table_part_root - size: 2_693_791_744 # 2569 * datasizes.MebiByte, + size: "2569 MiB" type: *filesystem_data_guid uuid: *root_partition_uuid payload_type: "filesystem" @@ -362,11 +379,11 @@ uuid: "0x14fc63d2" type: "dos" partitions: - - size: 4_194_304 # 4 MiB + - size: "4 MiB" bootable: true type: *prep_partition_dosid - &default_partition_table_part_boot_ppc64le - size: 1_073_741_824 # 1 * datasizes.GibiByte, + size: "1 GiB" payload_type: "filesystem" payload: type: "ext4" @@ -376,7 +393,7 @@ fstab_freq: 0 fstab_passno: 0 - &default_partition_table_part_root_ppc64le - size: 2_147_483_648 # 2 * datasizes.GibiByte, + size: "2 GiB" payload_type: "filesystem" payload: type: "ext4" @@ -397,7 +414,7 @@ x86_64: uuid: "D209C89E-EA5E-4FBD-B161-B461CCE297E0" type: "gpt" - start_offset: 8_388_608 # 8 * datasizes.MebiByte + start_offset: "8 MiB" partitions: - *default_partition_table_part_efi - &minimal_raw_partition_table_part_boot @@ -408,7 +425,7 @@ aarch64: &minimal_raw_partition_table_aarch64 uuid: "0xc1748067" type: "dos" - start_offset: 8_388_608 # 8 * datasizes.MebiByte + start_offset: "8 MiB" partitions: - <<: *default_partition_table_part_efi bootable: true @@ -426,7 +443,7 @@ x86_64: &iot_base_partition_table_x86_64 uuid: "D209C89E-EA5E-4FBD-B161-B461CCE297E0" type: "gpt" - start_offset: 8_388_608 # 8 * datasizes.MebiByte + start_offset: "8 MiB" partitions: - *iot_base_partition_table_part_efi - *iot_base_partition_table_part_boot @@ -434,7 +451,7 @@ aarch64: &iot_base_partition_table_aarch64 uuid: "0xc1748067" type: "dos" - start_offset: 8_388_608 # 8 * datasizes.MebiByte + start_offset: "8 MiB" partitions: - *iot_base_partition_table_part_efi_aarch64 - *iot_base_partition_table_part_boot_aarch64 @@ -446,7 +463,7 @@ type: "gpt" partitions: - *iot_base_partition_table_part_efi - - size: 1_073_741_824 # 1 * datasizes.GibiByte, + - size: "1 GiB" type: *xboot_ldr_partition_guid uuid: *data_partition_uuid payload_type: "filesystem" @@ -477,7 +494,7 @@ name: "rootvg" description: "built with lvm2 and osbuild" logical_volumes: - - size: 8_589_934_592 # 8 * datasizes.GibiByte, + - size: "8 GiB" name: "rootlv" payload_type: "filesystem" payload: @@ -500,6 +517,48 @@ image_config: timezone: "UTC" image_types: + "server-vagrant-libvirt": &server_vagrant_libvirt + filename: "vagrant-libvirt.box" + mime_type: "application/x-tar" + environment: *kvm_env + bootable: true + default_size: 5_368_709_120 # 5 * datasizes.GibiByte + image_func: "disk" + build_pipelines: ["build"] + payload_pipelines: ["os", "image", "vagrant", "archive"] + exports: ["archive"] + required_partition_sizes: *default_required_dir_sizes + image_config: &image_config_vagrant + default_target: "multi-user.target" + kernel_options: *cloud_kernel_options + users: + # yamllint disable rule:line-length + - name: "vagrant" + # yamllint disable rule:line-length + key: | + ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key + ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN1YdxBpNlzxDqfJyw/QKow1F+wvG9hXGoqiysfJOn5Y vagrant insecure public key + # yamllint enable rule:line-length + files: + - path: "/etc/sudoers.d/vagrant" + user: "root" + group: "root" + mode: 440 + data: | + vagrant ALL=(ALL) NOPASSWD: ALL + partition_table: + <<: *default_partition_tables + package_sets: + os: + - *cloud_base_pkgset + - include: + - "qemu-guest-agent" + platforms: + - <<: *x86_64_bios_platform + image_format: "vagrant_libvirt" + - <<: *aarch64_platform + image_format: "vagrant_libvirt" + "server-qcow2": &server_qcow2 name_aliases: ["qcow2"] filename: "disk.qcow2" @@ -811,6 +870,9 @@ image_types: rpm_ostree: true bootable: true image_func: "iot" + ostree: + name: "fedora" + remote: "fedora-iot" build_pipelines: ["build"] payload_pipelines: ["ostree-deployment", "image", "xz"] exports: ["xz"] @@ -885,6 +947,9 @@ image_types: rpm_ostree: true bootable: true image_func: "iot" + ostree: + name: "fedora" + remote: "fedora-iot" build_pipelines: ["build"] payload_pipelines: ["ostree-deployment", "image", "qcow2"] exports: ["qcow2"] @@ -1069,6 +1134,7 @@ image_types: - "uboot-images-armv8" boot_files: - ["/usr/share/uboot/rpi_arm64/u-boot.bin", "/boot/efi/rpi-u-boot.bin"] + bootloader: "grub2" - *riscv64_uefi_platform image_config: # NOTE: temporary workaround for a bug in initial-setup that @@ -1328,6 +1394,9 @@ image_types: boot_iso: true image_func: "iot_installer" iso_label: "IoT" + ostree: + name: "fedora-iot" + remote: "fedora-iot" build_pipelines: ["build"] payload_pipelines: - "anaconda-tree" @@ -1407,7 +1476,9 @@ image_types: - "sdubby" condition: version_greater_or_equal: - VERSION_RAWHIDE: + # XXX: this was VERSION_RAWHIDE, if we need this again lets add + # "alias" to defs.DistroYAML + 43: include: - "anaconda-webui" platforms: @@ -1424,6 +1495,8 @@ image_types: image_func: "image_installer" # We don't know the variant of the OS pipeline being installed iso_label: "Unknown" + # We don't know the variant that goes into the OS pipeline that gets installed + variant: "Unknown" build_pipelines: ["build"] payload_pipelines: - "anaconda-tree" @@ -1433,6 +1506,22 @@ image_types: - "bootiso" exports: ["bootiso"] required_partition_sizes: *default_required_dir_sizes + installer_config: + additional_dracut_modules: + - "net-lib" + - "dbus-broker" + squashfs_rootfs: true + condition: + # on match the config is fully replaced + version_less_than: + "41": + additional_dracut_modules: &additional_dracut_f41 + - "ifcfg" + - "dbus-broker" + squashfs_rootfs: false + "42": + additional_dracut_modules: *additional_dracut_f41 + squashfs_rootfs: true image_config: locale: "en_US.UTF-8" iso_rootfs_type: "squashfs" @@ -1605,6 +1694,9 @@ image_types: default_size: 10_737_418_240 # 10 * datasizes.GibiByte image_func: "iot_simplified_installer" iso_label: "IoT" + ostree: + name: "fedora" + remote: "fedora-iot" build_pipelines: ["build"] payload_pipelines: - "ostree-deployment" @@ -1616,7 +1708,8 @@ image_types: - "bootiso" exports: ["bootiso"] required_partition_sizes: *default_required_dir_sizes - installer_config: *default_installer_config + installer_config: + <<: *default_installer_config image_config: <<: *image_config_iot ignition_platform: "metal" diff --git a/vendor/github.com/osbuild/images/pkg/distro/defs/loader.go b/vendor/github.com/osbuild/images/pkg/distro/defs/loader.go index 6f5eea9ff..c09d15f2e 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/defs/loader.go +++ b/vendor/github.com/osbuild/images/pkg/distro/defs/loader.go @@ -2,28 +2,36 @@ package defs import ( + "bytes" + "crypto/sha256" "embed" "errors" "fmt" + "io" "io/fs" "os" "path/filepath" "slices" "sort" - "strings" + "sync" + "text/template" + "github.com/gobwas/glob" "github.com/hashicorp/go-version" "golang.org/x/exp/maps" "gopkg.in/yaml.v3" "github.com/osbuild/images/internal/common" "github.com/osbuild/images/internal/environment" + "github.com/osbuild/images/pkg/arch" + "github.com/osbuild/images/pkg/customizations/oscap" "github.com/osbuild/images/pkg/disk" "github.com/osbuild/images/pkg/distro" "github.com/osbuild/images/pkg/experimentalflags" "github.com/osbuild/images/pkg/olog" "github.com/osbuild/images/pkg/platform" "github.com/osbuild/images/pkg/rpmmd" + "github.com/osbuild/images/pkg/runner" ) var ( @@ -32,12 +40,146 @@ var ( ErrNoPartitionTableForArch = errors.New("no partition table for arch") ) -//go:embed */*.yaml +//go:embed *.yaml */*.yaml var data embed.FS -var DataFS fs.FS = data +var defaultDataFS fs.FS = data -type toplevelYAML struct { +// distrosYAML defines all supported YAML based distributions +type distrosYAML struct { + Distros []DistroYAML +} + +func dataFS() fs.FS { + // XXX: this is a short term measure, pass a set of + // searchPaths down the stack instead + var dataFS fs.FS = defaultDataFS + if overrideDir := experimentalflags.String("yamldir"); overrideDir != "" { + olog.Printf("WARNING: using experimental override dir %q", overrideDir) + dataFS = os.DirFS(overrideDir) + } + return dataFS +} + +type DistroYAML struct { + // Match can be used to match multiple versions via a + // fnmatch/glob style expression. We could also use a + // regex and do something like: + // rhel-(?P[0-9]+)\.(?P[0-9]+) + // if we need to be more precise in the future, but for + // now every match will be split into "$distroname-$major.$minor" + // (with minor being optional) + Match string `yaml:"match"` + + // The distro metadata, can contain go text template strings + // for {{.Major}}, {{.Minor}} which will be expanded by the + // upper layers. + Name string `yaml:"name"` + Codename string `yaml:"codename"` + Vendor string `yaml:"vendor"` + Preview bool `yaml:"preview"` + OsVersion string `yaml:"os_version"` + ReleaseVersion string `yaml:"release_version"` + ModulePlatformID string `yaml:"module_platform_id"` + Product string `yaml:"product"` + OSTreeRefTmpl string `yaml:"ostree_ref_tmpl"` + Runner runner.RunnerConf `yaml:"runner"` + + // ISOLabelTmpl can contain {{.Product}},{{.OsVersion}},{{.Arch}},{{.ImgTypeLabel}} + ISOLabelTmpl string `yaml:"iso_label_tmpl"` + + DefaultFSType disk.FSType `yaml:"default_fs_type"` + + // directory with the actual image defintions, we separate that + // so that we can point the "centos-10" distro to the "./rhel-10" + // image types file/directory. + DefsPath string `yaml:"defs_path"` + + BootstrapContainers map[arch.Arch]string `yaml:"bootstrap_containers"` + + OscapProfilesAllowList []oscap.Profile `yaml:"oscap_profiles_allowlist"` +} + +func executeTemplates(d *DistroYAML, nameVer string) error { + id, err := distro.ParseID(nameVer) + if err != nil { + return err + } + + var errs []error + subs := func(inp string) string { + var buf bytes.Buffer + templ, err := template.New("").Parse(inp) + if err != nil { + errs = append(errs, err) + return inp + } + if err := templ.Execute(&buf, id); err != nil { + errs = append(errs, err) + return inp + } + return buf.String() + } + d.Name = subs(d.Name) + d.OsVersion = subs(d.OsVersion) + d.ReleaseVersion = subs(d.ReleaseVersion) + d.OSTreeRefTmpl = subs(d.OSTreeRefTmpl) + d.ModulePlatformID = subs(d.ModulePlatformID) + d.Runner.Name = subs(d.Runner.Name) + for a := range d.BootstrapContainers { + d.BootstrapContainers[a] = subs(d.BootstrapContainers[a]) + } + + return errors.Join(errs...) +} + +// Distro return the given distro or nil if the distro is not +// found. This mimics the "distrofactory.GetDistro() interface. +// +// Note that eventually we want something like "Distros()" instead +// that returns all known distros but for now we keep compatibility +// with the way distrofactory/reporegistry work which is by defining +// distros via repository files. +func Distro(nameVer string) (*DistroYAML, error) { + f, err := dataFS().Open("distros.yaml") + if err != nil { + return nil, err + } + defer f.Close() + + decoder := yaml.NewDecoder(f) + decoder.KnownFields(true) + + var distros distrosYAML + if err := decoder.Decode(&distros); err != nil { + return nil, err + } + + for _, distro := range distros.Distros { + if distro.Name == nameVer { + return &distro, nil + } + + pat, err := glob.Compile(distro.Match) + if err != nil { + return nil, err + } + if pat.Match(nameVer) { + if err := executeTemplates(&distro, nameVer); err != nil { + return nil, err + } + + return &distro, nil + } + } + + return nil, nil +} + +// imageTypesYAML describes the image types for a given distribution +// family. Note that multiple distros may use the same image types, +// e.g. centos/rhel +type imageTypesYAML struct { ImageConfig distroImageConfig `yaml:"image_config,omitempty"` ImageTypes map[string]imageType `yaml:"image_types"` Common map[string]any `yaml:".common,omitempty"` @@ -83,9 +225,17 @@ type imageType struct { Environment environment.EnvironmentConf `yaml:"environment"` Bootable bool `yaml:"bootable"` - BootISO bool `yaml:"boot_iso"` - ISOLabel string `yaml:"iso_label"` - RPMOSTree bool `yaml:"rpm_ostree"` + BootISO bool `yaml:"boot_iso"` + ISOLabel string `yaml:"iso_label"` + // XXX: or iso_variant? + Variant string `yaml:"variant"` + + RPMOSTree bool `yaml:"rpm_ostree"` + + OSTree struct { + Name string `yaml:"name"` + Remote string `yaml:"remote"` + } `yaml:"ostree"` DefaultSize uint64 `yaml:"default_size"` // the image func name: disk,container,live-installer,... @@ -195,11 +345,14 @@ func DistroImageConfig(distroNameVer string) (*distro.ImageConfig, error) { cond := toplevel.ImageConfig.Condition if cond != nil { - distroName, _ := splitDistroNameVer(distroNameVer) + id, err := distro.ParseID(distroNameVer) + if err != nil { + return nil, err + } // XXX: we shoudl probably use a similar pattern like // for the partition table overrides (via // findElementIndexByJSONTag) but this if fine for now - if distroNameCnf, ok := cond.DistroName[distroName]; ok { + if distroNameCnf, ok := cond.DistroName[id.Name]; ok { imgConfig = distroNameCnf.InheritFrom(imgConfig) } } @@ -209,14 +362,17 @@ func DistroImageConfig(distroNameVer string) (*distro.ImageConfig, error) { // PackageSets loads the PackageSets from the yaml source file // discovered via the imagetype. -func PackageSets(it distro.ImageType, replacements map[string]string) (map[string]rpmmd.PackageSet, error) { +func PackageSets(it distro.ImageType) (map[string]rpmmd.PackageSet, error) { typeName := it.Name() arch := it.Arch() archName := arch.Name() distribution := arch.Distro() distroNameVer := distribution.Name() - distroName, distroVersion := splitDistroNameVer(distroNameVer) + id, err := distro.ParseID(distroNameVer) + if err != nil { + return nil, err + } // each imagetype can have multiple package sets, so that we can // use yaml aliases/anchors to de-duplicate them @@ -247,7 +403,7 @@ func PackageSets(it distro.ImageType, replacements map[string]string) (map[strin Exclude: archSet.Exclude, }) } - if distroNameSet, ok := pkgSet.Condition.DistroName[distroName]; ok { + if distroNameSet, ok := pkgSet.Condition.DistroName[id.Name]; ok { rpmmdPkgSet = rpmmdPkgSet.Append(rpmmd.PackageSet{ Include: distroNameSet.Include, Exclude: distroNameSet.Exclude, @@ -257,10 +413,7 @@ func PackageSets(it distro.ImageType, replacements map[string]string) (map[strin // packageSets are strictly additive the order // is irrelevant for ltVer, ltSet := range pkgSet.Condition.VersionLessThan { - if r, ok := replacements[ltVer]; ok { - ltVer = r - } - if common.VersionLessThan(distroVersion, ltVer) { + if common.VersionLessThan(id.VersionString(), ltVer) { rpmmdPkgSet = rpmmdPkgSet.Append(rpmmd.PackageSet{ Include: ltSet.Include, Exclude: ltSet.Exclude, @@ -269,10 +422,7 @@ func PackageSets(it distro.ImageType, replacements map[string]string) (map[strin } for gteqVer, gteqSet := range pkgSet.Condition.VersionGreaterOrEqual { - if r, ok := replacements[gteqVer]; ok { - gteqVer = r - } - if common.VersionGreaterThanOrEqual(distroVersion, gteqVer) { + if common.VersionGreaterThanOrEqual(id.VersionString(), gteqVer) { rpmmdPkgSet = rpmmdPkgSet.Append(rpmmd.PackageSet{ Include: gteqSet.Include, Exclude: gteqSet.Exclude, @@ -291,7 +441,7 @@ func PackageSets(it distro.ImageType, replacements map[string]string) (map[strin } // PartitionTable returns the partionTable for the given distro/imgType. -func PartitionTable(it distro.ImageType, replacements map[string]string) (*disk.PartitionTable, error) { +func PartitionTable(it distro.ImageType) (*disk.PartitionTable, error) { distroNameVer := it.Arch().Distro().Name() toplevel, err := load(distroNameVer) @@ -309,118 +459,150 @@ func PartitionTable(it distro.ImageType, replacements map[string]string) (*disk. arch := it.Arch() archName := arch.Name() + pt, ok := imgType.PartitionTables[archName] + if !ok { + return nil, fmt.Errorf("%w (%q): %q", ErrNoPartitionTableForArch, it.Name(), archName) + } + if imgType.PartitionTablesOverrides != nil { cond := imgType.PartitionTablesOverrides.Condition - distroName, distroVersion := splitDistroNameVer(it.Arch().Distro().Name()) + id, err := distro.ParseID(it.Arch().Distro().Name()) + if err != nil { + return nil, err + } for _, ltVer := range versionLessThanSortedKeys(cond.VersionLessThan) { ltOverrides := cond.VersionLessThan[ltVer] - if r, ok := replacements[ltVer]; ok { - ltVer = r - } - if common.VersionLessThan(distroVersion, ltVer) { - for arch, overridePt := range ltOverrides { - imgType.PartitionTables[arch] = overridePt + if common.VersionLessThan(id.VersionString(), ltVer) { + if newPt, ok := ltOverrides[archName]; ok { + pt = newPt } } } for _, gteqVer := range backward(versionLessThanSortedKeys(cond.VersionGreaterOrEqual)) { geOverrides := cond.VersionGreaterOrEqual[gteqVer] - if r, ok := replacements[gteqVer]; ok { - gteqVer = r - } - if common.VersionGreaterThanOrEqual(distroVersion, gteqVer) { - for arch, overridePt := range geOverrides { - imgType.PartitionTables[arch] = overridePt + if common.VersionGreaterThanOrEqual(id.VersionString(), gteqVer) { + if newPt, ok := geOverrides[archName]; ok { + pt = newPt } } } - if distroNameOverrides, ok := cond.DistroName[distroName]; ok { - for arch, overridePt := range distroNameOverrides { - imgType.PartitionTables[arch] = overridePt + if distroNameOverrides, ok := cond.DistroName[id.Name]; ok { + if newPt, ok := distroNameOverrides[archName]; ok { + pt = newPt } } } - pt, ok := imgType.PartitionTables[archName] - if !ok { - return nil, fmt.Errorf("%w (%q): %q", ErrNoPartitionTableForArch, it.Name(), archName) - } - return pt, nil } -func splitDistroNameVer(distroNameVer string) (string, string) { - // we need to split from the right for "centos-stream-10" like - // distro names, sadly go has no rsplit() so we do it manually - // XXX: we cannot use distroidparser here because of import cycles - idx := strings.LastIndex(distroNameVer, "-") - return distroNameVer[:idx], distroNameVer[idx+1:] +// Cache the toplevel structure, loading/parsing YAML is quite +// expensive. This can all be removed in the future where there +// is a single load for each distroNameVer. Right now the various +// helpers (like ParititonTable(), ImageConfig() are called a +// gazillion times. However once we move into the "generic" distro +// the distro will do a single load/parse of all image types and +// just reuse them and this can go. +type imageTypesCache struct { + cache map[string]*imageTypesYAML + mu sync.Mutex } -func load(distroNameVer string) (*toplevelYAML, error) { - // we need to split from the right for "centos-stream-10" like - // distro names, sadly go has no rsplit() so we do it manually - // XXX: we cannot use distroidparser here because of import cycles - distroName, distroVersion := splitDistroNameVer(distroNameVer) - distroNameMajorVer := strings.SplitN(distroNameVer, ".", 2)[0] - distroMajorVer := strings.SplitN(distroVersion, ".", 2)[0] +func newImageTypesCache() *imageTypesCache { + return &imageTypesCache{cache: make(map[string]*imageTypesYAML)} +} - // XXX: this is a short term measure, pass a set of - // searchPaths down the stack instead - var dataFS fs.FS = DataFS - if overrideDir := experimentalflags.String("yamldir"); overrideDir != "" { - olog.Printf("WARNING: using experimental override dir %q", overrideDir) - dataFS = os.DirFS(overrideDir) +func (i *imageTypesCache) Get(hash string) *imageTypesYAML { + i.mu.Lock() + defer i.mu.Unlock() + + return i.cache[hash] +} + +func (i *imageTypesCache) Set(hash string, ity *imageTypesYAML) { + i.mu.Lock() + defer i.mu.Unlock() + + i.cache[hash] = ity +} + +var ( + itCache = newImageTypesCache() +) + +func load(distroNameVer string) (*imageTypesYAML, error) { + id, err := distro.ParseID(distroNameVer) + if err != nil { + return nil, err } // XXX: this is only needed temporary until we have a "distros.yaml" // that describes some high-level properties of each distro // (like their yaml dirs) var baseDir string - switch distroName { - case "rhel": + switch id.Name { + case "rhel", "almalinux", "centos", "almalinux_kitten": // rhel yaml files are under ./rhel-$majorVer - baseDir = distroNameMajorVer - case "almalinux": // almalinux yaml is just rhel, we take only its major version - baseDir = fmt.Sprintf("rhel-%s", distroMajorVer) - case "centos", "almalinux_kitten": // centos and kitten yaml is just rhel but we have (sadly) no // symlinks in "go:embed" so we have to have this slightly ugly // workaround - baseDir = fmt.Sprintf("rhel-%s", distroVersion) - case "fedora", "test-distro": + baseDir = fmt.Sprintf("rhel-%v", id.MajorVersion) + case "test-distro": // our other distros just have a single yaml dir per distro // and use condition.version_gt etc - baseDir = distroName - default: - return nil, fmt.Errorf("unsupported distro in loader %q (add to loader.go)", distroName) + baseDir = id.Name } - f, err := dataFS.Open(filepath.Join(baseDir, "distro.yaml")) + // take the base path from the distros.yaml + distro, err := Distro(distroNameVer) + if err != nil && !os.IsNotExist(err) { + return nil, err + } + if distro != nil && distro.DefsPath != "" { + baseDir = distro.DefsPath + } + + f, err := dataFS().Open(filepath.Join(baseDir, "distro.yaml")) if err != nil { return nil, err } defer f.Close() - decoder := yaml.NewDecoder(f) - decoder.KnownFields(true) + // XXX: this is currently needed because rhel distros call + // ImageType() and ParitionTable() a gazillion times and + // each time the full yaml is loaded. Once things move to + // the "generic" distro this will no longer be the case and + // this cache can be removed and below we can decode directly + // from "f" again instead of wasting memory with "buf" + var buf bytes.Buffer + h := sha256.New() + if _, err := io.Copy(io.MultiWriter(&buf, h), f); err != nil { + return nil, fmt.Errorf("cannot read from %s: %w", baseDir, err) + } + inputHash := string(h.Sum(nil)) + if cached := itCache.Get(inputHash); cached != nil { + return cached, nil + } - // each imagetype can have multiple package sets, so that we can - // use yaml aliases/anchors to de-duplicate them - var toplevel toplevelYAML + var toplevel imageTypesYAML + decoder := yaml.NewDecoder(&buf) + decoder.KnownFields(true) if err := decoder.Decode(&toplevel); err != nil { return nil, err } + // XXX: remove once we no longer need caching + itCache.Set(inputHash, &toplevel) + return &toplevel, nil } // ImageConfig returns the image type specific ImageConfig -func ImageConfig(distroNameVer, archName, typeName string, replacements map[string]string) (*distro.ImageConfig, error) { +func ImageConfig(distroNameVer, archName, typeName string) (*distro.ImageConfig, error) { toplevel, err := load(distroNameVer) if err != nil { return nil, err @@ -432,20 +614,21 @@ func ImageConfig(distroNameVer, archName, typeName string, replacements map[stri imgConfig := imgType.ImageConfig.ImageConfig cond := imgType.ImageConfig.Condition if cond != nil { - distroName, distroVersion := splitDistroNameVer(distroNameVer) + id, err := distro.ParseID(distroNameVer) + if err != nil { + return nil, err + } - if distroNameCnf, ok := cond.DistroName[distroName]; ok { + if distroNameCnf, ok := cond.DistroName[id.Name]; ok { imgConfig = distroNameCnf.InheritFrom(imgConfig) } if archCnf, ok := cond.Architecture[archName]; ok { imgConfig = archCnf.InheritFrom(imgConfig) } - for ltVer, ltConf := range cond.VersionLessThan { - if r, ok := replacements[ltVer]; ok { - ltVer = r - } - if common.VersionLessThan(distroVersion, ltVer) { - imgConfig = ltConf.InheritFrom(imgConfig) + for _, ltVer := range versionLessThanSortedKeys(cond.VersionLessThan) { + ltOverrides := cond.VersionLessThan[ltVer] + if common.VersionLessThan(id.VersionString(), ltVer) { + imgConfig = ltOverrides.InheritFrom(imgConfig) } } } @@ -468,7 +651,7 @@ func nNonEmpty[K comparable, V any](maps ...map[K]V) int { // InstallerConfig returns the InstallerConfig for the given imgType // Note that on conditions the InstallerConfig is fully replaced, do // any merging in YAML -func InstallerConfig(distroNameVer, archName, typeName string, replacements map[string]string) (*distro.InstallerConfig, error) { +func InstallerConfig(distroNameVer, archName, typeName string) (*distro.InstallerConfig, error) { toplevel, err := load(distroNameVer) if err != nil { return nil, err @@ -484,20 +667,21 @@ func InstallerConfig(distroNameVer, archName, typeName string, replacements map[ return nil, fmt.Errorf("only a single conditional allowed in installer config for %v", typeName) } - distroName, distroVersion := splitDistroNameVer(distroNameVer) + id, err := distro.ParseID(distroNameVer) + if err != nil { + return nil, err + } - if distroNameCnf, ok := cond.DistroName[distroName]; ok { + if distroNameCnf, ok := cond.DistroName[id.Name]; ok { installerConfig = distroNameCnf } if archCnf, ok := cond.Architecture[archName]; ok { installerConfig = archCnf } - for ltVer, ltConf := range cond.VersionLessThan { - if r, ok := replacements[ltVer]; ok { - ltVer = r - } - if common.VersionLessThan(distroVersion, ltVer) { - installerConfig = ltConf + for _, ltVer := range versionLessThanSortedKeys(cond.VersionLessThan) { + ltOverrides := cond.VersionLessThan[ltVer] + if common.VersionLessThan(id.VersionString(), ltVer) { + installerConfig = ltOverrides } } } diff --git a/vendor/github.com/osbuild/images/pkg/distro/defs/rhel-10/distro.yaml b/vendor/github.com/osbuild/images/pkg/distro/defs/rhel-10/distro.yaml index 46f77178e..252f49957 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/defs/rhel-10/distro.yaml +++ b/vendor/github.com/osbuild/images/pkg/distro/defs/rhel-10/distro.yaml @@ -86,7 +86,8 @@ value: "4194304" - key: "vm.max_map_count" value: "2147483647" - dnf_set_release_ver_var: true + dnf_config: + set_release_ver_var: true sap_pkgset: &sap_pkgset include: @@ -224,6 +225,7 @@ - &filesystem_data_guid "0FC63DAF-8483-4772-8E79-3D69D8477DE4" - &xboot_ldr_partition_guid "BC13C2FF-59E6-4262-A352-B275FD6F7172" - &lvm_partition_guid "E6D6D379-F507-44C2-A23C-238F2A3DF928" + - &root_partition_x86_64_guid "4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709" # static UUIDs for partitions and filesystems # NOTE(akoutsou): These are unnecessary and have stuck around since the # beginning where (I believe) the goal was to have predictable, @@ -242,12 +244,12 @@ uuid: "D209C89E-EA5E-4FBD-B161-B461CCE297E0" type: "gpt" partitions: - - size: 1_048_576 # 1 MiB + - size: "1 MiB" bootable: true type: *bios_boot_partition_guid uuid: *bios_boot_partition_uuid - &default_partition_table_part_efi - size: 209_715_200 # 200 MiB + size: "200 MiB" type: *efi_system_partition_guid uuid: *efi_system_partition_uuid payload_type: "filesystem" @@ -260,7 +262,7 @@ fstab_freq: 0 fstab_passno: 2 - &default_partition_table_part_root - size: 2_147_483_648 # 2 * datasizes.GibiByte, + size: "2 GiB" type: *filesystem_data_guid uuid: *root_partition_uuid payload_type: "filesystem" @@ -281,11 +283,11 @@ uuid: "0x14fc63d2" type: "dos" partitions: - - size: 4_194_304 # 4 MiB + - size: "4 MiB" bootable: true type: *prep_partition_dosid - &default_partition_table_part_root_ppc64le - size: 2_147_483_648 # 2 * datasizes.GibiByte, + size: "2 GiB" payload_type: "filesystem" payload: <<: *default_partition_table_part_root_payload @@ -297,6 +299,193 @@ - <<: *default_partition_table_part_root_ppc64le bootable: true + azure_image_config: &azure_image_config + # from CreateAzureDatalossWarningScriptAndUnit + files: + - path: &dataloss_script "/usr/local/sbin/temp-disk-dataloss-warning" + mode: 0755 + data: | + #!/bin/sh + # /usr/local/sbin/temp-disk-dataloss-warning + # Write dataloss warning file on mounted Azure resource disk + + AZURE_RESOURCE_DISK_PART1="/dev/disk/cloud/azure_resource-part1" + + MOUNTPATH=$(grep "$AZURE_RESOURCE_DISK_PART1" /etc/fstab | tr '\t' ' ' | cut -d' ' -f2) + if [ -z "$MOUNTPATH" ]; then + echo "There is no mountpoint of $AZURE_RESOURCE_DISK_PART1 in /etc/fstab" + exit 0 + fi + + if [ "$MOUNTPATH" = "none" ]; then + echo "Mountpoint of $AZURE_RESOURCE_DISK_PART1 is not a path" + exit 1 + fi + + if ! mountpoint -q "$MOUNTPATH"; then + echo "$AZURE_RESOURCE_DISK_PART1 is not mounted at $MOUNTPATH" + exit 1 + fi + + echo "Creating a dataloss warning file at ${MOUNTPATH}/DATALOSS_WARNING_README.txt" + + cat <<'EOF' > "${MOUNTPATH}/DATALOSS_WARNING_README.txt" + WARNING: THIS IS A TEMPORARY DISK. + + Any data stored on this drive is SUBJECT TO LOSS and THERE IS NO WAY TO RECOVER IT. + + Please do not use this disk for storing any personal or application data. + + EOF + systemd_unit: + - filename: &dataloss_systemd_unit_filename "temp-disk-dataloss-warning.service" + "unit-type": "system" + "unit-path": "etc" + config: + "Unit": + Description: "Azure temporary resource disk dataloss warning file creation" + After: ["multi-user.target", "cloud-final.service"] + "Service": + Type: "oneshot" + ExecStart: [*dataloss_script] + StandardOutput: "journal+console" + "Install": + WantedBy: ["default.target"] + keyboard: + keymap: "us" + "x11-keymap": + layouts: ["us"] + update_default_kernel: true + default_kernel: "kernel-core" + sysconfig: + networking: true + no_zero_conf: true + enabled_services: + - "firewalld" + - "nm-cloud-setup.service" + - "nm-cloud-setup.timer" + - "sshd" + - "waagent" + - *dataloss_systemd_unit_filename + sshd_config: + config: + ClientAliveInterval: 180 + modprobe: + - filename: "blacklist-amdgpu.conf" + commands: + - command: blacklist + modulename: "amdgpu" + - filename: "blacklist-intel-cstate.conf" + commands: + - command: blacklist + modulename: "intel_cstate" + - filename: "blacklist-floppy.conf" + commands: + - command: blacklist + modulename: "floppy" + - filename: "blacklist-nouveau.conf" + commands: + - command: blacklist + modulename: "nouveau" + - command: blacklist + modulename: "lbm-nouveau" + - filename: "blacklist-skylake-edac.conf" + commands: + - command: blacklist + modulename: "skx_edac" + - filename: "blacklist-intel_uncore.conf" + commands: + - command: blacklist + modulename: "intel_uncore" + - filename: "blacklist-acpi_cpufreq.conf" + commands: + - command: blacklist + modulename: "acpi_cpufreq" + pwquality: + config: + minlen: 6 + minclass: 3 + dcredit: 0 + ucredit: 0 + lcredit: 0 + ocredit: 0 + waagent_config: + config: + "ResourceDisk.Format": false + "ResourceDisk.EnableSwap": false + "Provisioning.UseCloudInit": true + "Provisioning.Enabled": false + grub2_config: + disable_recovery: true + disable_submenu: true + distributor: "$(sed 's, release .*$,,g' /etc/system-release)" + terminal: ["serial", "console"] + serial: "serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1" + timeout: 10 + timeout_style: "countdown" + udev_rules: + filename: "/etc/udev/rules.d/68-azure-sriov-nm-unmanaged.rules" + rules: + - comment: + - "Accelerated Networking on Azure exposes a new SRIOV interface to the VM." + - "This interface is transparently bonded to the synthetic interface," + - "so NetworkManager should just ignore any SRIOV interfaces." + - rule: + - K: "SUBSYSTEM" + O: "==" + V: "net" + - K: "DRIVERS" + O: "==" + V: "hv_pci" + - K: "ACTION" + O: "==" + V: "add" + - K: "ENV" + A: "NM_UNMANAGED" + O: "=" + V: "1" + systemd_dropin: + - unit: "nm-cloud-setup.service" + dropin: "10-rh-enable-for-azure.conf" + config: + service: + environment: + - key: "NM_CLOUD_SETUP_AZURE" + value: "yes" + default_target: "multi-user.target" + network_manager: + path: "/etc/NetworkManager/conf.d/99-azure-unmanaged-devices.conf" + settings: + keyfile: + "unmanaged-devices": + - "driver:mlx4_core" + - "driver:mlx5_core" + condition: + distro_name: + rhel: + gpgkey_files: + - "/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release" + architecture: + x86_64: + kernel_options: + # common + - "ro" + - "loglevel=3" + - "nvme_core.io_timeout=240" + # x86 + - "console=tty1" + - "console=ttyS0" + - "earlyprintk=ttyS0" + - "rootdelay=300" + aarch64: + kernel_options: + # common + - "ro" + - "loglevel=3" + - "nvme_core.io_timeout=240" + # aarch64 + - "console=ttyAMA0" + image_config: default: default_kernel: "kernel" @@ -450,107 +639,15 @@ image_types: vhd: &vhd # based on https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/deploying_rhel_9_on_microsoft_azure/assembly_deploying-a-rhel-image-as-a-virtual-machine-on-microsoft-azure_cloud-content-azure#making-configuration-changes_configure-the-image-azure image_config: &image_config_vhd - # from CreateAzureDatalossWarningScriptAndUnit - files: - - path: &dataloss_script "/usr/local/sbin/temp-disk-dataloss-warning" - mode: 0755 - data: | - #!/bin/sh - # /usr/local/sbin/temp-disk-dataloss-warning - # Write dataloss warning file on mounted Azure resource disk - - AZURE_RESOURCE_DISK_PART1="/dev/disk/cloud/azure_resource-part1" - - MOUNTPATH=$(grep "$AZURE_RESOURCE_DISK_PART1" /etc/fstab | tr '\t' ' ' | cut -d' ' -f2) - if [ -z "$MOUNTPATH" ]; then - echo "There is no mountpoint of $AZURE_RESOURCE_DISK_PART1 in /etc/fstab" - exit 0 - fi - - if [ "$MOUNTPATH" = "none" ]; then - echo "Mountpoint of $AZURE_RESOURCE_DISK_PART1 is not a path" - exit 1 - fi - - if ! mountpoint -q "$MOUNTPATH"; then - echo "$AZURE_RESOURCE_DISK_PART1 is not mounted at $MOUNTPATH" - exit 1 - fi - - echo "Creating a dataloss warning file at ${MOUNTPATH}/DATALOSS_WARNING_README.txt" - - cat <<'EOF' > "${MOUNTPATH}/DATALOSS_WARNING_README.txt" - WARNING: THIS IS A TEMPORARY DISK. - - Any data stored on this drive is SUBJECT TO LOSS and THERE IS NO WAY TO RECOVER IT. - - Please do not use this disk for storing any personal or application data. - - EOF - systemd_unit: - - filename: &dataloss_systemd_unit_filename "temp-disk-dataloss-warning.service" - "unit-type": "system" - "unit-path": "etc" - config: - "Unit": - Description: "Azure temporary resource disk dataloss warning file creation" - After: ["multi-user.target", "cloud-final.service"] - "Service": - Type: "oneshot" - ExecStart: [*dataloss_script] - StandardOutput: "journal+console" - "Install": - WantedBy: ["default.target"] - keyboard: - keymap: "us" - "x11-keymap": - layouts: ["us"] - update_default_kernel: true - default_kernel: "kernel-core" - sysconfig: - networking: true - no_zero_conf: true - enabled_services: - - "firewalld" - - "nm-cloud-setup.service" - - "nm-cloud-setup.timer" - - "sshd" - - "waagent" - - *dataloss_systemd_unit_filename - sshd_config: - config: - ClientAliveInterval: 180 - modprobe: - - filename: "blacklist-amdgpu.conf" - commands: - - command: blacklist - modulename: "amdgpu" - - filename: "blacklist-intel-cstate.conf" - commands: - - command: blacklist - modulename: "intel_cstate" - - filename: "blacklist-floppy.conf" - commands: - - command: blacklist - modulename: "floppy" - - filename: "blacklist-nouveau.conf" - commands: - - command: blacklist - modulename: "nouveau" - - command: blacklist - modulename: "lbm-nouveau" - - filename: "blacklist-skylake-edac.conf" - commands: - - command: blacklist - modulename: "skx_edac" - - filename: "blacklist-intel_uncore.conf" - commands: - - command: blacklist - modulename: "intel_uncore" - - filename: "blacklist-acpi_cpufreq.conf" - commands: - - command: blacklist - modulename: "acpi_cpufreq" + <<: *azure_image_config + time_synchronization: + refclocks: + - driver: + name: "PHC" + path: "/dev/ptp_hyperv" + poll: 3 + dpoll: -2 + offset: 0.0 cloud_init: - filename: "10-azure-kvp.cfg" config: @@ -566,98 +663,6 @@ image_types: apply_network_config: false datasource_list: - "Azure" - pwquality: - config: - minlen: 6 - minclass: 3 - dcredit: 0 - ucredit: 0 - lcredit: 0 - ocredit: 0 - waagent_config: - config: - "ResourceDisk.Format": false - "ResourceDisk.EnableSwap": false - "Provisioning.UseCloudInit": true - "Provisioning.Enabled": false - grub2_config: - disable_recovery: true - disable_submenu: true - distributor: "$(sed 's, release .*$,,g' /etc/system-release)" - terminal: ["serial", "console"] - serial: "serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1" - timeout: 10 - timeout_style: "countdown" - udev_rules: - filename: "/etc/udev/rules.d/68-azure-sriov-nm-unmanaged.rules" - rules: - - comment: - - "Accelerated Networking on Azure exposes a new SRIOV interface to the VM." - - "This interface is transparently bonded to the synthetic interface," - - "so NetworkManager should just ignore any SRIOV interfaces." - - rule: - - K: "SUBSYSTEM" - O: "==" - V: "net" - - K: "DRIVERS" - O: "==" - V: "hv_pci" - - K: "ACTION" - O: "==" - V: "add" - - K: "ENV" - A: "NM_UNMANAGED" - O: "=" - V: "1" - systemd_dropin: - - unit: "nm-cloud-setup.service" - dropin: "10-rh-enable-for-azure.conf" - config: - service: - environment: - - key: "NM_CLOUD_SETUP_AZURE" - value: "yes" - default_target: "multi-user.target" - time_synchronization: - refclocks: - - driver: - name: "PHC" - path: "/dev/ptp_hyperv" - poll: 3 - dpoll: -2 - offset: 0.0 - network_manager: - path: "/etc/NetworkManager/conf.d/99-azure-unmanaged-devices.conf" - settings: - keyfile: - "unmanaged-devices": - - "driver:mlx4_core" - - "driver:mlx5_core" - condition: - distro_name: - rhel: - gpgkey_files: - - "/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release" - architecture: - x86_64: - kernel_options: - # common - - "ro" - - "loglevel=3" - - "nvme_core.io_timeout=240" - # x86 - - "console=tty1" - - "console=ttyS0" - - "earlyprintk=ttyS0" - - "rootdelay=300" - aarch64: - kernel_options: - # common - - "ro" - - "loglevel=3" - - "nvme_core.io_timeout=240" - # aarch64 - - "console=ttyAMA0" partition_table: <<: *default_partition_tables package_sets: @@ -746,10 +751,10 @@ image_types: x86_64: uuid: "D209C89E-EA5E-4FBD-B161-B461CCE297E0" type: "gpt" - size: 68_719_476_736 # 64 * datasizes.GibiByte + size: "64 GiB" partitions: - &azure_rhui_part_boot_efi - size: 524_288_000 # 500 * datasizes.MebiByte + size: "500 MiB" type: *efi_system_partition_guid UUID: *efi_system_partition_uuid payload_type: "filesystem" @@ -762,7 +767,7 @@ image_types: fstab_passno: 2 # NB: we currently don't support /boot on LVM - &azure_rhui_part_boot - size: 1_073_741_824 # 1 * datasizes.GibiByte + size: "1 GiB" type: *filesystem_data_guid uuid: *data_partition_uuid payload_type: "filesystem" @@ -772,7 +777,7 @@ image_types: fstab_options: "defaults" fstab_freq: 0 fstab_passno: 0 - - size: 2_097_152 # 2 * datasizes.MebiByte + - size: "2 MiB" bootable: true type: *bios_boot_partition_guid uuid: *bios_boot_partition_uuid @@ -784,7 +789,7 @@ image_types: name: "rootvg" description: "built with lvm2 and osbuild" logical_volumes: - - size: 1_073_741_824 # 1 * datasizes.GibiByte + - size: "1 GiB" name: "homelv" payload_type: "filesystem" payload: @@ -792,7 +797,7 @@ image_types: label: "home" mountpoint: "/home" fstab_options: "defaults" - - size: 2_147_483_648 # 2 * datasizes.GibiByte + - size: "2 GiB" name: "rootlv" payload_type: "filesystem" payload: @@ -800,7 +805,7 @@ image_types: label: "root" mountpoint: "/" fstab_options: "defaults" - - size: 2_147_483_648 # 2 * datasizes.GibiByte + - size: "2 GiB" name: "tmplv" payload_type: "filesystem" payload: @@ -808,7 +813,7 @@ image_types: label: "tmp" mountpoint: "/tmp" fstab_options: "defaults" - - size: 10_737_418_240 # 10 * datasizes.GibiByte + - size: "10 GiB" name: "usrlv" payload_type: "filesystem" payload: @@ -816,7 +821,7 @@ image_types: label: "usr" mountpoint: "/usr" fstab_options: "defaults" - - size: 10_737_418_240 # 10 * datasizes.GibiByte + - size: "10 GiB" name: "varlv" payload_type: "filesystem" payload: @@ -827,7 +832,7 @@ image_types: aarch64: uuid: "D209C89E-EA5E-4FBD-B161-B461CCE297E0" type: "gpt" - size: 68_719_476_736 # 64 * datasizes.GibiByte + size: "64 GiB" partitions: - *azure_rhui_part_boot_efi # NB: we currently don't support /boot on LVM @@ -1283,9 +1288,10 @@ image_types: keyboard: keymap: "us" dnf_config: - - config: - main: - ipresolve: "4" + options: + - config: + main: + ipresolve: "4" dnf_automatic_config: config: commands: @@ -1415,3 +1421,69 @@ image_types: rhel: include: - "insights-client" + + "azure-cvm": + image_config: + <<: *azure_image_config + default_kernel: "kernel-uki-virt" + default_kernel_name: "kernel-uki-virt" + no_bls: true + cloud_init: + - filename: "91-azure_datasource.cfg" + config: + datasource: + azure: + apply_network_config: false + datasource_list: + - "Azure" + package_sets: + os: + - include: + - "@minimal-environment" + - "chrony" + - "cloud-init" + - "cloud-utils-growpart" + - "cryptsetup" + - "NetworkManager-cloud-setup" + - "openssh-server" + - "redhat-cloud-client-configuration" + - "redhat-release" + - "tpm2-tools" + - "WALinuxAgent" + - exclude: + - "dracut-config-rescue" + - "grubby" + - "iwl*" + # In EL9 we exclude linux-firmware* (note the asterisk). + # In EL10, packages in the minimal-environment group require + # linux-firmware-whence, so we only exclude the linux-firmware + # package here. + - "linux-firmware" + - "os-prober" + partition_table: + x86_64: + uuid: "D209C89E-EA5E-4FBD-B161-B461CCE297E0" + type: "gpt" + partitions: + - size: 264_241_152 # 52 MiB + type: *efi_system_partition_guid + uuid: *efi_system_partition_uuid + payload_type: "filesystem" + payload: + type: vfat + uuid: *efi_filesystem_uuid + mountpoint: "/boot/efi" + label: "ESP" + fstab_options: "defaults,uid=0,gid=0,umask=077,shortname=winnt" + fstab_freq: 0 + fstab_passno: 2 + - size: 5_368_709_120 # 5 * datasizes.GibiByte, + type: *root_partition_x86_64_guid + payload_type: "filesystem" + payload: + type: "ext4" + label: "root" + mountpoint: "/" + fstab_options: "defaults" + fstab_freq: 0 + fstab_passno: 0 diff --git a/vendor/github.com/osbuild/images/pkg/distro/defs/rhel-7/distro.yaml b/vendor/github.com/osbuild/images/pkg/distro/defs/rhel-7/distro.yaml index 1c1cd780b..078bf67ef 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/defs/rhel-7/distro.yaml +++ b/vendor/github.com/osbuild/images/pkg/distro/defs/rhel-7/distro.yaml @@ -72,12 +72,12 @@ uuid: "D209C89E-EA5E-4FBD-B161-B461CCE297E0" type: "gpt" partitions: - - size: 1_048_576 # 1 MiB + - size: "1 MiB" bootable: true type: *bios_boot_partition_guid uuid: *bios_boot_partition_uuid - &default_partition_table_part_efi - size: 209_715_200 # 200 MiB + size: "200 MiB" type: *efi_system_partition_guid uuid: *efi_system_partition_uuid payload_type: "filesystem" @@ -90,7 +90,7 @@ fstab_freq: 0 fstab_passno: 2 - &default_partition_table_part_boot - size: 524_288_000 # 500 * MiB + size: "500 MiB" type: *filesystem_data_guid uuid: *data_partition_uuid payload_type: "filesystem" @@ -102,7 +102,7 @@ fstab_freq: 0 fstab_passno: 0 - &default_partition_table_part_root - size: 2_147_483_648 # 2 * datasizes.GibiByte, + size: "2 GiB" type: *filesystem_data_guid uuid: *root_partition_uuid payload_type: "filesystem" diff --git a/vendor/github.com/osbuild/images/pkg/distro/defs/rhel-8/distro.yaml b/vendor/github.com/osbuild/images/pkg/distro/defs/rhel-8/distro.yaml index 9daac3ef3..0ea5dc9be 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/defs/rhel-8/distro.yaml +++ b/vendor/github.com/osbuild/images/pkg/distro/defs/rhel-8/distro.yaml @@ -555,12 +555,12 @@ partitions: - &default_partition_table_part_bios - size: 1_048_576 # 1 MiB + size: "1 MiB" bootable: true type: *bios_boot_partition_guid uuid: *bios_boot_partition_uuid - &default_partition_table_part_efi - size: 104_857_600 # 100 MiB + size: "100 MiB" type: *efi_system_partition_guid uuid: *efi_system_partition_uuid payload_type: "filesystem" @@ -573,7 +573,7 @@ fstab_freq: 0 fstab_passno: 2 - &default_partition_table_part_root - size: 2_147_483_648 # 2 * datasizes.GibiByte, + size: "2 GiB" type: *filesystem_data_guid uuid: *root_partition_uuid payload_type: "filesystem" @@ -586,7 +586,7 @@ fstab_passno: 0 # ec2 - &ec2_partition_table_part_boot - size: 1_073_741_824 # 1 GiB + size: "1 GiB" type: *filesystem_data_guid uuid: *data_partition_uuid payload_type: "filesystem" @@ -598,7 +598,7 @@ fstab_passno: 0 - &ec2_partition_table_part_boot512 <<: *ec2_partition_table_part_boot - size: 536_870_912 # 512MiB + size: "512 MiB" default_partition_tables: &default_partition_tables x86_64: @@ -618,11 +618,11 @@ uuid: "0x14fc63d2" type: "dos" partitions: - - size: 4_194_304 # 4 MiB + - size: "4 MiB" bootable: true type: *prep_partition_dosid - &default_partition_table_part_root_ppc64le - size: 2_147_483_648 # 2 * datasizes.GibiByte, + size: "2 GiB" payload_type: "filesystem" payload: <<: *default_partition_table_part_root_payload @@ -641,7 +641,7 @@ partitions: - *default_partition_table_part_bios - &edge_base_partition_table_part_efi - size: 133_169_152 # 127 MiB + size: "127 MiB" type: *efi_system_partition_guid uuid: *efi_system_partition_uuid payload_type: "filesystem" @@ -654,7 +654,7 @@ fstab_freq: 0 fstab_passno: 2 - &edge_base_partition_table_part_boot - size: 402_653_184 # 384 * MiB + size: "384 MiB" type: *filesystem_data_guid uuid: *data_partition_uuid payload_type: "filesystem" @@ -666,7 +666,7 @@ fstab_freq: 1 fstab_passno: 1 - &edge_base_partition_table_part_root - size: 2_147_483_648 # 2 * datasizes.GibiByte, + size: "2 GiB" type: *filesystem_data_guid uuid: *root_partition_uuid payload_type: "luks" @@ -707,7 +707,7 @@ partitions: - *default_partition_table_part_bios - &ec2_partition_table_part_efi - size: 209_715_200 # 200 MiB + size: "200 MiB" type: *efi_system_partition_guid uuid: *efi_system_partition_uuid payload_type: "filesystem" @@ -720,7 +720,7 @@ fstab_freq: 0 fstab_passno: 2 - &ec2_partition_table_part_root - size: 2_147_483_648 # 2 * datasizes.GibiByte, + size: "2 GiB" type: *filesystem_data_guid uuid: *root_partition_uuid payload_type: "filesystem" diff --git a/vendor/github.com/osbuild/images/pkg/distro/defs/rhel-9/distro.yaml b/vendor/github.com/osbuild/images/pkg/distro/defs/rhel-9/distro.yaml index 032b1b110..067baffc5 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/defs/rhel-9/distro.yaml +++ b/vendor/github.com/osbuild/images/pkg/distro/defs/rhel-9/distro.yaml @@ -391,12 +391,12 @@ partitions: - &default_partition_table_part_bios - size: 1_048_576 # 1 MiB + size: "1 MiB" bootable: true type: *bios_boot_partition_guid uuid: *bios_boot_partition_uuid - &default_partition_table_part_efi - size: 209_715_200 # 200 MiB + size: "200 MiB" type: *efi_system_partition_guid uuid: *efi_system_partition_uuid payload_type: "filesystem" @@ -409,7 +409,7 @@ fstab_freq: 0 fstab_passno: 2 - &default_partition_table_part_boot - size: 1_073_741_824 # 1 GiB + size: "1 GiB" type: *xboot_ldr_partition_guid uuid: *data_partition_uuid payload_type: "filesystem" @@ -421,7 +421,7 @@ fstab_freq: 0 fstab_passno: 0 - &default_partition_table_part_root - size: 2_147_483_648 # 2 * datasizes.GibiByte, + size: "2 GiB" type: *filesystem_data_guid uuid: *root_partition_uuid payload_type: "filesystem" @@ -434,22 +434,22 @@ fstab_passno: 0 # ppc64 - &default_partition_table_part_bios_ppc64le - size: 4_194_304 # 4 MiB + size: "4 MiB" bootable: true type: *prep_partition_dosid - &default_partition_table_part_boot_ppc64le - size: 1_073_741_824 # 1 GiB + size: "1 GiB" payload_type: "filesystem" payload: <<: *default_partition_table_part_boot_payload - &default_partition_table_part_boot512_ppc64le <<: *default_partition_table_part_boot_ppc64le - size: 524_288_000 # 500 MiB + size: "500 MiB" - &default_partition_table_part_boot600_ppc64le <<: *default_partition_table_part_boot_ppc64le - size: 629_145_600 # 600 MiB + size: "600 MiB" - &default_partition_table_part_root_ppc64le - size: 2_147_483_648 # 2 * datasizes.GibiByte, + size: "2 GiB" payload_type: "filesystem" payload: <<: *default_partition_table_part_root_payload @@ -1182,3 +1182,25 @@ image_types: *edge_commit_x86_64_pkgset aarch64: *edge_commit_aarch64_pkgset + + "azure-cvm": + package_sets: + os: + - include: + - "@minimal-environment" + - "chrony" + - "cloud-init" + - "cloud-utils-growpart" + - "cryptsetup" + - "NetworkManager-cloud-setup" + - "openssh-server" + - "redhat-cloud-client-configuration" + - "redhat-release" + - "tpm2-tools" + - "WALinuxAgent" + - exclude: + - "dracut-config-rescue" + - "iwl*" + - "linux-firmware*" + - "grubby" + - "os-prober" diff --git a/vendor/github.com/osbuild/images/pkg/distro/fedora/distro.go b/vendor/github.com/osbuild/images/pkg/distro/fedora/distro.go deleted file mode 100644 index 10ddaa279..000000000 --- a/vendor/github.com/osbuild/images/pkg/distro/fedora/distro.go +++ /dev/null @@ -1,290 +0,0 @@ -package fedora - -import ( - "errors" - "fmt" - "sort" - "strconv" - - "github.com/osbuild/images/internal/common" - "github.com/osbuild/images/pkg/arch" - "github.com/osbuild/images/pkg/customizations/oscap" - "github.com/osbuild/images/pkg/distro" - "github.com/osbuild/images/pkg/distro/defs" - "github.com/osbuild/images/pkg/platform" - "github.com/osbuild/images/pkg/runner" -) - -const ( - // package set names - - // main/common os image package set name - osPkgsKey = "os" - - // container package set name - containerPkgsKey = "container" - - // installer package set name - installerPkgsKey = "installer" - - // blueprint package set name - blueprintPkgsKey = "blueprint" -) - -var ( - oscapProfileAllowList = []oscap.Profile{ - oscap.Ospp, - oscap.PciDss, - oscap.Standard, - } -) - -type distribution struct { - name string - product string - osVersion string - releaseVersion string - modulePlatformID string - ostreeRefTmpl string - runner runner.Runner - arches map[string]distro.Arch - defaultImageConfig *distro.ImageConfig -} - -func getISOLabelFunc(variant string) isoLabelFunc { - const ISO_LABEL = "%s-%s-%s-%s" - - return func(t *imageType) string { - return fmt.Sprintf(ISO_LABEL, t.Arch().Distro().Product(), t.Arch().Distro().OsVersion(), variant, t.Arch().Name()) - } - -} - -func getDistro(version int) distribution { - if version < 0 { - panic("Invalid Fedora version (must be positive)") - } - nameVer := fmt.Sprintf("fedora-%d", version) - return distribution{ - name: nameVer, - product: "Fedora", - osVersion: strconv.Itoa(version), - releaseVersion: strconv.Itoa(version), - modulePlatformID: fmt.Sprintf("platform:f%d", version), - ostreeRefTmpl: fmt.Sprintf("fedora/%d/%%s/iot", version), - runner: &runner.Fedora{Version: uint64(version)}, - defaultImageConfig: common.Must(defs.DistroImageConfig(nameVer)), - } -} - -func (d *distribution) Name() string { - return d.name -} - -func (d *distribution) Codename() string { - return "" // Fedora does not use distro codename -} - -func (d *distribution) Releasever() string { - return d.releaseVersion -} - -func (d *distribution) OsVersion() string { - return d.releaseVersion -} - -func (d *distribution) Product() string { - return d.product -} - -func (d *distribution) ModulePlatformID() string { - return d.modulePlatformID -} - -func (d *distribution) OSTreeRef() string { - return d.ostreeRefTmpl -} - -func (d *distribution) ListArches() []string { - archNames := make([]string, 0, len(d.arches)) - for name := range d.arches { - archNames = append(archNames, name) - } - sort.Strings(archNames) - return archNames -} - -func (d *distribution) GetArch(name string) (distro.Arch, error) { - arch, exists := d.arches[name] - if !exists { - return nil, errors.New("invalid architecture: " + name) - } - return arch, nil -} - -func (d *distribution) addArches(arches ...architecture) { - if d.arches == nil { - d.arches = map[string]distro.Arch{} - } - - // Do not make copies of architectures, as opposed to image types, - // because architecture definitions are not used by more than a single - // distro definition. - for idx := range arches { - d.arches[arches[idx].name] = &arches[idx] - } -} - -func (d *distribution) getDefaultImageConfig() *distro.ImageConfig { - return d.defaultImageConfig -} - -type architecture struct { - distro *distribution - name string - imageTypes map[string]distro.ImageType - imageTypeAliases map[string]string -} - -func (a *architecture) Name() string { - return a.name -} - -func (a *architecture) ListImageTypes() []string { - itNames := make([]string, 0, len(a.imageTypes)) - for name := range a.imageTypes { - itNames = append(itNames, name) - } - sort.Strings(itNames) - return itNames -} - -func (a *architecture) GetImageType(name string) (distro.ImageType, error) { - t, exists := a.imageTypes[name] - if !exists { - aliasForName, exists := a.imageTypeAliases[name] - if !exists { - return nil, errors.New("invalid image type: " + name) - } - t, exists = a.imageTypes[aliasForName] - if !exists { - panic(fmt.Sprintf("image type '%s' is an alias to a non-existing image type '%s'", name, aliasForName)) - } - } - return t, nil -} - -func (a *architecture) addImageTypes(platform platform.Platform, imageTypes ...imageType) { - if a.imageTypes == nil { - a.imageTypes = map[string]distro.ImageType{} - } - for idx := range imageTypes { - it := imageTypes[idx] - it.arch = a - it.platform = platform - a.imageTypes[it.name] = &it - for _, alias := range it.nameAliases { - if a.imageTypeAliases == nil { - a.imageTypeAliases = map[string]string{} - } - if existingAliasFor, exists := a.imageTypeAliases[alias]; exists { - panic(fmt.Sprintf("image type alias '%s' for '%s' is already defined for another image type '%s'", alias, it.name, existingAliasFor)) - } - a.imageTypeAliases[alias] = it.name - } - } -} - -func (a *architecture) Distro() distro.Distro { - return a.distro -} - -func newDistro(version int) distro.Distro { - rd := getDistro(version) - - // XXX: generate architecture automatically from the imgType yaml - x86_64 := architecture{ - name: arch.ARCH_X86_64.String(), - distro: &rd, - } - - aarch64 := architecture{ - name: arch.ARCH_AARCH64.String(), - distro: &rd, - } - - ppc64le := architecture{ - distro: &rd, - name: arch.ARCH_PPC64LE.String(), - } - - s390x := architecture{ - distro: &rd, - name: arch.ARCH_S390X.String(), - } - - riscv64 := architecture{ - name: arch.ARCH_RISCV64.String(), - distro: &rd, - } - - // XXX: move all image types should to YAML - its, err := defs.ImageTypes(rd.name) - if err != nil { - panic(err) - } - for _, imgTypeYAML := range its { - // use as marker for images that are not converted to - // YAML yet - if imgTypeYAML.Filename == "" { - continue - } - it := newImageTypeFrom(rd, imgTypeYAML) - for _, pl := range imgTypeYAML.Platforms { - switch pl.Arch { - case arch.ARCH_X86_64: - x86_64.addImageTypes(&pl, it) - case arch.ARCH_AARCH64: - aarch64.addImageTypes(&pl, it) - case arch.ARCH_PPC64LE: - ppc64le.addImageTypes(&pl, it) - case arch.ARCH_S390X: - s390x.addImageTypes(&pl, it) - case arch.ARCH_RISCV64: - riscv64.addImageTypes(&pl, it) - default: - err := fmt.Errorf("unsupported arch: %v", pl.Arch) - panic(err) - } - } - } - - rd.addArches(x86_64, aarch64, ppc64le, s390x, riscv64) - return &rd -} - -func ParseID(idStr string) (*distro.ID, error) { - id, err := distro.ParseID(idStr) - if err != nil { - return nil, err - } - - if id.Name != "fedora" { - return nil, fmt.Errorf("invalid distro name: %s", id.Name) - } - - if id.MinorVersion != -1 { - return nil, fmt.Errorf("fedora distro does not support minor versions") - } - - return id, nil -} - -func DistroFactory(idStr string) distro.Distro { - id, err := ParseID(idStr) - if err != nil { - return nil - } - - return newDistro(id.MajorVersion) -} diff --git a/vendor/github.com/osbuild/images/pkg/distro/fedora/package_sets.go b/vendor/github.com/osbuild/images/pkg/distro/fedora/package_sets.go deleted file mode 100644 index 0fe3e6e6b..000000000 --- a/vendor/github.com/osbuild/images/pkg/distro/fedora/package_sets.go +++ /dev/null @@ -1,80 +0,0 @@ -package fedora - -import ( - "fmt" - - "github.com/osbuild/images/internal/common" - "github.com/osbuild/images/pkg/distro" - "github.com/osbuild/images/pkg/distro/defs" - "github.com/osbuild/images/pkg/rpmmd" -) - -func packageSetLoader(t *imageType) (map[string]rpmmd.PackageSet, error) { - return defs.PackageSets(t, VersionReplacements()) -} - -func imageConfig(d distribution, imageType string) *distro.ImageConfig { - // arch is currently not used in fedora - arch := "" - return common.Must(defs.ImageConfig(d.name, arch, imageType, VersionReplacements())) -} - -func installerConfig(d distribution, imageType string) *distro.InstallerConfig { - // arch is currently not used in fedora - arch := "" - return common.Must(defs.InstallerConfig(d.name, arch, imageType, VersionReplacements())) -} - -func newImageTypeFrom(d distribution, imgYAML defs.ImageTypeYAML) imageType { - it := imageType{ - name: imgYAML.Name(), - nameAliases: imgYAML.NameAliases, - filename: imgYAML.Filename, - compression: imgYAML.Compression, - mimeType: imgYAML.MimeType, - bootable: imgYAML.Bootable, - bootISO: imgYAML.BootISO, - rpmOstree: imgYAML.RPMOSTree, - isoLabel: getISOLabelFunc(imgYAML.ISOLabel), - defaultSize: imgYAML.DefaultSize, - buildPipelines: imgYAML.BuildPipelines, - payloadPipelines: imgYAML.PayloadPipelines, - exports: imgYAML.Exports, - requiredPartitionSizes: imgYAML.RequiredPartitionSizes, - environment: &imgYAML.Environment, - } - // XXX: make this a helper on imgYAML() - it.defaultImageConfig = imageConfig(d, imgYAML.Name()) - it.defaultInstallerConfig = installerConfig(d, imgYAML.Name()) - it.packageSets = packageSetLoader - - switch imgYAML.Image { - case "disk": - it.image = diskImage - case "container": - it.image = containerImage - case "image_installer": - it.image = imageInstallerImage - case "live_installer": - it.image = liveInstallerImage - case "bootable_container": - it.image = bootableContainerImage - case "iot": - it.image = iotImage - case "iot_commit": - it.image = iotCommitImage - case "iot_container": - it.image = iotContainerImage - case "iot_installer": - it.image = iotInstallerImage - case "iot_simplified_installer": - it.image = iotSimplifiedInstallerImage - case "tar": - it.image = tarImage - default: - err := fmt.Errorf("unknown image func: %v for %v", imgYAML.Image, imgYAML.Name()) - panic(err) - } - - return it -} diff --git a/vendor/github.com/osbuild/images/pkg/distro/fedora/version.go b/vendor/github.com/osbuild/images/pkg/distro/fedora/version.go deleted file mode 100644 index b87426260..000000000 --- a/vendor/github.com/osbuild/images/pkg/distro/fedora/version.go +++ /dev/null @@ -1,15 +0,0 @@ -package fedora - -const VERSION_BRANCHED = "43" -const VERSION_RAWHIDE = "43" - -// Fedora 43 and later we reset the machine-id file to align ourselves with the -// other Fedora variants. -const VERSION_FIRSTBOOT = "43" - -func VersionReplacements() map[string]string { - return map[string]string{ - "VERSION_BRANCHED": VERSION_BRANCHED, - "VERSION_RAWHIDE": VERSION_RAWHIDE, - } -} diff --git a/vendor/github.com/osbuild/images/pkg/distro/generic/distro.go b/vendor/github.com/osbuild/images/pkg/distro/generic/distro.go new file mode 100644 index 000000000..dfc4d74de --- /dev/null +++ b/vendor/github.com/osbuild/images/pkg/distro/generic/distro.go @@ -0,0 +1,238 @@ +package generic + +import ( + "bytes" + "errors" + "fmt" + "sort" + "text/template" + + "github.com/osbuild/images/internal/common" + "github.com/osbuild/images/pkg/distro" + "github.com/osbuild/images/pkg/distro/defs" + "github.com/osbuild/images/pkg/platform" +) + +const ( + // package set names + + // main/common os image package set name + osPkgsKey = "os" + + // container package set name + containerPkgsKey = "container" + + // installer package set name + installerPkgsKey = "installer" + + // blueprint package set name + blueprintPkgsKey = "blueprint" +) + +var ( + ErrDistroNotFound = errors.New("distribution not found") +) + +// distribution implements the distro.Distro interface +var _ = distro.Distro(&distribution{}) + +type distribution struct { + defs.DistroYAML + + arches map[string]*architecture + // XXX: move into defs.DistroYAML? the downside of doing this + // is that we would have to duplicate the default image config + // accross the centos/alma/rhel distros.yaml, otherwise we + // just load it from the imagetypes file/dir and it is natually + // "in-sync" + defaultImageConfig *distro.ImageConfig +} + +func (d *distribution) getISOLabelFunc(isoLabel string) isoLabelFunc { + return func(t *imageType) string { + type inputs struct { + Product string + OsVersion string + Arch string + ImgTypeLabel string + } + templ := common.Must(template.New("iso-label").Parse(d.DistroYAML.ISOLabelTmpl)) + var buf bytes.Buffer + err := templ.Execute(&buf, inputs{ + Product: t.Arch().Distro().Product(), + OsVersion: t.Arch().Distro().OsVersion(), + Arch: t.Arch().Name(), + ImgTypeLabel: isoLabel, + }) + if err != nil { + // XXX: cleanup isoLabelFunc to allow error + panic(err) + } + return buf.String() + } +} + +func newDistro(nameVer string) (distro.Distro, error) { + distroYAML, err := defs.Distro(nameVer) + if err != nil { + return nil, err + } + if distroYAML == nil { + return nil, nil + } + + rd := &distribution{ + DistroYAML: *distroYAML, + + defaultImageConfig: common.Must(defs.DistroImageConfig(nameVer)), + arches: make(map[string]*architecture), + } + + its, err := defs.ImageTypes(rd.Name()) + if err != nil { + return nil, err + } + for _, imgTypeYAML := range its { + // use as marker for images that are not converted to + // YAML yet + if imgTypeYAML.Filename == "" { + continue + } + for _, pl := range imgTypeYAML.Platforms { + ar, ok := rd.arches[pl.Arch.String()] + if !ok { + ar = newArchitecture(rd, pl.Arch.String()) + rd.arches[pl.Arch.String()] = ar + } + it := newImageTypeFrom(rd, ar, imgTypeYAML) + if err := ar.addImageType(&pl, it); err != nil { + return nil, err + } + } + } + + return rd, nil +} + +func (d *distribution) Name() string { + return d.DistroYAML.Name +} + +func (d *distribution) Codename() string { + return d.DistroYAML.Codename +} + +func (d *distribution) Releasever() string { + return d.DistroYAML.ReleaseVersion +} + +func (d *distribution) OsVersion() string { + return d.DistroYAML.OsVersion +} + +func (d *distribution) Product() string { + return d.DistroYAML.Product +} + +func (d *distribution) ModulePlatformID() string { + return d.DistroYAML.ModulePlatformID +} + +func (d *distribution) OSTreeRef() string { + return d.DistroYAML.OSTreeRefTmpl +} + +func (d *distribution) ListArches() []string { + archNames := make([]string, 0, len(d.arches)) + for name := range d.arches { + archNames = append(archNames, name) + } + sort.Strings(archNames) + return archNames +} + +func (d *distribution) GetArch(name string) (distro.Arch, error) { + arch, exists := d.arches[name] + if !exists { + return nil, fmt.Errorf("invalid architecture: %v", name) + } + return arch, nil +} + +// architecture implements the distro.Arch interface +var _ = distro.Arch(&architecture{}) + +type architecture struct { + distro *distribution + name string + imageTypes map[string]distro.ImageType + imageTypeAliases map[string]string +} + +func newArchitecture(rd *distribution, name string) *architecture { + return &architecture{ + distro: rd, + name: name, + imageTypes: make(map[string]distro.ImageType), + imageTypeAliases: make(map[string]string), + } +} + +func (a *architecture) Name() string { + return a.name +} + +func (a *architecture) ListImageTypes() []string { + itNames := make([]string, 0, len(a.imageTypes)) + for name := range a.imageTypes { + itNames = append(itNames, name) + } + sort.Strings(itNames) + return itNames +} + +func (a *architecture) GetImageType(name string) (distro.ImageType, error) { + t, exists := a.imageTypes[name] + if !exists { + aliasForName, exists := a.imageTypeAliases[name] + if !exists { + return nil, fmt.Errorf("invalid image type: %v", name) + } + t, exists = a.imageTypes[aliasForName] + if !exists { + panic(fmt.Sprintf("image type '%s' is an alias to a non-existing image type '%s'", name, aliasForName)) + } + } + return t, nil +} + +func (a *architecture) addImageType(platform platform.Platform, it imageType) error { + it.arch = a + it.platform = platform + a.imageTypes[it.Name()] = &it + for _, alias := range it.ImageTypeYAML.NameAliases { + if a.imageTypeAliases == nil { + a.imageTypeAliases = map[string]string{} + } + if existingAliasFor, exists := a.imageTypeAliases[alias]; exists { + return fmt.Errorf("image type alias '%s' for '%s' is already defined for another image type '%s'", alias, it.Name(), existingAliasFor) + } + a.imageTypeAliases[alias] = it.Name() + } + return nil +} + +func (a *architecture) Distro() distro.Distro { + return a.distro +} + +func DistroFactory(idStr string) distro.Distro { + distro, err := newDistro(idStr) + if errors.Is(err, ErrDistroNotFound) { + return nil + } + if err != nil { + panic(err) + } + return distro +} diff --git a/vendor/github.com/osbuild/images/pkg/distro/generic/imagedefs.go b/vendor/github.com/osbuild/images/pkg/distro/generic/imagedefs.go new file mode 100644 index 000000000..d78f86b3c --- /dev/null +++ b/vendor/github.com/osbuild/images/pkg/distro/generic/imagedefs.go @@ -0,0 +1,48 @@ +package generic + +import ( + "fmt" + + "github.com/osbuild/images/internal/common" + "github.com/osbuild/images/pkg/distro/defs" +) + +func newImageTypeFrom(d *distribution, ar *architecture, imgYAML defs.ImageTypeYAML) imageType { + typName := imgYAML.Name() + it := imageType{ + ImageTypeYAML: imgYAML, + isoLabel: d.getISOLabelFunc(imgYAML.ISOLabel), + } + it.defaultImageConfig = common.Must(defs.ImageConfig(d.Name(), ar.name, typName)) + it.defaultInstallerConfig = common.Must(defs.InstallerConfig(d.Name(), ar.name, typName)) + + switch imgYAML.Image { + case "disk": + it.image = diskImage + case "container": + it.image = containerImage + case "image_installer": + it.image = imageInstallerImage + case "live_installer": + it.image = liveInstallerImage + case "bootable_container": + it.image = bootableContainerImage + case "iot": + it.image = iotImage + case "iot_commit": + it.image = iotCommitImage + case "iot_container": + it.image = iotContainerImage + case "iot_installer": + it.image = iotInstallerImage + case "iot_simplified_installer": + it.image = iotSimplifiedInstallerImage + case "tar": + it.image = tarImage + default: + err := fmt.Errorf("unknown image func: %v for %v", imgYAML.Image, imgYAML.Name()) + panic(err) + } + + return it +} diff --git a/vendor/github.com/osbuild/images/pkg/distro/fedora/images.go b/vendor/github.com/osbuild/images/pkg/distro/generic/images.go similarity index 91% rename from vendor/github.com/osbuild/images/pkg/distro/fedora/images.go rename to vendor/github.com/osbuild/images/pkg/distro/generic/images.go index 537a3051d..7a41746a9 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/fedora/images.go +++ b/vendor/github.com/osbuild/images/pkg/distro/generic/images.go @@ -1,10 +1,9 @@ -package fedora +package generic import ( "fmt" "math/rand" - "github.com/osbuild/images/internal/common" "github.com/osbuild/images/internal/workload" "github.com/osbuild/images/pkg/arch" "github.com/osbuild/images/pkg/blueprint" @@ -25,19 +24,12 @@ import ( "github.com/osbuild/images/pkg/rpmmd" ) -// HELPERS - -func osCustomizations( - t *imageType, - osPackageSet rpmmd.PackageSet, - containers []container.SourceSpec, - c *blueprint.Customizations) (manifest.OSCustomizations, error) { - +func osCustomizations(t *imageType, osPackageSet rpmmd.PackageSet, containers []container.SourceSpec, c *blueprint.Customizations) (manifest.OSCustomizations, error) { imageConfig := t.getDefaultImageConfig() osc := manifest.OSCustomizations{} - if t.bootable || t.rpmOstree { + if t.ImageTypeYAML.Bootable || t.ImageTypeYAML.RPMOSTree { osc.KernelName = c.GetKernel().Name var kernelOptions []string @@ -68,11 +60,13 @@ func osCustomizations( osc.ExcludeDocs = *imageConfig.ExcludeDocs } - if !t.bootISO { + if !t.ImageTypeYAML.BootISO { // don't put users and groups in the payload of an installer // add them via kickstart instead osc.Groups = users.GroupsFromBP(c.GetGroups()) + osc.Users = users.UsersFromBP(c.GetUsers()) + osc.Users = append(osc.Users, imageConfig.Users...) } osc.EnabledServices = imageConfig.EnabledServices @@ -159,7 +153,7 @@ func osCustomizations( // deployment, rather than the commit. Therefore the containers need to be // stored in a different location, like `/usr/share`, and the container // storage engine configured accordingly. - if t.rpmOstree && len(containers) > 0 { + if t.ImageTypeYAML.RPMOSTree && len(containers) > 0 { storagePath := "/usr/share/containers/storage" osc.ContainersStorage = &storagePath } @@ -194,7 +188,7 @@ func osCustomizations( } if oscapConfig := c.GetOpenSCAP(); oscapConfig != nil { - if t.rpmOstree { + if t.ImageTypeYAML.RPMOSTree { panic("unexpected oscap options for ostree image type") } @@ -228,7 +222,7 @@ func osCustomizations( osc.Tmpfilesd = imageConfig.Tmpfilesd osc.PamLimitsConf = imageConfig.PamLimitsConf osc.Sysctld = imageConfig.Sysctld - osc.DNFConfig = imageConfig.DNFConfigOptions(t.arch.distro.osVersion) + osc.DNFConfig = imageConfig.DNFConfigOptions(t.arch.distro.OsVersion()) osc.SshdConfig = imageConfig.SshdConfig osc.AuthConfig = imageConfig.Authconfig osc.PwQuality = imageConfig.PwQuality @@ -261,7 +255,7 @@ func ostreeDeploymentCustomizations( t *imageType, c *blueprint.Customizations) (manifest.OSTreeDeploymentCustomizations, error) { - if !t.rpmOstree || !t.bootable { + if !t.ImageTypeYAML.RPMOSTree || !t.ImageTypeYAML.Bootable { return manifest.OSTreeDeploymentCustomizations{}, fmt.Errorf("ostree deployment customizations are only supported for bootable rpm-ostree images") } @@ -349,9 +343,9 @@ func diskImage(workload workload.Workload, return nil, err } - img.Environment = t.environment + img.Environment = &t.ImageTypeYAML.Environment img.Workload = workload - img.Compression = t.compression + img.Compression = t.ImageTypeYAML.Compression if bp.Minimal { // Disable weak dependencies if the 'minimal' option is enabled img.OSCustomizations.InstallWeakDeps = false @@ -385,7 +379,7 @@ func tarImage(workload workload.Workload, return nil, err } - img.Environment = t.environment + img.Environment = &t.ImageTypeYAML.Environment img.Workload = workload img.Filename = t.Filename() @@ -410,7 +404,7 @@ func containerImage(workload workload.Workload, return nil, err } - img.Environment = t.environment + img.Environment = &t.ImageTypeYAML.Environment img.Workload = workload img.Filename = t.Filename() @@ -434,11 +428,11 @@ func liveInstallerImage(workload workload.Workload, d := t.arch.distro - img.Product = d.product + img.Product = d.Product() img.Variant = "Workstation" - img.OSVersion = d.osVersion - img.Release = fmt.Sprintf("%s %s", d.product, d.osVersion) - img.Preview = common.VersionGreaterThanOrEqual(img.OSVersion, VERSION_BRANCHED) + img.OSVersion = d.OsVersion() + img.Release = fmt.Sprintf("%s %s", d.DistroYAML.Product, d.OsVersion()) + img.Preview = d.DistroYAML.Preview var err error img.ISOLabel, err = t.ISOLabel() @@ -461,10 +455,12 @@ func liveInstallerImage(workload workload.Workload, if err != nil { return nil, err } - if installerConfig != nil { img.AdditionalDracutModules = append(img.AdditionalDracutModules, installerConfig.AdditionalDracutModules...) img.AdditionalDrivers = append(img.AdditionalDrivers, installerConfig.AdditionalDrivers...) + if installerConfig.SquashfsRootfs != nil && *installerConfig.SquashfsRootfs { + img.RootfsType = manifest.SquashfsRootfs + } } imgConfig := t.getDefaultImageConfig() @@ -534,22 +530,19 @@ func imageInstallerImage(workload workload.Workload, if installerConfig != nil { img.AdditionalDracutModules = append(img.AdditionalDracutModules, installerConfig.AdditionalDracutModules...) img.AdditionalDrivers = append(img.AdditionalDrivers, installerConfig.AdditionalDrivers...) + if installerConfig.SquashfsRootfs != nil && *installerConfig.SquashfsRootfs { + img.RootfsType = manifest.SquashfsRootfs + } } - // On Fedora anaconda needs dbus-broker, but isn't added when dracut runs. - img.AdditionalDracutModules = append(img.AdditionalDracutModules, "dbus-broker") - d := t.arch.distro - img.Product = d.product + img.Product = d.DistroYAML.Product - // We don't know the variant that goes into the OS pipeline that gets installed - img.Variant = "Unknown" - - img.OSVersion = d.osVersion - img.Release = fmt.Sprintf("%s %s", d.product, d.osVersion) - - img.Preview = common.VersionGreaterThanOrEqual(img.OSVersion, VERSION_BRANCHED) + img.OSVersion = d.OsVersion() + img.Release = fmt.Sprintf("%s %s", d.DistroYAML.Product, d.OsVersion()) + img.Variant = t.Variant + img.Preview = d.DistroYAML.Preview img.ISOLabel, err = t.ISOLabel() if err != nil { @@ -609,10 +602,10 @@ func iotCommitImage(workload workload.Workload, }, } - img.Environment = t.environment + img.Environment = &t.ImageTypeYAML.Environment img.Workload = workload img.OSTreeParent = parentCommit - img.OSVersion = d.osVersion + img.OSVersion = d.OsVersion() img.Filename = t.Filename() img.InstallWeakDeps = false @@ -640,15 +633,19 @@ func bootableContainerImage(workload workload.Workload, return nil, err } - img.Environment = t.environment + img.Environment = &t.ImageTypeYAML.Environment img.Workload = workload img.OSTreeParent = parentCommit - img.OSVersion = d.osVersion + img.OSVersion = d.OsVersion() img.Filename = t.Filename() img.InstallWeakDeps = false img.BootContainer = true + id, err := distro.ParseID(d.Name()) + if err != nil { + return nil, err + } img.BootcConfig = &bootc.Config{ - Filename: "20-fedora.toml", + Filename: fmt.Sprintf("20-%s.toml", id.Name), RootFilesystemType: "ext4", } @@ -691,10 +688,10 @@ func iotContainerImage(workload workload.Workload, } img.ContainerLanguage = img.OSCustomizations.Language - img.Environment = t.environment + img.Environment = &t.ImageTypeYAML.Environment img.Workload = workload img.OSTreeParent = parentCommit - img.OSVersion = d.osVersion + img.OSVersion = d.OsVersion() img.ExtraContainerPackages = packageSets[containerPkgsKey] img.Filename = t.Filename() @@ -728,8 +725,8 @@ func iotInstallerImage(workload workload.Workload, return nil, err } img.Kickstart.OSTree = &kickstart.OSTree{ - OSName: "fedora-iot", - Remote: "fedora-iot", + OSName: t.OSTree.Name, + Remote: t.OSTree.Remote, } img.Kickstart.Path = osbuild.KickstartPathOSBuild img.Kickstart.Language, img.Kickstart.Keyboard = customizations.GetPrimaryLocale() @@ -760,16 +757,19 @@ func iotInstallerImage(workload workload.Workload, if installerConfig != nil { img.AdditionalDracutModules = append(img.AdditionalDracutModules, installerConfig.AdditionalDracutModules...) img.AdditionalDrivers = append(img.AdditionalDrivers, installerConfig.AdditionalDrivers...) + if installerConfig.SquashfsRootfs != nil && *installerConfig.SquashfsRootfs { + img.RootfsType = manifest.SquashfsRootfs + } } // On Fedora anaconda needs dbus-broker, but isn't added when dracut runs. img.AdditionalDracutModules = append(img.AdditionalDracutModules, "dbus-broker") - img.Product = d.product + img.Product = d.DistroYAML.Product img.Variant = "IoT" - img.OSVersion = d.osVersion - img.Release = fmt.Sprintf("%s %s", d.product, d.osVersion) - img.Preview = common.VersionGreaterThanOrEqual(img.OSVersion, VERSION_BRANCHED) + img.OSVersion = d.OsVersion() + img.Release = fmt.Sprintf("%s %s", d.DistroYAML.Product, d.OsVersion()) + img.Preview = d.DistroYAML.Preview img.ISOLabel, err = t.ISOLabel() if err != nil { @@ -821,9 +821,9 @@ func iotImage(workload workload.Workload, img.Workload = workload img.Remote = ostree.Remote{ - Name: "fedora-iot", + Name: t.OSTree.Remote, } - img.OSName = "fedora-iot" + img.OSName = t.OSTree.Remote // TODO: move generation into LiveImage pt, err := t.getPartitionTable(customizations, options, rng) @@ -833,7 +833,7 @@ func iotImage(workload workload.Workload, img.PartitionTable = pt img.Filename = t.Filename() - img.Compression = t.compression + img.Compression = t.ImageTypeYAML.Compression return img, nil } @@ -862,9 +862,9 @@ func iotSimplifiedInstallerImage(workload workload.Workload, rawImg.Platform = t.platform rawImg.Workload = workload rawImg.Remote = ostree.Remote{ - Name: "fedora-iot", + Name: t.OSTree.Remote, } - rawImg.OSName = "fedora" + rawImg.OSName = t.OSTree.Name // TODO: move generation into LiveImage pt, err := t.getPartitionTable(customizations, options, rng) @@ -907,10 +907,10 @@ func iotSimplifiedInstallerImage(workload workload.Workload, img.AdditionalDracutModules = append(img.AdditionalDracutModules, "dbus-broker") d := t.arch.distro - img.Product = d.product + img.Product = d.DistroYAML.Product img.Variant = "IoT" - img.OSName = "fedora" - img.OSVersion = d.osVersion + img.OSName = t.OSTree.Name + img.OSVersion = d.OsVersion() img.ISOLabel, err = t.ISOLabel() if err != nil { diff --git a/vendor/github.com/osbuild/images/pkg/distro/fedora/imagetype.go b/vendor/github.com/osbuild/images/pkg/distro/generic/imagetype.go similarity index 80% rename from vendor/github.com/osbuild/images/pkg/distro/fedora/imagetype.go rename to vendor/github.com/osbuild/images/pkg/distro/generic/imagetype.go index 4a59c2f7e..6a2a730e4 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/fedora/imagetype.go +++ b/vendor/github.com/osbuild/images/pkg/distro/generic/imagetype.go @@ -1,4 +1,4 @@ -package fedora +package generic import ( "errors" @@ -9,8 +9,8 @@ import ( "slices" "github.com/osbuild/images/internal/common" - "github.com/osbuild/images/internal/environment" "github.com/osbuild/images/internal/workload" + "github.com/osbuild/images/pkg/arch" "github.com/osbuild/images/pkg/blueprint" "github.com/osbuild/images/pkg/container" "github.com/osbuild/images/pkg/customizations/oscap" @@ -28,41 +28,29 @@ import ( type imageFunc func(workload workload.Workload, t *imageType, bp *blueprint.Blueprint, options distro.ImageOptions, packageSets map[string]rpmmd.PackageSet, containers []container.SourceSpec, rng *rand.Rand) (image.ImageKind, error) -type packageSetFunc func(t *imageType) (map[string]rpmmd.PackageSet, error) - type isoLabelFunc func(t *imageType) string +// imageType implements the distro.ImageType interface +var _ = distro.ImageType(&imageType{}) + type imageType struct { - arch *architecture - platform platform.Platform - environment environment.Environment - workload workload.Workload - name string - nameAliases []string - filename string - compression string - mimeType string - packageSets packageSetFunc + defs.ImageTypeYAML + + arch *architecture + platform platform.Platform + + // XXX: make definable via YAML + workload workload.Workload + // XXX: make member function ImageTypeYAML defaultImageConfig *distro.ImageConfig defaultInstallerConfig *distro.InstallerConfig - defaultSize uint64 - buildPipelines []string - payloadPipelines []string - exports []string - image imageFunc - isoLabel isoLabelFunc - // bootISO: installable ISO - bootISO bool - // rpmOstree: iot/ostree - rpmOstree bool - // bootable image - bootable bool - requiredPartitionSizes map[string]uint64 + image imageFunc + isoLabel isoLabelFunc } func (t *imageType) Name() string { - return t.name + return t.ImageTypeYAML.Name() } func (t *imageType) Arch() distro.Arch { @@ -70,24 +58,24 @@ func (t *imageType) Arch() distro.Arch { } func (t *imageType) Filename() string { - return t.filename + return t.ImageTypeYAML.Filename } func (t *imageType) MIMEType() string { - return t.mimeType + return t.ImageTypeYAML.MimeType } func (t *imageType) OSTreeRef() string { d := t.arch.distro - if t.rpmOstree { - return fmt.Sprintf(d.ostreeRefTmpl, t.arch.Name()) + if t.ImageTypeYAML.RPMOSTree { + return fmt.Sprintf(d.OSTreeRef(), t.arch.Name()) } return "" } func (t *imageType) ISOLabel() (string, error) { - if !t.bootISO { - return "", fmt.Errorf("image type %q is not an ISO", t.name) + if !t.ImageTypeYAML.BootISO { + return "", fmt.Errorf("image type %q is not an ISO", t.Name()) } if t.isoLabel != nil { @@ -99,21 +87,21 @@ func (t *imageType) ISOLabel() (string, error) { func (t *imageType) Size(size uint64) uint64 { // Microsoft Azure requires vhd images to be rounded up to the nearest MB - if t.name == "vhd" && size%datasizes.MebiByte != 0 { + if t.ImageTypeYAML.Name() == "vhd" && size%datasizes.MebiByte != 0 { size = (size/datasizes.MebiByte + 1) * datasizes.MebiByte } if size == 0 { - size = t.defaultSize + size = t.ImageTypeYAML.DefaultSize } return size } func (t *imageType) BuildPipelines() []string { - return t.buildPipelines + return t.ImageTypeYAML.BuildPipelines } func (t *imageType) PayloadPipelines() []string { - return t.payloadPipelines + return t.ImageTypeYAML.PayloadPipelines } func (t *imageType) PayloadPackageSets() []string { @@ -121,8 +109,8 @@ func (t *imageType) PayloadPackageSets() []string { } func (t *imageType) Exports() []string { - if len(t.exports) > 0 { - return t.exports + if len(t.ImageTypeYAML.Exports) > 0 { + return t.ImageTypeYAML.Exports } return []string{"assembler"} } @@ -139,14 +127,10 @@ func (t *imageType) BootMode() platform.BootMode { } func (t *imageType) BasePartitionTable() (*disk.PartitionTable, error) { - return defs.PartitionTable(t, VersionReplacements()) + return defs.PartitionTable(t) } -func (t *imageType) getPartitionTable( - customizations *blueprint.Customizations, - options distro.ImageOptions, - rng *rand.Rand, -) (*disk.PartitionTable, error) { +func (t *imageType) getPartitionTable(customizations *blueprint.Customizations, options distro.ImageOptions, rng *rand.Rand) (*disk.PartitionTable, error) { basePartitionTable, err := t.BasePartitionTable() if err != nil { return nil, err @@ -169,15 +153,15 @@ func (t *imageType) getPartitionTable( partOptions := &disk.CustomPartitionTableOptions{ PartitionTableType: basePartitionTable.Type, // PT type is not customizable, it is determined by the base PT for an image type or architecture BootMode: t.BootMode(), - DefaultFSType: disk.FS_EXT4, // default fs type for Fedora - RequiredMinSizes: t.requiredPartitionSizes, + DefaultFSType: t.arch.distro.DefaultFSType, + RequiredMinSizes: t.ImageTypeYAML.RequiredPartitionSizes, Architecture: t.platform.GetArch(), } return disk.NewCustomPartitionTable(partitioning, partOptions, rng) } partitioningMode := options.PartitioningMode - if t.rpmOstree { + if t.ImageTypeYAML.RPMOSTree { // IoT supports only LVM, force it. // Raw is not supported, return an error if it is requested // TODO Need a central location for logic like this @@ -188,7 +172,7 @@ func (t *imageType) getPartitionTable( } mountpoints := customizations.GetFilesystems() - return disk.NewPartitionTable(basePartitionTable, mountpoints, imageSize, partitioningMode, t.platform.GetArch(), t.requiredPartitionSizes, rng) + return disk.NewPartitionTable(basePartitionTable, mountpoints, imageSize, partitioningMode, t.platform.GetArch(), t.ImageTypeYAML.RequiredPartitionSizes, rng) } func (t *imageType) getDefaultImageConfig() *distro.ImageConfig { @@ -197,13 +181,13 @@ func (t *imageType) getDefaultImageConfig() *distro.ImageConfig { if imageConfig == nil { imageConfig = &distro.ImageConfig{} } - return imageConfig.InheritFrom(t.arch.distro.getDefaultImageConfig()) + return imageConfig.InheritFrom(t.arch.distro.defaultImageConfig) } func (t *imageType) getDefaultInstallerConfig() (*distro.InstallerConfig, error) { - if !t.bootISO { - return nil, fmt.Errorf("image type %q is not an ISO", t.name) + if !t.ImageTypeYAML.BootISO { + return nil, fmt.Errorf("image type %q is not an ISO", t.Name()) } return t.defaultInstallerConfig, nil @@ -237,8 +221,8 @@ func (t *imageType) Manifest(bp *blueprint.Blueprint, staticPackageSets := make(map[string]rpmmd.PackageSet) // don't add any static packages if Minimal was selected - if !bp.Minimal && t.packageSets != nil { - pkgSets, err := t.packageSets(t) + if !bp.Minimal { + pkgSets, err := defs.PackageSets(t) if err != nil { return nil, nil, err } @@ -324,7 +308,7 @@ func (t *imageType) Manifest(bp *blueprint.Blueprint, if options.UseBootstrapContainer { mf.DistroBootstrapRef = bootstrapContainerFor(t) } - _, err = img.InstantiateManifest(&mf, repos, t.arch.distro.runner, rng) + _, err = img.InstantiateManifest(&mf, repos, &t.arch.distro.DistroYAML.Runner, rng) if err != nil { return nil, nil, err } @@ -339,13 +323,13 @@ func (t *imageType) checkOptions(bp *blueprint.Blueprint, options distro.ImageOp var warnings []string - if !t.rpmOstree && options.OSTree != nil { + if !t.ImageTypeYAML.RPMOSTree && options.OSTree != nil { return warnings, fmt.Errorf("OSTree is not supported for %q", t.Name()) } // we do not support embedding containers on ostree-derived images, only on commits themselves - if len(bp.Containers) > 0 && t.rpmOstree && (t.name != "iot-commit" && t.name != "iot-container") { - return warnings, fmt.Errorf("embedding containers is not supported for %s on %s", t.name, t.arch.distro.name) + if len(bp.Containers) > 0 && t.ImageTypeYAML.RPMOSTree && (t.Name() != "iot-commit" && t.Name() != "iot-container") { + return warnings, fmt.Errorf("embedding containers is not supported for %s on %s", t.Name(), t.arch.distro.Name()) } if options.OSTree != nil { @@ -354,37 +338,37 @@ func (t *imageType) checkOptions(bp *blueprint.Blueprint, options distro.ImageOp } } - if t.bootISO && t.rpmOstree { + if t.ImageTypeYAML.BootISO && t.ImageTypeYAML.RPMOSTree { // ostree-based ISOs require a URL from which to pull a payload commit if options.OSTree == nil || options.OSTree.URL == "" { - return warnings, fmt.Errorf("boot ISO image type %q requires specifying a URL from which to retrieve the OSTree commit", t.name) + return warnings, fmt.Errorf("boot ISO image type %q requires specifying a URL from which to retrieve the OSTree commit", t.Name()) } } - if t.name == "iot-raw-xz" || t.name == "iot-qcow2" { + if t.Name() == "iot-raw-xz" || t.Name() == "iot-qcow2" { allowed := []string{"User", "Group", "Directories", "Files", "Services", "FIPS"} if err := customizations.CheckAllowed(allowed...); err != nil { - return warnings, fmt.Errorf(distro.UnsupportedCustomizationError, t.name, strings.Join(allowed, ", ")) + return warnings, fmt.Errorf(distro.UnsupportedCustomizationError, t.Name(), strings.Join(allowed, ", ")) } // TODO: consider additional checks, such as those in "edge-simplified-installer" in RHEL distros } // BootISOs have limited support for customizations. // TODO: Support kernel name selection for image-installer - if t.bootISO { - if t.name == "iot-simplified-installer" { + if t.ImageTypeYAML.BootISO { + if t.Name() == "iot-simplified-installer" { allowed := []string{"InstallationDevice", "FDO", "Ignition", "Kernel", "User", "Group", "FIPS"} if err := customizations.CheckAllowed(allowed...); err != nil { - return warnings, fmt.Errorf(distro.UnsupportedCustomizationError, t.name, strings.Join(allowed, ", ")) + return warnings, fmt.Errorf(distro.UnsupportedCustomizationError, t.Name(), strings.Join(allowed, ", ")) } if customizations.GetInstallationDevice() == "" { - return warnings, fmt.Errorf("boot ISO image type %q requires specifying an installation device to install to", t.name) + return warnings, fmt.Errorf("boot ISO image type %q requires specifying an installation device to install to", t.Name()) } // FDO is optional, but when specified has some restrictions if customizations.GetFDO() != nil { if customizations.GetFDO().ManufacturingServerURL == "" { - return warnings, fmt.Errorf("boot ISO image type %q requires specifying FDO.ManufacturingServerURL configuration to install to when using FDO", t.name) + return warnings, fmt.Errorf("boot ISO image type %q requires specifying FDO.ManufacturingServerURL configuration to install to when using FDO", t.Name()) } var diunSet int if customizations.GetFDO().DiunPubKeyHash != "" { @@ -397,7 +381,7 @@ func (t *imageType) checkOptions(bp *blueprint.Blueprint, options distro.ImageOp diunSet++ } if diunSet != 1 { - return warnings, fmt.Errorf("boot ISO image type %q requires specifying one of [FDO.DiunPubKeyHash,FDO.DiunPubKeyInsecure,FDO.DiunPubKeyRootCerts] configuration to install to when using FDO", t.name) + return warnings, fmt.Errorf("boot ISO image type %q requires specifying one of [FDO.DiunPubKeyHash,FDO.DiunPubKeyInsecure,FDO.DiunPubKeyRootCerts] configuration to install to when using FDO", t.Name()) } } @@ -410,21 +394,21 @@ func (t *imageType) checkOptions(bp *blueprint.Blueprint, options distro.ImageOp return warnings, fmt.Errorf("ignition.firstboot requires a provisioning url") } } - } else if t.name == "iot-installer" || t.name == "minimal-installer" { + } else if t.Name() == "iot-installer" || t.Name() == "minimal-installer" { // "Installer" is actually not allowed for image-installer right now, but this is checked at the end allowed := []string{"User", "Group", "FIPS", "Installer", "Timezone", "Locale"} if err := customizations.CheckAllowed(allowed...); err != nil { - return warnings, fmt.Errorf(distro.UnsupportedCustomizationError, t.name, strings.Join(allowed, ", ")) + return warnings, fmt.Errorf(distro.UnsupportedCustomizationError, t.Name(), strings.Join(allowed, ", ")) } - } else if t.name == "workstation-live-installer" { + } else if t.Name() == "workstation-live-installer" { allowed := []string{"Installer"} if err := customizations.CheckAllowed(allowed...); err != nil { - return warnings, fmt.Errorf(distro.NoCustomizationsAllowedError, t.name) + return warnings, fmt.Errorf(distro.NoCustomizationsAllowedError, t.Name()) } } } - if kernelOpts := customizations.GetKernel(); kernelOpts.Append != "" && t.rpmOstree { + if kernelOpts := customizations.GetKernel(); kernelOpts.Append != "" && t.ImageTypeYAML.RPMOSTree { return warnings, fmt.Errorf("kernel boot parameter customizations are not supported for ostree types") } @@ -433,7 +417,7 @@ func (t *imageType) checkOptions(bp *blueprint.Blueprint, options distro.ImageOp if err != nil { return warnings, err } - if (len(mountpoints) > 0 || partitioning != nil) && t.rpmOstree { + if (len(mountpoints) > 0 || partitioning != nil) && t.ImageTypeYAML.RPMOSTree { return warnings, fmt.Errorf("Custom mountpoints and partitioning are not supported for ostree types") } if len(mountpoints) > 0 && partitioning != nil { @@ -451,11 +435,11 @@ func (t *imageType) checkOptions(bp *blueprint.Blueprint, options distro.ImageOp } if osc := customizations.GetOpenSCAP(); osc != nil { - supported := oscap.IsProfileAllowed(osc.ProfileID, oscapProfileAllowList) + supported := oscap.IsProfileAllowed(osc.ProfileID, t.arch.distro.DistroYAML.OscapProfilesAllowList) if !supported { return warnings, fmt.Errorf("OpenSCAP unsupported profile: %s", osc.ProfileID) } - if t.rpmOstree { + if t.ImageTypeYAML.RPMOSTree { return warnings, fmt.Errorf("OpenSCAP customizations are not supported for ostree types") } if osc.ProfileID == "" { @@ -475,7 +459,7 @@ func (t *imageType) checkOptions(bp *blueprint.Blueprint, options distro.ImageOp dcp := policies.CustomDirectoriesPolicies fcp := policies.CustomFilesPolicies - if t.rpmOstree { + if t.ImageTypeYAML.RPMOSTree { dcp = policies.OstreeCustomDirectoriesPolicies fcp = policies.OstreeCustomFilesPolicies } @@ -506,7 +490,7 @@ func (t *imageType) checkOptions(bp *blueprint.Blueprint, options distro.ImageOp } if instCust != nil { // only supported by the Anaconda installer - if slices.Index([]string{"iot-installer"}, t.name) == -1 { + if slices.Index([]string{"iot-installer"}, t.Name()) == -1 { return warnings, fmt.Errorf("installer customizations are not supported for %q", t.Name()) } @@ -525,18 +509,7 @@ func (t *imageType) checkOptions(bp *blueprint.Blueprint, options distro.ImageOp return warnings, nil } -// XXX: this will become part of the yaml distro definitions, i.e. -// the yaml will have a "bootstrap_ref" key for each distro/arch func bootstrapContainerFor(t *imageType) string { - arch := t.arch.Name() - distro := t.arch.distro - - // XXX: remove once fedora containers are part of the upstream - // fedora registry (and can be validated via tls) - if arch == "riscv64" { - return "ghcr.io/mvo5/fedora-buildroot:" + distro.OsVersion() - } - - // we need fedora-toolbox to get python3 - return "registry.fedoraproject.org/fedora-toolbox:" + distro.OsVersion() + a := common.Must(arch.FromString(t.arch.name)) + return t.arch.distro.DistroYAML.BootstrapContainers[a] } diff --git a/vendor/github.com/osbuild/images/pkg/distro/id.go b/vendor/github.com/osbuild/images/pkg/distro/id.go index 914b859d5..bbf2f48d3 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/id.go +++ b/vendor/github.com/osbuild/images/pkg/distro/id.go @@ -16,7 +16,7 @@ type ID struct { MinorVersion int } -func (id ID) versionString() string { +func (id ID) VersionString() string { if id.MinorVersion == -1 { return fmt.Sprintf("%d", id.MajorVersion) } else { @@ -25,11 +25,11 @@ func (id ID) versionString() string { } func (id ID) String() string { - return fmt.Sprintf("%s-%s", id.Name, id.versionString()) + return fmt.Sprintf("%s-%s", id.Name, id.VersionString()) } func (id ID) Version() (*version.Version, error) { - return version.NewVersion(id.versionString()) + return version.NewVersion(id.VersionString()) } type ParseError struct { diff --git a/vendor/github.com/osbuild/images/pkg/distro/image_config.go b/vendor/github.com/osbuild/images/pkg/distro/image_config.go index 70fe19ac2..28b9d5e07 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/image_config.go +++ b/vendor/github.com/osbuild/images/pkg/distro/image_config.go @@ -8,6 +8,7 @@ import ( "github.com/osbuild/images/pkg/customizations/fsnode" "github.com/osbuild/images/pkg/customizations/shell" "github.com/osbuild/images/pkg/customizations/subscription" + "github.com/osbuild/images/pkg/customizations/users" "github.com/osbuild/images/pkg/manifest" "github.com/osbuild/images/pkg/osbuild" ) @@ -29,6 +30,17 @@ type ImageConfig struct { UpdateDefaultKernel *bool `yaml:"update_default_kernel,omitempty"` KernelOptions []string `yaml:"kernel_options,omitempty"` + // The name of the default kernel to use for the image type. + // NOTE: Currently this overrides the kernel named in the blueprint. The + // only image type that uses it is the azure-cvm, which doesn't allow + // kernel selection. The option should generally be a fallback for when the + // blueprint doesn't specify a kernel. + // + // This option has no effect on the DefaultKernel option under Sysconfig. + // If both options are set, they should have the same value. + // These two options should be unified. + DefaultKernelName *string `yaml:"default_kernel_name"` + // List of files from which to import GPG keys into the RPM database GPGKeyFiles []string `yaml:"gpgkey_files,omitempty"` @@ -60,9 +72,8 @@ type ImageConfig struct { PamLimitsConf []*osbuild.PamLimitsConfStageOptions `yaml:"pam_limits_conf,omitempty"` Sysctld []*osbuild.SysctldStageOptions // Do not use DNFConfig directly, call "DNFConfigOptions()" - DNFConfig []*osbuild.DNFConfigStageOptions `yaml:"dnf_config,omitempty"` - DNFSetReleaseVerVar *bool `yaml:"dnf_set_release_ver_var,omitempty"` - SshdConfig *osbuild.SshdConfigStageOptions `yaml:"sshd_config"` + DNFConfig *DNFConfig `yaml:"dnf_config"` + SshdConfig *osbuild.SshdConfigStageOptions `yaml:"sshd_config"` Authconfig *osbuild.AuthconfigStageOptions PwQuality *osbuild.PwqualityConfStageOptions WAAgentConfig *osbuild.WAAgentConfStageOptions `yaml:"waagent_config,omitempty"` @@ -77,6 +88,8 @@ type ImageConfig struct { WSLConfig *WSLConfig `yaml:"wsl_config,omitempty"` + Users []users.User + Files []*fsnode.File Directories []*fsnode.Directory @@ -125,6 +138,11 @@ type ImageConfig struct { IsoRootfsType *manifest.RootfsType `yaml:"iso_rootfs_type,omitempty"` } +type DNFConfig struct { + Options []*osbuild.DNFConfigStageOptions + SetReleaseVerVar *bool `yaml:"set_release_ver_var"` +} + type WSLConfig struct { BootSystemd bool `yaml:"boot_systemd,omitempty"` } @@ -155,8 +173,11 @@ func (c *ImageConfig) InheritFrom(parentConfig *ImageConfig) *ImageConfig { } func (c *ImageConfig) DNFConfigOptions(osVersion string) []*osbuild.DNFConfigStageOptions { - if c.DNFSetReleaseVerVar == nil || !*c.DNFSetReleaseVerVar { - return c.DNFConfig + if c.DNFConfig == nil { + return nil + } + if c.DNFConfig.SetReleaseVerVar == nil || !*c.DNFConfig.SetReleaseVerVar { + return c.DNFConfig.Options } // We currently have no use-case where we set both a custom @@ -166,7 +187,7 @@ func (c *ImageConfig) DNFConfigOptions(osVersion string) []*osbuild.DNFConfigSta // existing once (exactly once) and we need to consider what to // do about potentially conflicting (manually set) "releasever" // values by the user. - if c.DNFConfig != nil { + if c.DNFConfig.SetReleaseVerVar != nil && c.DNFConfig.Options != nil { err := fmt.Errorf("internal error: currently DNFConfig and DNFSetReleaseVerVar cannot be used together, please reporting this as a feature request") panic(err) } diff --git a/vendor/github.com/osbuild/images/pkg/distro/installer_config.go b/vendor/github.com/osbuild/images/pkg/distro/installer_config.go index af373a35a..b33120975 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/installer_config.go +++ b/vendor/github.com/osbuild/images/pkg/distro/installer_config.go @@ -6,4 +6,7 @@ type InstallerConfig struct { // Additional dracut modules and drivers to enable AdditionalDracutModules []string `yaml:"additional_dracut_modules"` AdditionalDrivers []string `yaml:"additional_drivers"` + + // SquashfsRootfs will set SquashfsRootfs as rootfs in the iso image + SquashfsRootfs *bool `yaml:"squashfs_rootfs"` } diff --git a/vendor/github.com/osbuild/images/pkg/distro/rhel/images.go b/vendor/github.com/osbuild/images/pkg/distro/rhel/images.go index 4eb2a56fe..6fd35f158 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/rhel/images.go +++ b/vendor/github.com/osbuild/images/pkg/distro/rhel/images.go @@ -37,7 +37,16 @@ func osCustomizations( osc := manifest.OSCustomizations{} if t.Bootable || t.RPMOSTree { + // TODO: for now the only image types that define a default kernel are + // ones that use UKIs and don't allow overriding, so this works. + // However, if we ever need to specify default kernels for image types + // that allow overriding, we will need to change c.GetKernel() to take + // an argument as fallback or make it not return the standard "kernel" + // when it's unset. osc.KernelName = c.GetKernel().Name + if imageConfig.DefaultKernelName != nil { + osc.KernelName = *imageConfig.DefaultKernelName + } var kernelOptions []string // XXX: keep in sync with the identical copy in fedora/images.go @@ -74,7 +83,9 @@ func osCustomizations( // don't put users and groups in the payload of an installer // add them via kickstart instead osc.Groups = users.GroupsFromBP(c.GetGroups()) + osc.Users = users.UsersFromBP(c.GetUsers()) + osc.Users = append(osc.Users, imageConfig.Users...) } osc.EnabledServices = imageConfig.EnabledServices diff --git a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel10/azure.go b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel10/azure.go index e78961d55..75b687b67 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel10/azure.go +++ b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel10/azure.go @@ -69,3 +69,24 @@ func mkAzureSapInternalImgType(rd *rhel.Distribution, a arch.Arch) *rhel.ImageTy return it } + +// Azure Confidential VM +func mkAzureCVMImgType(rd *rhel.Distribution) *rhel.ImageType { + it := rhel.NewImageType( + "azure-cvm", + "disk.vhd", + "application/x-vhd", + packageSetLoader, + rhel.DiskImage, + []string{"build"}, + []string{"os", "image", "vpc"}, + []string{"vpc"}, + ) + + it.Bootable = true + it.DefaultSize = 32 * datasizes.GibiByte + it.DefaultImageConfig = imageConfig(rd, "x86_64", "azure-cvm") + it.BasePartitionTables = defaultBasePartitionTables + + return it +} diff --git a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel10/distro.go b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel10/distro.go index 6548639cb..3460ae742 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel10/distro.go +++ b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel10/distro.go @@ -253,6 +253,18 @@ func newDistro(name string, major, minor int) *rhel.Distribution { x86_64.AddImageTypes(ec2X86Platform, mkEc2ImgTypeX86_64(rd), mkEc2HaImgTypeX86_64(rd), mkEC2SapImgTypeX86_64(rd)) aarch64.AddImageTypes(ec2Aarch64Platform, mkEC2ImgTypeAarch64(rd)) + + azureX64CVMPlatform := &platform.X86{ + UEFIVendor: rd.Vendor(), + BasePlatform: platform.BasePlatform{ + ImageFormat: platform.FORMAT_VHD, + }, + Bootloader: platform.BOOTLOADER_UKI, + } + x86_64.AddImageTypes( + azureX64CVMPlatform, + mkAzureCVMImgType(rd), + ) } rd.AddArches(x86_64, aarch64, ppc64le, s390x) diff --git a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel10/package_sets.go b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel10/package_sets.go index 7d5c55df3..b821a4617 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel10/package_sets.go +++ b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel10/package_sets.go @@ -11,9 +11,9 @@ import ( ) func packageSetLoader(t *rhel.ImageType) (map[string]rpmmd.PackageSet, error) { - return defs.PackageSets(t, nil) + return defs.PackageSets(t) } func imageConfig(d *rhel.Distribution, archName, imageType string) *distro.ImageConfig { - return common.Must(defs.ImageConfig(d.Name(), archName, imageType, nil)) + return common.Must(defs.ImageConfig(d.Name(), archName, imageType)) } diff --git a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel10/partition_tables.go b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel10/partition_tables.go index 8b795dd3a..28b6e28ed 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel10/partition_tables.go +++ b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel10/partition_tables.go @@ -9,7 +9,7 @@ import ( ) func defaultBasePartitionTables(t *rhel.ImageType) (disk.PartitionTable, bool) { - partitionTable, err := defs.PartitionTable(t, nil) + partitionTable, err := defs.PartitionTable(t) if errors.Is(err, defs.ErrNoPartitionTableForImgType) { return disk.PartitionTable{}, false } diff --git a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel7/package_sets.go b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel7/package_sets.go index aaf617d60..567c8d510 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel7/package_sets.go +++ b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel7/package_sets.go @@ -7,5 +7,5 @@ import ( ) func packageSetLoader(t *rhel.ImageType) (map[string]rpmmd.PackageSet, error) { - return defs.PackageSets(t, nil) + return defs.PackageSets(t) } diff --git a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel7/partition_tables.go b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel7/partition_tables.go index 1cc6ebc3d..f240829b3 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel7/partition_tables.go +++ b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel7/partition_tables.go @@ -9,7 +9,7 @@ import ( ) func defaultBasePartitionTables(t *rhel.ImageType) (disk.PartitionTable, bool) { - partitionTable, err := defs.PartitionTable(t, nil) + partitionTable, err := defs.PartitionTable(t) if errors.Is(err, defs.ErrNoPartitionTableForImgType) { return disk.PartitionTable{}, false } diff --git a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel8/gce.go b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel8/gce.go index 62401545e..56f50fee1 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel8/gce.go +++ b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel8/gce.go @@ -76,11 +76,13 @@ func defaultGceByosImageConfig(rd distro.Distro) *distro.ImageConfig { Keyboard: &osbuild.KeymapStageOptions{ Keymap: "us", }, - DNFConfig: []*osbuild.DNFConfigStageOptions{ - { - Config: &osbuild.DNFConfig{ - Main: &osbuild.DNFConfigMain{ - IPResolve: "4", + DNFConfig: &distro.DNFConfig{ + Options: []*osbuild.DNFConfigStageOptions{ + { + Config: &osbuild.DNFConfig{ + Main: &osbuild.DNFConfigMain{ + IPResolve: "4", + }, }, }, }, diff --git a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel8/package_sets.go b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel8/package_sets.go index e5489c836..2fb630b00 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel8/package_sets.go +++ b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel8/package_sets.go @@ -9,5 +9,5 @@ import ( ) func packageSetLoader(t *rhel.ImageType) (map[string]rpmmd.PackageSet, error) { - return defs.PackageSets(t, nil) + return defs.PackageSets(t) } diff --git a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel8/partition_tables.go b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel8/partition_tables.go index 68f11e392..598f83c31 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel8/partition_tables.go +++ b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel8/partition_tables.go @@ -9,7 +9,7 @@ import ( ) func partitionTables(t *rhel.ImageType) (disk.PartitionTable, bool) { - partitionTable, err := defs.PartitionTable(t, nil) + partitionTable, err := defs.PartitionTable(t) if errors.Is(err, defs.ErrNoPartitionTableForImgType) { return disk.PartitionTable{}, false } diff --git a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel8/sap.go b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel8/sap.go index 22a52217e..7ebf0791b 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel8/sap.go +++ b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel8/sap.go @@ -107,7 +107,10 @@ func sapImageConfig(rd distro.Distro) *distro.ImageConfig { if common.VersionLessThan(rd.OsVersion(), "8.10") { // E4S/EUS - ic.DNFSetReleaseVerVar = common.ToPtr(true) + if ic.DNFConfig == nil { + ic.DNFConfig = &distro.DNFConfig{} + } + ic.DNFConfig.SetReleaseVerVar = common.ToPtr(true) } return ic diff --git a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/azure.go b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/azure.go index 644bf83e2..5b708af7a 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/azure.go +++ b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/azure.go @@ -77,6 +77,27 @@ func mkAzureSapInternalImgType(rd *rhel.Distribution, a arch.Arch) *rhel.ImageTy return it } +// Azure Confidential VM +func mkAzureCVMImgType(rd *rhel.Distribution) *rhel.ImageType { + it := rhel.NewImageType( + "azure-cvm", + "disk.vhd", + "application/x-vhd", + packageSetLoader, + rhel.DiskImage, + []string{"build"}, + []string{"os", "image", "vpc"}, + []string{"vpc"}, + ) + + it.Bootable = true + it.DefaultSize = 32 * datasizes.GibiByte + it.DefaultImageConfig = azureCVMImageConfig(rd) + it.BasePartitionTables = azureCVMPartitionTables + + return it +} + // PARTITION TABLES func azureInternalBasePartitionTables(t *rhel.ImageType) (disk.PartitionTable, bool) { var bootSize uint64 @@ -327,8 +348,9 @@ func defaultAzureKernelOptions(rd *rhel.Distribution, a arch.Arch) []string { return kargs } -// based on https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/deploying_rhel_9_on_microsoft_azure/assembly_deploying-a-rhel-image-as-a-virtual-machine-on-microsoft-azure_cloud-content-azure#making-configuration-changes_configure-the-image-azure -func defaultAzureImageConfig(rd *rhel.Distribution) *distro.ImageConfig { +// Base ImageConfig for Azure images. Should not be used directly since the +// default ImageConfig adds a few extra bits. +func baseAzureImageConfig(rd *rhel.Distribution) *distro.ImageConfig { ic := &distro.ImageConfig{ Timezone: common.ToPtr("Etc/UTC"), Locale: common.ToPtr("en_US.UTF-8"), @@ -389,34 +411,6 @@ func defaultAzureImageConfig(rd *rhel.Distribution) *distro.ImageConfig { }, }, }, - CloudInit: []*osbuild.CloudInitStageOptions{ - { - Filename: "10-azure-kvp.cfg", - Config: osbuild.CloudInitConfigFile{ - Reporting: &osbuild.CloudInitConfigReporting{ - Logging: &osbuild.CloudInitConfigReportingHandlers{ - Type: "log", - }, - Telemetry: &osbuild.CloudInitConfigReportingHandlers{ - Type: "hyperv", - }, - }, - }, - }, - { - Filename: "91-azure_datasource.cfg", - Config: osbuild.CloudInitConfigFile{ - Datasource: &osbuild.CloudInitConfigDatasource{ - Azure: &osbuild.CloudInitConfigDatasourceAzure{ - ApplyNetworkConfig: false, - }, - }, - DatasourceList: []string{ - "Azure", - }, - }, - }, - }, PwQuality: &osbuild.PwqualityConfStageOptions{ Config: osbuild.PwqualityConfConfig{ Minlen: common.ToPtr(6), @@ -498,17 +492,6 @@ func defaultAzureImageConfig(rd *rhel.Distribution) *distro.ImageConfig { ic.WAAgentConfig.Config.ProvisioningUseCloudInit = common.ToPtr(true) ic.WAAgentConfig.Config.ProvisioningEnabled = common.ToPtr(false) - ic.TimeSynchronization = &osbuild.ChronyStageOptions{ - Refclocks: []osbuild.ChronyConfigRefclock{ - { - Driver: osbuild.NewChronyDriverPHC("/dev/ptp_hyperv"), - Poll: common.ToPtr(3), - Dpoll: common.ToPtr(-2), - Offset: common.ToPtr(0.0), - }, - }, - } - datalossWarningScript, datalossSystemdUnit, err := rhel.CreateAzureDatalossWarningScriptAndUnit() if err != nil { panic(err) @@ -533,6 +516,118 @@ func defaultAzureImageConfig(rd *rhel.Distribution) *distro.ImageConfig { return ic } +// based on https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/deploying_rhel_9_on_microsoft_azure/assembly_deploying-a-rhel-image-as-a-virtual-machine-on-microsoft-azure_cloud-content-azure#making-configuration-changes_configure-the-image-azure +func defaultAzureImageConfig(rd *rhel.Distribution) *distro.ImageConfig { + ic := &distro.ImageConfig{ + CloudInit: []*osbuild.CloudInitStageOptions{ + { + Filename: "10-azure-kvp.cfg", + Config: osbuild.CloudInitConfigFile{ + Reporting: &osbuild.CloudInitConfigReporting{ + Logging: &osbuild.CloudInitConfigReportingHandlers{ + Type: "log", + }, + Telemetry: &osbuild.CloudInitConfigReportingHandlers{ + Type: "hyperv", + }, + }, + }, + }, + { + Filename: "91-azure_datasource.cfg", + Config: osbuild.CloudInitConfigFile{ + Datasource: &osbuild.CloudInitConfigDatasource{ + Azure: &osbuild.CloudInitConfigDatasourceAzure{ + ApplyNetworkConfig: false, + }, + }, + DatasourceList: []string{ + "Azure", + }, + }, + }, + }, + } + + if rd.IsRHEL() && common.VersionGreaterThanOrEqual(rd.OsVersion(), "9.6") { + ic.TimeSynchronization = &osbuild.ChronyStageOptions{ + Refclocks: []osbuild.ChronyConfigRefclock{ + { + Driver: osbuild.NewChronyDriverPHC("/dev/ptp_hyperv"), + Poll: common.ToPtr(3), + Dpoll: common.ToPtr(-2), + Offset: common.ToPtr(0.0), + }, + }, + } + } + + return ic.InheritFrom(baseAzureImageConfig(rd)) +} + func sapAzureImageConfig(rd *rhel.Distribution) *distro.ImageConfig { return sapImageConfig(rd.OsVersion()).InheritFrom(defaultAzureImageConfig(rd)) } + +func azureCVMImageConfig(rd *rhel.Distribution) *distro.ImageConfig { + ic := &distro.ImageConfig{ + DefaultKernelName: common.ToPtr("kernel-uki-virt"), + NoBLS: common.ToPtr(true), + CloudInit: []*osbuild.CloudInitStageOptions{ + { + Filename: "91-azure_datasource.cfg", + Config: osbuild.CloudInitConfigFile{ + Datasource: &osbuild.CloudInitConfigDatasource{ + Azure: &osbuild.CloudInitConfigDatasourceAzure{ + ApplyNetworkConfig: false, + }, + }, + DatasourceList: []string{ + "Azure", + }, + }, + }, + }, + } + return ic.InheritFrom(baseAzureImageConfig(rd)) +} + +func azureCVMPartitionTables(t *rhel.ImageType) (disk.PartitionTable, bool) { + switch t.Arch().Name() { + case arch.ARCH_X86_64.String(): + return disk.PartitionTable{ + UUID: "D209C89E-EA5E-4FBD-B161-B461CCE297E0", + Type: disk.PT_GPT, + Partitions: []disk.Partition{ + { + Size: 252 * datasizes.MebiByte, + Type: disk.EFISystemPartitionGUID, + UUID: disk.EFISystemPartitionUUID, + Payload: &disk.Filesystem{ + Type: "vfat", + UUID: disk.EFIFilesystemUUID, + Mountpoint: "/boot/efi", + Label: "EFI-SYSTEM", + FSTabOptions: "defaults,uid=0,gid=0,umask=077,shortname=winnt", + FSTabFreq: 0, + FSTabPassNo: 2, + }, + }, + { + Size: 5 * datasizes.GibiByte, + Type: disk.RootPartitionX86_64GUID, + Payload: &disk.Filesystem{ + Type: "ext4", + Label: "root", + Mountpoint: "/", + FSTabOptions: "defaults", + FSTabFreq: 0, + FSTabPassNo: 0, + }, + }, + }, + }, true + default: + return disk.PartitionTable{}, false + } +} diff --git a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/distro.go b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/distro.go index 749994f58..5d481fc1e 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/distro.go +++ b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/distro.go @@ -346,6 +346,22 @@ func newDistro(name string, major, minor int) *rhel.Distribution { }, mkEC2ImgTypeAarch64(), ) + + // CVM is only available starting from 9.6 + if common.VersionGreaterThanOrEqual(rd.OsVersion(), "9.6") { + azureX64CVMPlatform := &platform.X86{ + UEFIVendor: rd.Vendor(), + BasePlatform: platform.BasePlatform{ + ImageFormat: platform.FORMAT_VHD, + }, + Bootloader: platform.BOOTLOADER_UKI, + } + x86_64.AddImageTypes( + azureX64CVMPlatform, + mkAzureCVMImgType(rd), + ) + + } } rd.AddArches(x86_64, aarch64, ppc64le, s390x) diff --git a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/gce.go b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/gce.go index 2d821f27c..0027870f2 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/gce.go +++ b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/gce.go @@ -60,11 +60,13 @@ func baseGCEImageConfig() *distro.ImageConfig { Keyboard: &osbuild.KeymapStageOptions{ Keymap: "us", }, - DNFConfig: []*osbuild.DNFConfigStageOptions{ - { - Config: &osbuild.DNFConfig{ - Main: &osbuild.DNFConfigMain{ - IPResolve: "4", + DNFConfig: &distro.DNFConfig{ + Options: []*osbuild.DNFConfigStageOptions{ + { + Config: &osbuild.DNFConfig{ + Main: &osbuild.DNFConfigMain{ + IPResolve: "4", + }, }, }, }, diff --git a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/options.go b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/options.go index 1a4ce2e48..3935f87d4 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/options.go +++ b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/options.go @@ -208,5 +208,15 @@ func checkOptions(t *rhel.ImageType, bp *blueprint.Blueprint, options distro.Ima } } + // don't support setting any kernel customizations for image types with + // UKIs + // NOTE: this is very ugly and stupid, it should not be based on the image + // type name, but we want to redo this whole function anyway + // NOTE: we can't use customizations.GetKernel() because it returns + // 'Name: "kernel"' when unset. + if t.Name() == "azure-cvm" && customizations != nil && customizations.Kernel != nil { + return warnings, fmt.Errorf("kernel customizations are not supported for %q", t.Name()) + } + return warnings, nil } diff --git a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/package_sets.go b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/package_sets.go index a71b50aac..5b92e1d9c 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/package_sets.go +++ b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/package_sets.go @@ -7,5 +7,5 @@ import ( ) func packageSetLoader(t *rhel.ImageType) (map[string]rpmmd.PackageSet, error) { - return defs.PackageSets(t, nil) + return defs.PackageSets(t) } diff --git a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/partition_tables.go b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/partition_tables.go index ba17455d4..299ffe376 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/partition_tables.go +++ b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/partition_tables.go @@ -7,7 +7,7 @@ import ( ) func defaultBasePartitionTables(t *rhel.ImageType) (disk.PartitionTable, bool) { - partitionTable, err := defs.PartitionTable(t, nil) + partitionTable, err := defs.PartitionTable(t) if err != nil { // XXX: have a check to differenciate ErrNoEnt and else return disk.PartitionTable{}, false diff --git a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/sap.go b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/sap.go index ed8c86ddc..03f9577f3 100644 --- a/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/sap.go +++ b/vendor/github.com/osbuild/images/pkg/distro/rhel/rhel9/sap.go @@ -104,6 +104,8 @@ func sapImageConfig(osVersion string) *distro.ImageConfig { ), }, // E4S/EUS - DNFSetReleaseVerVar: common.ToPtr(true), + DNFConfig: &distro.DNFConfig{ + SetReleaseVerVar: common.ToPtr(true), + }, } } diff --git a/vendor/github.com/osbuild/images/pkg/distrofactory/distrofactory.go b/vendor/github.com/osbuild/images/pkg/distrofactory/distrofactory.go index 4e264b8a0..215f89315 100644 --- a/vendor/github.com/osbuild/images/pkg/distrofactory/distrofactory.go +++ b/vendor/github.com/osbuild/images/pkg/distrofactory/distrofactory.go @@ -5,7 +5,7 @@ import ( "sort" "github.com/osbuild/images/pkg/distro" - "github.com/osbuild/images/pkg/distro/fedora" + "github.com/osbuild/images/pkg/distro/generic" "github.com/osbuild/images/pkg/distro/rhel/rhel10" "github.com/osbuild/images/pkg/distro/rhel/rhel7" "github.com/osbuild/images/pkg/distro/rhel/rhel8" @@ -109,7 +109,7 @@ func New(factories ...FactoryFunc) *Factory { // distros. func NewDefault() *Factory { return New( - fedora.DistroFactory, + generic.DistroFactory, rhel7.DistroFactory, rhel8.DistroFactory, rhel9.DistroFactory, diff --git a/vendor/github.com/osbuild/images/pkg/distroidparser/idparser.go b/vendor/github.com/osbuild/images/pkg/distroidparser/idparser.go index 7bd1e7269..b5af93f60 100644 --- a/vendor/github.com/osbuild/images/pkg/distroidparser/idparser.go +++ b/vendor/github.com/osbuild/images/pkg/distroidparser/idparser.go @@ -2,7 +2,6 @@ package distroidparser import ( "github.com/osbuild/images/pkg/distro" - "github.com/osbuild/images/pkg/distro/fedora" "github.com/osbuild/images/pkg/distro/rhel/rhel10" "github.com/osbuild/images/pkg/distro/rhel/rhel7" "github.com/osbuild/images/pkg/distro/rhel/rhel8" @@ -63,7 +62,6 @@ func (p *Parser) Standardize(idStr string) (string, error) { func NewDefaultParser() *Parser { return New( - fedora.ParseID, rhel7.ParseID, rhel8.ParseID, rhel9.ParseID, diff --git a/vendor/github.com/osbuild/images/pkg/image/anaconda_container_installer.go b/vendor/github.com/osbuild/images/pkg/image/anaconda_container_installer.go index 1dda2634f..f1edde66c 100644 --- a/vendor/github.com/osbuild/images/pkg/image/anaconda_container_installer.go +++ b/vendor/github.com/osbuild/images/pkg/image/anaconda_container_installer.go @@ -10,6 +10,7 @@ import ( "github.com/osbuild/images/pkg/customizations/anaconda" "github.com/osbuild/images/pkg/customizations/kickstart" "github.com/osbuild/images/pkg/datasizes" + "github.com/osbuild/images/pkg/disk" "github.com/osbuild/images/pkg/manifest" "github.com/osbuild/images/pkg/osbuild" "github.com/osbuild/images/pkg/platform" @@ -58,6 +59,9 @@ type AnacondaContainerInstaller struct { // Locale for the installer. This should be set to the same locale as the // ISO OS payload, if known. Locale string + + // Filesystem type for the installed system as opposed to that of the ISO. + InstallRootfsType disk.FSType } func NewAnacondaContainerInstaller(container container.SourceSpec, ref string) *AnacondaContainerInstaller { @@ -150,6 +154,8 @@ func (img *AnacondaContainerInstaller) InstantiateManifest(m *manifest.Manifest, isoTreePipeline.KernelOpts = append(isoTreePipeline.KernelOpts, "fips=1") } + isoTreePipeline.InstallRootfsType = img.InstallRootfsType + isoPipeline := manifest.NewISO(buildPipeline, isoTreePipeline, img.ISOLabel) isoPipeline.SetFilename(img.Filename) isoPipeline.ISOBoot = img.ISOBoot diff --git a/vendor/github.com/osbuild/images/pkg/image/bootc_disk.go b/vendor/github.com/osbuild/images/pkg/image/bootc_disk.go index d2b0fc716..9663f5981 100644 --- a/vendor/github.com/osbuild/images/pkg/image/bootc_disk.go +++ b/vendor/github.com/osbuild/images/pkg/image/bootc_disk.go @@ -60,12 +60,54 @@ func (img *BootcDiskImage) InstantiateManifestFromContainers(m *manifest.Manifes if img.BuildSELinux != "" { policy = img.BuildSELinux } + + var copyFilesFrom map[string][]string + var ensureDirs []*fsnode.Directory + + if *img.ContainerSource != *img.BuildContainerSource { + // If we're using a different build container from the target container then we copy + // the bootc customization file directories from the target container. This includes the + // bootc install customization, and /usr/lib/ostree/prepare-root.conf which configures + // e.g. composefs and fs-verity setup. + // + // To ensure that these copies never fail we also create the source and target + // directories as needed. + + pipelineName := "target" + // files to copy have slash at end to copy directory contents, not directory itself + copyFiles := []string{"/usr/lib/bootc/install/", "/usr/lib/ostree/"} + ensureDirPaths := []string{"/usr/lib/bootc/install", "/usr/lib/ostree"} + + copyFilesFrom = map[string][]string{pipelineName: copyFiles} + for _, path := range ensureDirPaths { + // Note: Mode/User/Group must be nil here to make GenDirectoryNodesStages use dirExistOk + dir, err := fsnode.NewDirectory(path, nil, nil, nil, true) + if err != nil { + return err + } + ensureDirs = append(ensureDirs, dir) + } + + targetContainers := []container.SourceSpec{*img.ContainerSource} + targetBuildPipeline := manifest.NewBuildFromContainer(m, runner, targetContainers, + &manifest.BuildOptions{ + PipelineName: pipelineName, + ContainerBuildable: true, + SELinuxPolicy: policy, + EnsureDirs: ensureDirs, + }) + targetBuildPipeline.Checkpoint() + } + buildContainers := []container.SourceSpec{*img.BuildContainerSource} buildPipeline := manifest.NewBuildFromContainer(m, runner, buildContainers, &manifest.BuildOptions{ ContainerBuildable: true, SELinuxPolicy: policy, + CopyFilesFrom: copyFilesFrom, + EnsureDirs: ensureDirs, }) + buildPipeline.Checkpoint() // In the bootc flow, we reuse the host container context for tools; diff --git a/vendor/github.com/osbuild/images/pkg/image/disk.go b/vendor/github.com/osbuild/images/pkg/image/disk.go index 9e98a693f..1c2d1c628 100644 --- a/vendor/github.com/osbuild/images/pkg/image/disk.go +++ b/vendor/github.com/osbuild/images/pkg/image/disk.go @@ -80,6 +80,17 @@ func (img *DiskImage) InstantiateManifest(m *manifest.Manifest, qcow2Pipeline := manifest.NewQCOW2(buildPipeline, rawImagePipeline) qcow2Pipeline.Compat = img.Platform.GetQCOW2Compat() imagePipeline = qcow2Pipeline + case platform.FORMAT_VAGRANT_LIBVIRT: + qcow2Pipeline := manifest.NewQCOW2(buildPipeline, rawImagePipeline) + qcow2Pipeline.Compat = img.Platform.GetQCOW2Compat() + + vagrantPipeline := manifest.NewVagrant(buildPipeline, qcow2Pipeline) + + tarPipeline := manifest.NewTar(buildPipeline, vagrantPipeline, "archive") + tarPipeline.Format = osbuild.TarArchiveFormatUstar + tarPipeline.SetFilename(img.Filename) + + imagePipeline = tarPipeline case platform.FORMAT_VHD: vpcPipeline := manifest.NewVPC(buildPipeline, rawImagePipeline) vpcPipeline.ForceSize = img.VPCForceSize diff --git a/vendor/github.com/osbuild/images/pkg/manifest/anaconda_installer_iso_tree.go b/vendor/github.com/osbuild/images/pkg/manifest/anaconda_installer_iso_tree.go index 95d95387c..09923684b 100644 --- a/vendor/github.com/osbuild/images/pkg/manifest/anaconda_installer_iso_tree.go +++ b/vendor/github.com/osbuild/images/pkg/manifest/anaconda_installer_iso_tree.go @@ -105,6 +105,8 @@ type AnacondaInstallerISOTree struct { // Pipeline object where subscription-related files are created for copying // onto the ISO. SubscriptionPipeline *Subscription + + InstallRootfsType disk.FSType } func NewAnacondaInstallerISOTree(buildPipeline Build, anacondaPipeline *AnacondaInstaller, rootfsPipeline *ISORootfsImg, bootTreePipeline *EFIBootTree) *AnacondaInstallerISOTree { @@ -552,6 +554,19 @@ func (p *AnacondaInstallerISOTree) bootcInstallerKickstartStages() []*osbuild.St panic(fmt.Sprintf("failed to create kickstart stage options: %v", err)) } + // Workaround for lack of --target-imgref in Anaconda, xref https://github.com/osbuild/images/issues/380 + kickstartOptions.Post = append(kickstartOptions.Post, osbuild.PostOptions{ + ErrorOnFail: true, + Commands: []string{ + fmt.Sprintf("bootc switch --mutate-in-place --transport registry %s", p.containerSpec.LocalName), + "# used during automatic image testing as finished marker", + "if [ -c /dev/ttyS0 ]; then", + " # continue on errors here, because we used to omit --erroronfail", + ` echo "Install finished" > /dev/ttyS0 || true`, + "fi", + }, + }) + // kickstart.New() already validates the options but they may have been // modified since then, so validate them before we create the stages if err := p.Kickstart.Validate(); err != nil { @@ -612,33 +627,32 @@ func (p *AnacondaInstallerISOTree) bootcInstallerKickstartStages() []*osbuild.St stages = append(stages, osbuild.NewKickstartStage(kickstartOptions)) - // and what we can't do in a separate kickstart that we include - targetContainerTransport := "registry" - // Because osbuild core only supports a subset of options, we append to the // base here with some more hardcoded defaults // that should very likely become configurable. - hardcodedKickstartBits := ` -reqpart --add-boot + var hardcodedKickstartBits string -part swap --fstype=swap --size=1024 -part / --fstype=ext4 --grow + // using `autopart` because `part / --fstype=btrfs` didn't work + rootFsType := p.InstallRootfsType + if rootFsType == disk.FS_NONE { + // if the rootfs type is not set, we default to ext4 + rootFsType = disk.FS_EXT4 + } + switch rootFsType { + case disk.FS_BTRFS: + hardcodedKickstartBits = ` +autopart --nohome --type=btrfs +` + default: + hardcodedKickstartBits = fmt.Sprintf(` +autopart --nohome --type=plain --fstype=%s +`, rootFsType.String()) + } + hardcodedKickstartBits += ` reboot --eject ` - // Workaround for lack of --target-imgref in Anaconda, xref https://github.com/osbuild/images/issues/380 - hardcodedKickstartBits += fmt.Sprintf(`%%post --erroronfail -bootc switch --mutate-in-place --transport %s %s - -# used during automatic image testing as finished marker -if [ -c /dev/ttyS0 ]; then - # continue on errors here, because we used to omit --erroronfail - echo "Install finished" > /dev/ttyS0 || true -fi -%%end -`, targetContainerTransport, p.containerSpec.LocalName) - kickstartFile, err := kickstartOptions.IncludeRaw(hardcodedKickstartBits) if err != nil { panic(err) @@ -733,11 +747,11 @@ func (p *AnacondaInstallerISOTree) makeKickstartStages(stageOptions *osbuild.Kic } } + if sudoersPost := makeKickstartSudoersPost(kickstartOptions.SudoNopasswd); sudoersPost != nil { + stageOptions.Post = append(stageOptions.Post, *sudoersPost) + } stages = append(stages, osbuild.NewKickstartStage(stageOptions)) - hardcodedKickstartBits := "" - hardcodedKickstartBits += makeKickstartSudoersPost(kickstartOptions.SudoNopasswd) - if p.SubscriptionPipeline != nil { subscriptionPath := "/subscription" stages = append(stages, osbuild.NewMkdirStage(&osbuild.MkdirStageOptions{Paths: []osbuild.MkdirStagePath{{Path: subscriptionPath, Parents: true, ExistOk: true}}})) @@ -757,7 +771,7 @@ func (p *AnacondaInstallerISOTree) makeKickstartStages(stageOptions *osbuild.Kic systemPath = "/mnt/sysroot" } - hardcodedKickstartBits += makeKickstartSubscriptionPost(subscriptionPath, systemPath) + stageOptions.Post = append(stageOptions.Post, makeKickstartSubscriptionPost(subscriptionPath, systemPath)...) // include a readme file on the ISO in the subscription path to explain what it's for subscriptionReadme, err := fsnode.NewFile( @@ -773,16 +787,6 @@ This directory contains files necessary for registering the system on first boot p.Files = append(p.Files, subscriptionReadme) } - if hardcodedKickstartBits != "" { - // Because osbuild core only supports a subset of options, - // we append to the base here with hardcoded wheel group with NOPASSWD option - kickstartFile, err := stageOptions.IncludeRaw(hardcodedKickstartBits) - if err != nil { - panic(err) - } - - p.Files = append(p.Files, kickstartFile) - } stages = append(stages, osbuild.GenFileNodesStages(p.Files)...) return stages @@ -795,44 +799,43 @@ func makeISORootPath(p string) string { return fmt.Sprintf("file://%s", fullpath) } -func makeKickstartSudoersPost(names []string) string { +func makeKickstartSudoersPost(names []string) *osbuild.PostOptions { if len(names) == 0 { - return "" + return nil } - echoLineFmt := `echo -e "%[1]s\tALL=(ALL)\tNOPASSWD: ALL" > "/etc/sudoers.d/%[1]s" -chmod 0440 /etc/sudoers.d/%[1]s` + echoLineFmt := `echo -e "%[1]s\tALL=(ALL)\tNOPASSWD: ALL" > "/etc/sudoers.d/%[1]s"` + chmodLineFmt := `chmod 0440 /etc/sudoers.d/%[1]s` filenames := make(map[string]bool) sort.Strings(names) - entries := make([]string, 0, len(names)) + post := &osbuild.PostOptions{} for _, name := range names { if filenames[name] { continue } - entries = append(entries, fmt.Sprintf(echoLineFmt, name)) + post.Commands = append(post.Commands, + fmt.Sprintf(echoLineFmt, name), + fmt.Sprintf(chmodLineFmt, name), + ) filenames[name] = true } - kickstartSudoersPost := ` -%%post -%s -restorecon -rvF /etc/sudoers.d -%%end -` - return fmt.Sprintf(kickstartSudoersPost, strings.Join(entries, "\n")) - + post.Commands = append(post.Commands, "restorecon -rvF /etc/sudoers.d") + return post } -func makeKickstartSubscriptionPost(source, dest string) string { - // we need to use --nochroot so the command can access files on the ISO +func makeKickstartSubscriptionPost(source, dest string) []osbuild.PostOptions { fullSourcePath := filepath.Join("/run/install/repo", source, "etc/*") - kickstartSubscriptionPost := ` -%%post --nochroot -cp -r %s %s -%%end -%%post -systemctl enable osbuild-subscription-register.service -%%end -` - return fmt.Sprintf(kickstartSubscriptionPost, fullSourcePath, dest) + return []osbuild.PostOptions{ + { + // we need to use --nochroot so the command can access files on the ISO + NoChroot: true, + Commands: []string{ + fmt.Sprintf("cp -r %s %s", fullSourcePath, dest), + }, + }, + { + Commands: []string{"systemctl enable osbuild-subscription-register.service"}, + }, + } } diff --git a/vendor/github.com/osbuild/images/pkg/manifest/build.go b/vendor/github.com/osbuild/images/pkg/manifest/build.go index 1e54703e9..9d52bbf8a 100644 --- a/vendor/github.com/osbuild/images/pkg/manifest/build.go +++ b/vendor/github.com/osbuild/images/pkg/manifest/build.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/osbuild/images/pkg/container" + "github.com/osbuild/images/pkg/customizations/fsnode" "github.com/osbuild/images/pkg/osbuild" "github.com/osbuild/images/pkg/rpmmd" "github.com/osbuild/images/pkg/runner" @@ -63,6 +64,15 @@ type BuildOptions struct { // build pipeline. This is only needed when doing cross-arch // building BootstrapPipeline Build + + // In some cases we have multiple build pipelines + PipelineName string + + // Copy in files from other pipeline + CopyFilesFrom map[string][]string + + // Ensure directories exist + EnsureDirs []*fsnode.Directory } // policy or default returns the selinuxPolicy or (if unset) the @@ -82,6 +92,9 @@ func NewBuild(m *Manifest, runner runner.Runner, repos []rpmmd.RepoConfig, opts } name := "build" + if opts.PipelineName != "" { + name = opts.PipelineName + } pipeline := &BuildrootFromPackages{ Base: NewBase(name, opts.BootstrapPipeline), runner: runner, @@ -199,6 +212,9 @@ type BuildrootFromContainer struct { containerBuildable bool disableSelinux bool selinuxPolicy string + + copyFilesFrom map[string][]string + ensureDirs []*fsnode.Directory } // NewBuildFromContainer creates a new build pipeline from the given @@ -209,6 +225,9 @@ func NewBuildFromContainer(m *Manifest, runner runner.Runner, containerSources [ } name := "build" + if opts.PipelineName != "" { + name = opts.PipelineName + } pipeline := &BuildrootFromContainer{ Base: NewBase(name, opts.BootstrapPipeline), runner: runner, @@ -218,6 +237,9 @@ func NewBuildFromContainer(m *Manifest, runner runner.Runner, containerSources [ containerBuildable: opts.ContainerBuildable, disableSelinux: opts.DisableSELinux, selinuxPolicy: policyOrDefault(opts.SELinuxPolicy), + + copyFilesFrom: opts.CopyFilesFrom, + ensureDirs: opts.EnsureDirs, } m.addPipeline(pipeline) return pipeline @@ -288,6 +310,27 @@ func (p *BuildrootFromContainer) serialize() osbuild.Pipeline { panic(err) } pipeline.AddStage(stage) + + for _, stage := range osbuild.GenDirectoryNodesStages(p.ensureDirs) { + pipeline.AddStage(stage) + } + + for copyFilesFrom, copyFiles := range p.copyFilesFrom { + inputName := "copy-tree" + paths := []osbuild.CopyStagePath{} + for _, copyPath := range copyFiles { + paths = append(paths, osbuild.CopyStagePath{ + From: fmt.Sprintf("input://%s%s", inputName, copyPath), + To: fmt.Sprintf("tree://%s", copyPath), + }) + } + + pipeline.AddStage(osbuild.NewCopyStageSimple( + &osbuild.CopyStageOptions{Paths: paths}, + osbuild.NewPipelineTreeInputs(inputName, copyFilesFrom), + )) + } + if !p.disableSelinux { pipeline.AddStage(osbuild.NewSELinuxStage( &osbuild.SELinuxStageOptions{ diff --git a/vendor/github.com/osbuild/images/pkg/manifest/os.go b/vendor/github.com/osbuild/images/pkg/manifest/os.go index 37ec69f88..ed1a5846e 100644 --- a/vendor/github.com/osbuild/images/pkg/manifest/os.go +++ b/vendor/github.com/osbuild/images/pkg/manifest/os.go @@ -400,6 +400,13 @@ func (p *OS) getBuildPackages(distro Distro) []string { packages = append(packages, tomlPkgsFor(distro)...) } + if p.platform.GetBootloader() == platform.BOOTLOADER_UKI { + // Only required if the hmac stage is added, which depends on the + // version of uki-direct. Add it conditioned just on the bootloader + // type for now, until we find a better way to decide. + packages = append(packages, "libkcapi-hmaccalc") + } + return packages } @@ -495,6 +502,15 @@ func (p *OS) serialize() osbuild.Pipeline { // https://github.com/osbuild/images/issues/624 rpmOptions.DisableDracut = true } + if p.platform.GetBootloader() == platform.BOOTLOADER_UKI && p.PartitionTable != nil { + espMountpoint, err := findESPMountpoint(p.PartitionTable) + if err != nil { + panic(err) + } + rpmOptions.KernelInstallEnv = &osbuild.KernelInstallEnv{ + BootRoot: espMountpoint, + } + } pipeline.AddStage(osbuild.NewRPMStage(rpmOptions, osbuild.NewRpmStageSourceFilesInputs(p.packageSpecs))) if !p.OSCustomizations.NoBLS { @@ -707,69 +723,31 @@ func (p *OS) serialize() osbuild.Pipeline { } pipeline.AddStages(fsCfgStages...) - var bootloader *osbuild.Stage - switch p.platform.GetArch() { - case arch.ARCH_S390X: - bootloader = osbuild.NewZiplStage(new(osbuild.ZiplStageOptions)) - default: - if p.OSCustomizations.NoBLS { - // BLS entries not supported: use grub2.legacy - id := "76a22bf4-f153-4541-b6c7-0332c0dfaeac" - product := osbuild.GRUB2Product{ - Name: p.OSProduct, - Version: p.OSVersion, - Nick: p.OSNick, - } - - _, err := rpmmd.GetVerStrFromPackageSpecList(p.packageSpecs, "dracut-config-rescue") - hasRescue := err == nil - bootloader = osbuild.NewGrub2LegacyStage( - osbuild.NewGrub2LegacyStageOptions( - p.OSCustomizations.Grub2Config, - p.PartitionTable, - kernelOptions, - p.platform.GetBIOSPlatform(), - p.platform.GetUEFIVendor(), - osbuild.MakeGrub2MenuEntries(id, p.kernelVer, product, hasRescue), - ), - ) - } else { - options := osbuild.NewGrub2StageOptions(pt, - strings.Join(kernelOptions, " "), - p.kernelVer, - p.platform.GetUEFIVendor() != "", - p.platform.GetBIOSPlatform(), - p.platform.GetUEFIVendor(), false) - - // Avoid a race condition because Grub2Config may be shared when set (yay pointers!) - if p.OSCustomizations.Grub2Config != nil { - // Make a COPY of it - cfg := *p.OSCustomizations.Grub2Config - - // TODO: don't store Grub2Config in OSPipeline, making the overrides unnecessary - // grub2.Config.Default is owned and set by `NewGrub2StageOptionsUnified` - // and thus we need to preserve it - if options.Config != nil { - cfg.Default = options.Config.Default - } - - // Point to the COPY with the possibly new Default value - options.Config = &cfg - } - if p.OSCustomizations.KernelOptionsBootloader { - options.WriteCmdLine = nil - if options.UEFI != nil { - options.UEFI.Unified = false - } - } - bootloader = osbuild.NewGRUB2Stage(options) + switch p.platform.GetBootloader() { + case platform.BOOTLOADER_GRUB2: + pipeline.AddStage(grubStage(p, pt, kernelOptions)) + if !p.OSCustomizations.KernelOptionsBootloader { + pipeline = prependKernelCmdlineStage(pipeline, rootUUID, kernelOptions) } - } - - pipeline.AddStage(bootloader) - - if !p.OSCustomizations.KernelOptionsBootloader || p.platform.GetArch() == arch.ARCH_S390X { + case platform.BOOTLOADER_ZIPL: + pipeline.AddStage(osbuild.NewZiplStage(new(osbuild.ZiplStageOptions))) pipeline = prependKernelCmdlineStage(pipeline, rootUUID, kernelOptions) + case platform.BOOTLOADER_UKI: + espMountpoint, err := findESPMountpoint(pt) + if err != nil { + panic(err) + } + csvfile, err := ukiBootCSVfile(espMountpoint, p.platform.GetArch(), p.kernelVer, p.platform.GetUEFIVendor()) + if err != nil { + panic(err) + } + p.addInlineDataAndStages(&pipeline, []*fsnode.File{csvfile}) + + stages, err := maybeAddHMACandDirStage(p.packageSpecs, espMountpoint, p.kernelVer) + if err != nil { + panic(err) + } + pipeline.AddStages(stages...) } } @@ -992,6 +970,166 @@ func usersFirstBootOptions(users []users.User) *osbuild.FirstBootStageOptions { return options } +func grubStage(p *OS, pt *disk.PartitionTable, kernelOptions []string) *osbuild.Stage { + if p.OSCustomizations.NoBLS { + // BLS entries not supported: use grub2.legacy + id := "76a22bf4-f153-4541-b6c7-0332c0dfaeac" + product := osbuild.GRUB2Product{ + Name: p.OSProduct, + Version: p.OSVersion, + Nick: p.OSNick, + } + + _, err := rpmmd.GetVerStrFromPackageSpecList(p.packageSpecs, "dracut-config-rescue") + hasRescue := err == nil + return osbuild.NewGrub2LegacyStage( + osbuild.NewGrub2LegacyStageOptions( + p.OSCustomizations.Grub2Config, + p.PartitionTable, + kernelOptions, + p.platform.GetBIOSPlatform(), + p.platform.GetUEFIVendor(), + osbuild.MakeGrub2MenuEntries(id, p.kernelVer, product, hasRescue), + ), + ) + } else { + options := osbuild.NewGrub2StageOptions(pt, + strings.Join(kernelOptions, " "), + p.kernelVer, + p.platform.GetUEFIVendor() != "", + p.platform.GetBIOSPlatform(), + p.platform.GetUEFIVendor(), false) + + // Avoid a race condition because Grub2Config may be shared when set (yay pointers!) + if p.OSCustomizations.Grub2Config != nil { + // Make a COPY of it + cfg := *p.OSCustomizations.Grub2Config + + // TODO: don't store Grub2Config in OSPipeline, making the overrides unnecessary + // grub2.Config.Default is owned and set by `NewGrub2StageOptionsUnified` + // and thus we need to preserve it + if options.Config != nil { + cfg.Default = options.Config.Default + } + + // Point to the COPY with the possibly new Default value + options.Config = &cfg + } + if p.OSCustomizations.KernelOptionsBootloader { + options.WriteCmdLine = nil + if options.UEFI != nil { + options.UEFI.Unified = false + } + } + return osbuild.NewGRUB2Stage(options) + } +} + +// ukiBootCSVfile creates a file node for the csv file in the ESP which +// controls the fallback boot to the UKI. +// NOTE: This is a temporary workaround. We expect that the kernel-bootcfg +// command from the python3-virt-firmware package will gain the ability to +// write these files offline during the RHEL 9.7 / 10.1 development cycle. +func ukiBootCSVfile(espMountpoint string, architecture arch.Arch, kernelVer, vendor string) (*fsnode.File, error) { + shortArch := "" + switch architecture { + case arch.ARCH_AARCH64: + shortArch = "aa64" + case arch.ARCH_X86_64: + shortArch = "x64" + default: + return nil, fmt.Errorf("ukiBootCSVfile: UKIs are only supported for x86_64 and aarch64") + } + + kernelFilename := fmt.Sprintf("ffffffffffffffffffffffffffffffff-%s.efi", kernelVer) + data := fmt.Sprintf("shim%s.efi,%s,\\EFI\\Linux\\%s ,UKI bootentry\n", shortArch, vendor, kernelFilename) + + csvPath := filepath.Join(espMountpoint, "EFI", vendor, fmt.Sprintf("BOOT%s.CSV", strings.ToUpper(shortArch))) + + return fsnode.NewFile(csvPath, nil, nil, nil, common.EncodeUTF16le(data)) +} + +func findESPMountpoint(pt *disk.PartitionTable) (string, error) { + // the ESP in our images is always at /boot/efi, but let's make this more + // flexible and future proof by finding the ESP mountpoint from the + // partition table + espMountpoint := "" + _ = pt.ForEachMountable(func(mnt disk.Mountable, path []disk.Entity) error { + parent := path[1] + if partition, ok := parent.(*disk.Partition); ok { + // ESP filesystem parent must be a plain partition + if partition.Type != disk.EFISystemPartitionGUID { + return nil + } + + // found ESP filesystem + espMountpoint = mnt.GetMountpoint() + } + return nil + }) + + if espMountpoint == "" { + return "", fmt.Errorf("failed to find mountpoint for ESP when generating boot CSV file") + } + + return espMountpoint, nil +} + +// The 99-uki-uefi-setup.install script, prior to v25.3 of the uki-direct +// package, would run `bootctl -p` to discover the ESP [1]. This doesn't work +// in osbuild because the system isn't booted or live. Since v25.3, the install +// script respects the $BOOT_ROOT env var that we set in osbuild during the +// org.osbuild.rpm stage. +// +// This function takes care of the main issue we have with the older version of +// the script: it generates the .hmac file for the kernel in the ESP. +// A less critical issue is that the .extra.d/ directory for kernel addons +// isn't created, so this function will also return a mkdir stage for that +// directory. +// The updated package is expected to be released in RHEL 9.7 and 10.1 (and +// will possibly be backported to RHEL 9.6 and 10.0). +// +// The function will return nil if the uki-direct package includes the fix +// (v25.3+) or if the uki-direct package is not included in the package list. +// +// [1] https://gitlab.com/kraxel/virt-firmware/-/commit/ca385db4f74a4d542455b9d40c91c8448c7be90c +func maybeAddHMACandDirStage(packages []rpmmd.PackageSpec, espMountpoint, kernelVer string) ([]*osbuild.Stage, error) { + ukiDirectVer, err := rpmmd.GetVerStrFromPackageSpecList(packages, "uki-direct") + if err != nil { + // the uki-direct package isn't in the list: no override necessary + return nil, nil + } + + // The GetVerStrFromPackageSpecList function returns + // -.. For the real package version, this doesn't + // appear to cause any issues with the version parser used by + // VersionLessThan. If a mock depsolver is used this can cause issues + // (Malformed version: 0-8.fk1.x86_64). Make sure we only use the + // component to avoid issues. + ukiDirectVer = strings.SplitN(ukiDirectVer, "-", 2)[0] + + if common.VersionLessThan(ukiDirectVer, "25.3") { + // generate hmac file using stage + kernelFilename := fmt.Sprintf("ffffffffffffffffffffffffffffffff-%s.efi", kernelVer) + kernelPath := filepath.Join(espMountpoint, "EFI", "Linux", kernelFilename) + hmacStage := osbuild.NewHMACStage(&osbuild.HMACStageOptions{ + Paths: []string{kernelPath}, + Algorithm: "sha512", + }) + addonsPath := kernelPath + ".extra.d" + addonsDir, err := fsnode.NewDirectory(addonsPath, nil, nil, nil, true) + if err != nil { + return nil, err + } + dirStages := osbuild.GenDirectoryNodesStages([]*fsnode.Directory{addonsDir}) + + return append([]*osbuild.Stage{hmacStage}, dirStages...), nil + } + + // package is new enough + return nil, nil +} + func (p *OS) Platform() platform.Platform { return p.platform } diff --git a/vendor/github.com/osbuild/images/pkg/manifest/ostree_deployment.go b/vendor/github.com/osbuild/images/pkg/manifest/ostree_deployment.go index 61f54a0f8..ae6097272 100644 --- a/vendor/github.com/osbuild/images/pkg/manifest/ostree_deployment.go +++ b/vendor/github.com/osbuild/images/pkg/manifest/ostree_deployment.go @@ -131,6 +131,11 @@ func (p *OSTreeDeployment) getBuildPackages(Distro) []string { packages := []string{ "rpm-ostree", } + + if len(p.Users) > 0 { + packages = append(packages, "shadow-utils") + } + return packages } diff --git a/vendor/github.com/osbuild/images/pkg/manifest/tar.go b/vendor/github.com/osbuild/images/pkg/manifest/tar.go index 6ce2448d7..6cc1939cb 100644 --- a/vendor/github.com/osbuild/images/pkg/manifest/tar.go +++ b/vendor/github.com/osbuild/images/pkg/manifest/tar.go @@ -10,13 +10,14 @@ type Tar struct { Base filename string - Format osbuild.TarArchiveFormat - RootNode osbuild.TarRootNode - Paths []string - ACLs *bool - SELinux *bool - Xattrs *bool - Transform string + Format osbuild.TarArchiveFormat + Compression osbuild.TarArchiveCompression + RootNode osbuild.TarRootNode + Paths []string + ACLs *bool + SELinux *bool + Xattrs *bool + Transform string inputPipeline Pipeline } @@ -51,14 +52,15 @@ func (p *Tar) serialize() osbuild.Pipeline { pipeline := p.Base.serialize() tarOptions := &osbuild.TarStageOptions{ - Filename: p.Filename(), - Format: p.Format, - ACLs: p.ACLs, - SELinux: p.SELinux, - Xattrs: p.Xattrs, - RootNode: p.RootNode, - Paths: p.Paths, - Transform: p.Transform, + Filename: p.Filename(), + Format: p.Format, + Compression: p.Compression, + ACLs: p.ACLs, + SELinux: p.SELinux, + Xattrs: p.Xattrs, + RootNode: p.RootNode, + Paths: p.Paths, + Transform: p.Transform, } tarStage := osbuild.NewTarStage(tarOptions, p.inputPipeline.Name()) pipeline.AddStage(tarStage) diff --git a/vendor/github.com/osbuild/images/pkg/manifest/vagrant.go b/vendor/github.com/osbuild/images/pkg/manifest/vagrant.go new file mode 100644 index 000000000..1b182fe69 --- /dev/null +++ b/vendor/github.com/osbuild/images/pkg/manifest/vagrant.go @@ -0,0 +1,58 @@ +package manifest + +import ( + "github.com/osbuild/images/pkg/artifact" + "github.com/osbuild/images/pkg/osbuild" +) + +type Vagrant struct { + Base + filename string + + imgPipeline FilePipeline +} + +func (p Vagrant) Filename() string { + return p.filename +} + +func (p *Vagrant) SetFilename(filename string) { + p.filename = filename +} + +func NewVagrant(buildPipeline Build, imgPipeline FilePipeline) *Vagrant { + p := &Vagrant{ + Base: NewBase("vagrant", buildPipeline), + imgPipeline: imgPipeline, + filename: "image.box", + } + + if buildPipeline != nil { + buildPipeline.addDependent(p) + } else { + imgPipeline.Manifest().addPipeline(p) + } + + return p +} + +func (p *Vagrant) serialize() osbuild.Pipeline { + pipeline := p.Base.serialize() + + pipeline.AddStage(osbuild.NewVagrantStage( + osbuild.NewVagrantStageOptions(osbuild.VagrantProviderLibvirt), + osbuild.NewVagrantStagePipelineFilesInputs(p.imgPipeline.Name(), p.imgPipeline.Filename()), + )) + + return pipeline +} + +func (p *Vagrant) getBuildPackages(Distro) []string { + return []string{"qemu-img"} +} + +func (p *Vagrant) Export() *artifact.Artifact { + p.Base.export = true + mimeType := "application/x-qemu-disk" + return artifact.New(p.Name(), p.Filename(), &mimeType) +} diff --git a/vendor/github.com/osbuild/images/pkg/osbuild/kickstart_stage.go b/vendor/github.com/osbuild/images/pkg/osbuild/kickstart_stage.go index 9b93942a2..221ccbe8b 100644 --- a/vendor/github.com/osbuild/images/pkg/osbuild/kickstart_stage.go +++ b/vendor/github.com/osbuild/images/pkg/osbuild/kickstart_stage.go @@ -38,6 +38,7 @@ type KickstartStageOptions struct { AutoPart *AutoPartOptions `json:"autopart,omitempty"` Network []NetworkOptions `json:"network,omitempty"` Bootloader *BootloaderOptions `json:"bootloader,omitempty"` + Post []PostOptions `json:"%post,omitempty"` } type BootloaderOptions struct { @@ -118,6 +119,14 @@ type RootPasswordOptions struct { Password string `json:"password,omitempty"` } +type PostOptions struct { + ErrorOnFail bool `json:"erroronfail,omitempty"` + Interpreter string `json:"interpreter,omitempty"` + Log string `json:"log,omitempty"` + NoChroot bool `json:"nochroot,omitempty"` + Commands []string `json:"commands"` +} + func (KickstartStageOptions) isStageOptions() {} // Creates an Anaconda kickstart file diff --git a/vendor/github.com/osbuild/images/pkg/osbuild/rpm_stage.go b/vendor/github.com/osbuild/images/pkg/osbuild/rpm_stage.go index 5dfa78fc3..10bf5c269 100644 --- a/vendor/github.com/osbuild/images/pkg/osbuild/rpm_stage.go +++ b/vendor/github.com/osbuild/images/pkg/osbuild/rpm_stage.go @@ -23,6 +23,9 @@ type RPMStageOptions struct { // Create the '/run/ostree-booted' marker OSTreeBooted *bool `json:"ostree_booted,omitempty"` + + // Set environment variables understood by kernel-install and plugins (kernel-install(8)) + KernelInstallEnv *KernelInstallEnv `json:"kernel_install_env,omitempty"` } type Exclude struct { @@ -30,6 +33,12 @@ type Exclude struct { Docs bool `json:"docs,omitempty"` } +type KernelInstallEnv struct { + // Sets $BOOT_ROOT for kernel-install to override + // $KERNEL_INSTALL_BOOT_ROOT, the installation location for boot entries + BootRoot string `json:"boot_root,omitempty"` +} + // RPMPackage represents one RPM, as referenced by its content hash // (checksum). The files source must indicate where to fetch the given // RPM. If CheckGPG is `true` the RPM must be signed with one of the diff --git a/vendor/github.com/osbuild/images/pkg/osbuild/tar_stage.go b/vendor/github.com/osbuild/images/pkg/osbuild/tar_stage.go index 379952b45..ca1a35a2a 100644 --- a/vendor/github.com/osbuild/images/pkg/osbuild/tar_stage.go +++ b/vendor/github.com/osbuild/images/pkg/osbuild/tar_stage.go @@ -13,6 +13,18 @@ const ( TarArchiveFormatV7 TarArchiveFormat = "v7" ) +type TarArchiveCompression string + +// valid values for the 'compression' Tar stage option +const ( + // `auto` means based on filename + TarArchiveCompressionAuto TarArchiveCompression = "auto" + + TarArchiveCompressionXz TarArchiveCompression = "xz" + TarArchiveCompressionGzip TarArchiveCompression = "gzip" + TarArchiveCompressionZstd TarArchiveCompression = "zstd" +) + type TarRootNode string // valid values for the 'root-node' Tar stage option @@ -28,6 +40,9 @@ type TarStageOptions struct { // Archive format to use Format TarArchiveFormat `json:"format,omitempty"` + // Compression to use, defaults to "auto" which is based on filename + Compression TarArchiveCompression `json:"compression,omitempty"` + // Enable support for POSIX ACLs ACLs *bool `json:"acls,omitempty"` @@ -70,6 +85,25 @@ func (o TarStageOptions) validate() error { } } + if o.Compression != "" { + allowedArchiveCompressionValues := []TarArchiveCompression{ + TarArchiveCompressionAuto, + TarArchiveCompressionXz, + TarArchiveCompressionGzip, + TarArchiveCompressionZstd, + } + valid := false + for _, value := range allowedArchiveCompressionValues { + if o.Compression == value { + valid = true + break + } + } + if !valid { + return fmt.Errorf("'compression' option does not allow %q as a value", o.Compression) + } + } + if o.RootNode != "" { allowedRootNodeValues := []TarRootNode{ TarRootNodeInclude, diff --git a/vendor/github.com/osbuild/images/pkg/osbuild/vagrant_stage.go b/vendor/github.com/osbuild/images/pkg/osbuild/vagrant_stage.go new file mode 100644 index 000000000..41a85f49f --- /dev/null +++ b/vendor/github.com/osbuild/images/pkg/osbuild/vagrant_stage.go @@ -0,0 +1,54 @@ +package osbuild + +import ( + "fmt" +) + +type VagrantProvider string + +const ( + VagrantProviderLibvirt VagrantProvider = "libvirt" +) + +type VagrantStageOptions struct { + Provider VagrantProvider `json:"provider"` +} + +func (VagrantStageOptions) isStageOptions() {} + +type VagrantStageInputs struct { + Image *FilesInput `json:"image"` +} + +func (VagrantStageInputs) isStageInputs() {} + +func NewVagrantStage(options *VagrantStageOptions, inputs *VagrantStageInputs) *Stage { + if err := options.validate(); err != nil { + panic(err) + } + + return &Stage{ + Type: "org.osbuild.vagrant", + Options: options, + Inputs: inputs, + } +} + +func NewVagrantStageOptions(provider VagrantProvider) *VagrantStageOptions { + return &VagrantStageOptions{ + Provider: provider, + } +} + +func (o *VagrantStageOptions) validate() error { + if o.Provider != VagrantProviderLibvirt { + return fmt.Errorf("unknown provider in vagrant stage options %s", o.Provider) + } + + return nil +} + +func NewVagrantStagePipelineFilesInputs(pipeline, file string) *VagrantStageInputs { + input := NewFilesInput(NewFilesInputPipelineObjectRef(pipeline, file, nil)) + return &VagrantStageInputs{Image: input} +} diff --git a/vendor/github.com/osbuild/images/pkg/platform/aarch64.go b/vendor/github.com/osbuild/images/pkg/platform/aarch64.go index 2212f7d8c..4bc06c229 100644 --- a/vendor/github.com/osbuild/images/pkg/platform/aarch64.go +++ b/vendor/github.com/osbuild/images/pkg/platform/aarch64.go @@ -32,6 +32,10 @@ func (p *Aarch64) GetPackages() []string { return packages } +func (p *Aarch64) GetBootloader() Bootloader { + return BOOTLOADER_GRUB2 +} + type Aarch64_Fedora struct { BasePlatform UEFIVendor string @@ -64,3 +68,7 @@ func (p *Aarch64_Fedora) GetPackages() []string { func (p *Aarch64_Fedora) GetBootFiles() [][2]string { return p.BootFiles } + +func (p *Aarch64_Fedora) GetBootloader() Bootloader { + return BOOTLOADER_GRUB2 +} diff --git a/vendor/github.com/osbuild/images/pkg/platform/platform.go b/vendor/github.com/osbuild/images/pkg/platform/platform.go index a227e8957..ea8d814ea 100644 --- a/vendor/github.com/osbuild/images/pkg/platform/platform.go +++ b/vendor/github.com/osbuild/images/pkg/platform/platform.go @@ -3,6 +3,7 @@ package platform import ( "encoding/json" "fmt" + "strings" "github.com/osbuild/images/internal/common" "github.com/osbuild/images/pkg/arch" @@ -19,8 +20,47 @@ const ( // image format enum FORMAT_VHD FORMAT_GCE FORMAT_OVA + FORMAT_VAGRANT_LIBVIRT ) +type Bootloader int + +const ( // bootloader enum + BOOTLOADER_NONE Bootloader = iota + BOOTLOADER_GRUB2 + BOOTLOADER_ZIPL + BOOTLOADER_UKI +) + +func (b *Bootloader) UnmarshalJSON(data []byte) (err error) { + var s string + if err := json.Unmarshal(data, &s); err != nil { + return err + } + *b, err = FromString(s) + return err +} + +func (b *Bootloader) UnmarshalYAML(unmarshal func(any) error) error { + return common.UnmarshalYAMLviaJSON(b, unmarshal) +} + +func FromString(b string) (Bootloader, error) { + // ignore case + switch strings.ToLower(b) { + case "grub2": + return BOOTLOADER_GRUB2, nil + case "zipl": + return BOOTLOADER_ZIPL, nil + case "uki": + return BOOTLOADER_UKI, nil + case "", "none": + return BOOTLOADER_NONE, nil + default: + return BOOTLOADER_NONE, fmt.Errorf("unsupported bootloader %q", b) + } +} + func (f ImageFormat) String() string { switch f { case FORMAT_UNSET: @@ -39,6 +79,8 @@ func (f ImageFormat) String() string { return "gce" case FORMAT_OVA: return "ova" + case FORMAT_VAGRANT_LIBVIRT: + return "vagrant_libvirt" default: panic(fmt.Errorf("unknown image format %d", f)) } @@ -66,6 +108,8 @@ func (f *ImageFormat) UnmarshalJSON(data []byte) error { *f = FORMAT_GCE case "ova": *f = FORMAT_OVA + case "vagrant_libvirt": + *f = FORMAT_VAGRANT_LIBVIRT default: panic(fmt.Errorf("unknown image format %q", s)) } @@ -86,6 +130,7 @@ type Platform interface { GetPackages() []string GetBuildPackages() []string GetBootFiles() [][2]string + GetBootloader() Bootloader } type BasePlatform struct { @@ -125,3 +170,7 @@ func (p BasePlatform) GetBuildPackages() []string { func (p BasePlatform) GetBootFiles() [][2]string { return [][2]string{} } + +func (p BasePlatform) GetBootloader() Bootloader { + return BOOTLOADER_NONE +} diff --git a/vendor/github.com/osbuild/images/pkg/platform/ppc64le.go b/vendor/github.com/osbuild/images/pkg/platform/ppc64le.go index c258c5520..50bfc9303 100644 --- a/vendor/github.com/osbuild/images/pkg/platform/ppc64le.go +++ b/vendor/github.com/osbuild/images/pkg/platform/ppc64le.go @@ -47,3 +47,7 @@ func (p *PPC64LE) GetBuildPackages() []string { return packages } + +func (p *PPC64LE) GetBootloader() Bootloader { + return BOOTLOADER_GRUB2 +} diff --git a/vendor/github.com/osbuild/images/pkg/platform/riscv64.go b/vendor/github.com/osbuild/images/pkg/platform/riscv64.go index 3ea13c739..858818e56 100644 --- a/vendor/github.com/osbuild/images/pkg/platform/riscv64.go +++ b/vendor/github.com/osbuild/images/pkg/platform/riscv64.go @@ -40,3 +40,7 @@ func (p *RISCV64) GetBuildPackages() []string { func (p *RISCV64) GetUEFIVendor() string { return p.UEFIVendor } + +func (p *RISCV64) GetBootloader() Bootloader { + return BOOTLOADER_GRUB2 +} diff --git a/vendor/github.com/osbuild/images/pkg/platform/s390x.go b/vendor/github.com/osbuild/images/pkg/platform/s390x.go index b5350d03b..c0fa6c149 100644 --- a/vendor/github.com/osbuild/images/pkg/platform/s390x.go +++ b/vendor/github.com/osbuild/images/pkg/platform/s390x.go @@ -40,3 +40,7 @@ func (p *S390X) GetBuildPackages() []string { return packages } + +func (p *S390X) GetBootloader() Bootloader { + return BOOTLOADER_ZIPL +} diff --git a/vendor/github.com/osbuild/images/pkg/platform/x86_64.go b/vendor/github.com/osbuild/images/pkg/platform/x86_64.go index 8186641a8..0302a0a6a 100644 --- a/vendor/github.com/osbuild/images/pkg/platform/x86_64.go +++ b/vendor/github.com/osbuild/images/pkg/platform/x86_64.go @@ -8,6 +8,7 @@ type X86 struct { BasePlatform BIOS bool UEFIVendor string + Bootloader Bootloader } func (p *X86) GetArch() arch.Arch { @@ -28,18 +29,28 @@ func (p *X86) GetUEFIVendor() string { func (p *X86) GetPackages() []string { packages := p.BasePlatform.FirmwarePackages - if p.BIOS { - packages = append(packages, - "dracut-config-generic", - "grub2-pc") - } + switch p.GetBootloader() { + case BOOTLOADER_GRUB2: + if p.BIOS { + packages = append(packages, + "dracut-config-generic", + "grub2-pc") + } - if p.UEFIVendor != "" { + if p.UEFIVendor != "" { + packages = append(packages, + "dracut-config-generic", + "efibootmgr", + "grub2-efi-x64", + "shim-x64") + } + case BOOTLOADER_UKI: packages = append(packages, - "dracut-config-generic", "efibootmgr", - "grub2-efi-x64", - "shim-x64") + "kernel-uki-virt-addons", // provides useful cmdline utilities for the UKI + "shim-x64", + "uki-direct", + ) } return packages @@ -52,3 +63,10 @@ func (p *X86) GetBuildPackages() []string { } return packages } + +func (p *X86) GetBootloader() Bootloader { + if p.Bootloader == BOOTLOADER_NONE { + return BOOTLOADER_GRUB2 + } + return p.Bootloader +} diff --git a/vendor/github.com/osbuild/images/pkg/platform/yaml.go b/vendor/github.com/osbuild/images/pkg/platform/yaml.go index 2f9e4dde9..e3babed5d 100644 --- a/vendor/github.com/osbuild/images/pkg/platform/yaml.go +++ b/vendor/github.com/osbuild/images/pkg/platform/yaml.go @@ -20,6 +20,8 @@ type PlatformConf struct { Packages map[string][]string `yaml:"packages"` BuildPackages map[string][]string `yaml:"build_packages"` BootFiles [][2]string `yaml:"boot_files"` + + Bootloader Bootloader `yaml:"bootloader"` } // ensure PlatformConf implements the Platform interface @@ -60,3 +62,7 @@ func (pc *PlatformConf) GetBuildPackages() []string { func (pc *PlatformConf) GetBootFiles() [][2]string { return pc.BootFiles } + +func (pc *PlatformConf) GetBootloader() Bootloader { + return pc.Bootloader +} diff --git a/vendor/github.com/osbuild/images/pkg/runner/yaml.go b/vendor/github.com/osbuild/images/pkg/runner/yaml.go new file mode 100644 index 000000000..17b9aa5b6 --- /dev/null +++ b/vendor/github.com/osbuild/images/pkg/runner/yaml.go @@ -0,0 +1,17 @@ +package runner + +// RunnerConf implements the runner interface +var _ = Runner(&RunnerConf{}) + +type RunnerConf struct { + Name string `yaml:"name"` + BuildPackages []string `yaml:"build_packages"` +} + +func (r *RunnerConf) String() string { + return r.Name +} + +func (r *RunnerConf) GetBuildPackages() []string { + return r.BuildPackages +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 1b7b44898..46d581b07 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -416,10 +416,10 @@ github.com/containerd/stargz-snapshotter/estargz/errorutil # github.com/containerd/typeurl/v2 v2.2.3 ## explicit; go 1.21 github.com/containerd/typeurl/v2 -# github.com/containers/common v0.62.0 +# github.com/containers/common v0.62.3 ## explicit; go 1.22.8 github.com/containers/common/pkg/retry -# github.com/containers/image/v5 v5.34.0 +# github.com/containers/image/v5 v5.34.3 ## explicit; go 1.22.8 github.com/containers/image/v5/copy github.com/containers/image/v5/directory @@ -504,7 +504,7 @@ github.com/containers/ocicrypt/keywrap/pkcs7 github.com/containers/ocicrypt/spec github.com/containers/ocicrypt/utils github.com/containers/ocicrypt/utils/keyprovider -# github.com/containers/storage v1.57.1 +# github.com/containers/storage v1.57.2 ## explicit; go 1.22.0 github.com/containers/storage github.com/containers/storage/drivers @@ -1049,7 +1049,7 @@ github.com/oracle/oci-go-sdk/v54/workrequests ## explicit; go 1.22.8 github.com/osbuild/blueprint/internal/common github.com/osbuild/blueprint/pkg/blueprint -# github.com/osbuild/images v0.148.0 +# github.com/osbuild/images v0.151.0 ## explicit; go 1.22.8 github.com/osbuild/images/data/dependencies github.com/osbuild/images/data/repositories @@ -1076,7 +1076,7 @@ github.com/osbuild/images/pkg/datasizes github.com/osbuild/images/pkg/disk github.com/osbuild/images/pkg/distro github.com/osbuild/images/pkg/distro/defs -github.com/osbuild/images/pkg/distro/fedora +github.com/osbuild/images/pkg/distro/generic github.com/osbuild/images/pkg/distro/rhel github.com/osbuild/images/pkg/distro/rhel/rhel10 github.com/osbuild/images/pkg/distro/rhel/rhel7