Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions pkg/daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -1236,8 +1236,10 @@ func (dn *Daemon) RunFirstbootCompleteMachineconfig(machineConfigFile string) er
// If the host isn't new enough to understand the new container model natively, run as a privileged container.
// See https://github.com/coreos/rpm-ostree/pull/3961 and https://issues.redhat.com/browse/MCO-356
// This currently will incur a double reboot; see https://github.com/coreos/rpm-ostree/issues/4018
if !newEnough {
logSystem("rpm-ostree is not new enough for new-format image; forcing an update via container and queuing immediate reboot")
// If Skopeo used by rpm-ostree is an older version supporting multi-arch Sigstore verificaiton, run as a privileged container which has updated skopeo.
// See https://redhat.atlassian.net/browse/OCPBUGS-83826 and https://redhat.atlassian.net/browse/OCPBUGS-81187
Comment on lines +1239 to +1240
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix fallback comment wording (reversed meaning + typo).

The comment currently says older skopeo versions are “supporting” multi-arch Sigstore verification and has a typo (“verificaiton”). It should say older versions do not support it.

✏️ Proposed comment fix
- // If Skopeo used by rpm-ostree is an older version supporting multi-arch Sigstore verificaiton, run as a privileged container which has updated skopeo.
+ // If skopeo used by rpm-ostree is an older version not supporting multi-arch Sigstore verification,
+ // run as a privileged container which has updated skopeo.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// If Skopeo used by rpm-ostree is an older version supporting multi-arch Sigstore verificaiton, run as a privileged container which has updated skopeo.
// See https://redhat.atlassian.net/browse/OCPBUGS-83826 and https://redhat.atlassian.net/browse/OCPBUGS-81187
// If skopeo used by rpm-ostree is an older version not supporting multi-arch Sigstore verification,
// run as a privileged container which has updated skopeo.
// See https://redhat.atlassian.net/browse/OCPBUGS-83826 and https://redhat.atlassian.net/browse/OCPBUGS-81187
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/daemon/daemon.go` around lines 1239 - 1240, Update the comment that
begins "If Skopeo used by rpm-ostree..." to correct the typo and reverse the
meaning: state that older skopeo versions do NOT support multi-arch Sigstore
verification (replace "supporting" with "do not support" and fix "verificaiton"
to "verification"), so the comment accurately explains why we fall back to
running a privileged container. Keep the rest of the context and links
unchanged.

if !newEnough || !skopeoSupportsMultiArchSigstore() {
logSystem("rpm-ostree or skopeo is not new enough for new-format image; forcing an update via container and queuing immediate reboot")
if err := dn.InplaceUpdateViaNewContainer(mc.Spec.OSImageURL); err != nil {
return err
}
Expand Down
46 changes: 44 additions & 2 deletions pkg/daemon/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -2758,8 +2758,10 @@ func (dn *Daemon) updateLayeredOS(config *mcfgv1.MachineConfig) error {
// If the host isn't new enough to understand the new container model natively, run as a privileged container.
// See https://github.com/coreos/rpm-ostree/pull/3961 and https://issues.redhat.com/browse/MCO-356
// This currently will incur a double reboot; see https://github.com/coreos/rpm-ostree/issues/4018
if !newEnough {
logSystem("rpm-ostree is not new enough for layering; forcing an update via container")
// If Skopeo used by rpm-ostree is an older version supporting multi-arch Sigstore verificaiton, run as a privileged container which has updated skopeo.
// See https://redhat.atlassian.net/browse/OCPBUGS-83826 and https://redhat.atlassian.net/browse/OCPBUGS-81187
if !newEnough || !skopeoSupportsMultiArchSigstore() {
logSystem("rpm-ostree or skopeo is not new enough for layering; forcing an update via container")
return dn.InplaceUpdateViaNewContainer(newURL)
}

Expand Down Expand Up @@ -2938,6 +2940,46 @@ func podmanSupportsSigstore() bool {
return podmanSigstoreSupportedValue
}

var (
skopeoMultiArchSigstoreSupported sync.Once
skopeoMultiArchSigstoreSupportedValue bool
)

func skopeoSupportsMultiArchSigstore() bool {
skopeoMultiArchSigstoreSupported.Do(func() {
// https://issues.redhat.com/browse/OCPBUGS-81187
// Multi-arch Sigstore fixed in skopeo 1.22.2
cmd := exec.Command("skopeo", "--version")
out, err := cmd.CombinedOutput()
if err != nil {
klog.Errorf("failed to run skopeo --version: %v", err)
skopeoMultiArchSigstoreSupportedValue = false
return
}
// Output format: "skopeo version 1.21.0-dev commit: d8be59c1ecc5c1860b7bab4f60721d55da2cda9a"
fields := strings.Fields(strings.TrimSpace(string(out)))
if len(fields) < 3 {
klog.Errorf("unexpected skopeo version output format: %s", string(out))
skopeoMultiArchSigstoreSupportedValue = false
return
}

versionStr := fields[2]
if dashIdx := strings.Index(versionStr, "-"); dashIdx != -1 {
versionStr = versionStr[:dashIdx]
}
skopeoVersion, err := semver.NewVersion(versionStr)
if err != nil {
klog.Errorf("failed to parse skopeo version %s: %v", versionStr, err)
skopeoMultiArchSigstoreSupportedValue = false
return
}
minSkopeoVersionForMultiArchSigstore := "1.22.2"
skopeoMultiArchSigstoreSupportedValue = skopeoVersion.Compare(*semver.New(minSkopeoVersionForMultiArchSigstore)) >= 0
})
return skopeoMultiArchSigstoreSupportedValue
}
Comment on lines +2948 to +2981
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid fail-open downgrade when the skopeo probe fails.

At Line 2958, Line 2967, and Line 2978, probe/parsing errors force false, and that directly triggers the fully permissive policy branch in pkg/daemon/rpm-ostree.go Line 305. Detection failures should not silently disable verification.

🔧 Suggested direction
-var (
-	skopeoMultiArchSigstoreSupported      sync.Once
-	skopeoMultiArchSigstoreSupportedValue bool
-)
+var (
+	skopeoMultiArchSigstoreSupported      sync.Once
+	skopeoMultiArchSigstoreSupportedValue bool
+	skopeoMultiArchSigstoreProbeErr       error
+)

-func skopeoSupportsMultiArchSigstore() bool {
+func skopeoSupportsMultiArchSigstore() (bool, error) {
 	skopeoMultiArchSigstoreSupported.Do(func() {
 		cmd := exec.Command("skopeo", "--version")
 		out, err := cmd.CombinedOutput()
 		if err != nil {
-			klog.Errorf("failed to run skopeo --version: %v", err)
-			skopeoMultiArchSigstoreSupportedValue = false
+			skopeoMultiArchSigstoreProbeErr = fmt.Errorf("failed to run skopeo --version: %w", err)
 			return
 		}
 		...
 		if err != nil {
-			klog.Errorf("failed to parse skopeo version %s: %v", versionStr, err)
-			skopeoMultiArchSigstoreSupportedValue = false
+			skopeoMultiArchSigstoreProbeErr = fmt.Errorf("failed to parse skopeo version %s: %w", versionStr, err)
 			return
 		}
 		skopeoMultiArchSigstoreSupportedValue = skopeoVersion.Compare(*semver.New(minSkopeoVersionForMultiArchSigstore)) >= 0
 	})
-	return skopeoMultiArchSigstoreSupportedValue
+	return skopeoMultiArchSigstoreSupportedValue, skopeoMultiArchSigstoreProbeErr
 }

Then gate permissive fallback only when probe succeeded and version is truly below minimum.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/daemon/update.go` around lines 2951 - 2987, The probe currently treats
any skopeo --version parse error as "false" which enables the permissive
fallback; modify skopeoSupportsMultiArchSigstore by introducing a probe-success
flag (e.g., skopeoMultiArchSigstoreProbeSucceeded) that is only set to true when
the command runs and the version comparison completes successfully (use existing
symbols skopeoMultiArchSigstoreSupported.Do,
skopeoMultiArchSigstoreSupportedValue, minSkopeoVersionForMultiArchSigstore and
semver parsing), and do not flip skopeoMultiArchSigstoreSupportedValue on
parse/exec errors; then update the code path in rpm-ostree.go that currently
gates permissive fallback on skopeoMultiArchSigstoreSupportedValue to require
the probe-success flag as well (i.e., only allow the permissive branch when the
probe succeeded and the version is below the minimum).


// Log a message to the systemd journal as well as our stdout
func logSystem(format string, a ...interface{}) {
message := fmt.Sprintf(format, a...)
Expand Down