Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add imgref module that parses ostree-container image references #21

Merged
merged 1 commit into from
Sep 14, 2023
Merged
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
10 changes: 10 additions & 0 deletions pkg/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (

"github.com/containers/image/v5/docker/reference"
yaml "gopkg.in/yaml.v3"

"github.com/coreos/rpmostree-client-go/pkg/imgref"
)

// Status summarizes the current worldview of the rpm-ostree daemon.
Expand Down Expand Up @@ -172,6 +174,14 @@ func (s *Deployment) GetBaseChecksum() string {
return s.Checksum
}

// Parse the deployment's container image reference.
func (d *Deployment) RequireContainerImage() (*imgref.OstreeImageReference, error) {
if d.ContainerImageReference == "" {
return nil, fmt.Errorf("deployment is not using a container origin")
}
return imgref.Parse(d.ContainerImageReference)
}

// Remove the pending deployment.
func (client *Client) RemovePendingDeployment() error {
return client.run("cleanup", "-p")
Expand Down
4 changes: 4 additions & 0 deletions pkg/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ func TestParseFcosContainer(t *testing.T) {

firstDeploy := s.Deployments[0]
assert.Equal(t, firstDeploy.ContainerImageReference, "ostree-unverified-registry:quay.io/fedora/fedora-coreos:testing-devel")

ir, err := firstDeploy.RequireContainerImage()
assert.Nil(t, err)
assert.Equal(t, ir.Imgref.Image, "quay.io/fedora/fedora-coreos:testing-devel")
}

func TestParseFcosWithOverrides(t *testing.T) {
Expand Down
91 changes: 91 additions & 0 deletions pkg/imgref/imgref.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// package imgref parses ostree-container image references.
package imgref

import (
"fmt"
"strings"
)

// SignatureVerify is a mirror of https://docs.rs/ostree-ext/latest/ostree_ext/container/enum.SignatureSource.html
type SignatureVerify struct {
AllowInsecure bool
OstreeRemote string
}

type ImageReferenceWithTransport struct {
// IsRegistry is true if this image is fetched from a registry
Transport string
// Image is the unparsed string representation of a container image.
// For e.g. oci-archive: it will be a filesystem path.
// It can include a tag or digest (or not).
Image string
}

// OstreeImage reference captures an ostree signature verification policy alongside an image reference.
// This mirrors https://docs.rs/ostree-ext/latest/ostree_ext/container/struct.OstreeImageReference.html
type OstreeImageReference struct {
Sigverify SignatureVerify
Imgref ImageReferenceWithTransport
}

// IsRegistry returns true if this image will be fetched from a registry.
func (ir *ImageReferenceWithTransport) IsRegistry() bool {
return ir.Transport == "registry"
}

// parseImageReference mirrors https://docs.rs/ostree-ext/0.12.0/src/ostree_ext/container/mod.rs.html#129
func parseImageReference(ir string) (*ImageReferenceWithTransport, error) {
irparts := strings.SplitN(ir, ":", 2)
if len(irparts) < 2 {
return nil, fmt.Errorf("invalid image reference (missing ':'): %s", ir)
}

imgref := ImageReferenceWithTransport{
Transport: irparts[0],
Image: irparts[1],
}
// docker:// is a special case; we want to rename it and also trim the //
if imgref.Transport == "docker" {
imgref.Transport = "registry"
if !strings.HasPrefix(imgref.Image, "//") {
return nil, fmt.Errorf("missing // in docker://")
}
imgref.Image = imgref.Image[2:]
}
return &imgref, nil
}

func Parse(ir string) (*OstreeImageReference, error) {
parts := strings.SplitN(ir, ":", 2)
if len(parts) != 2 {
panic("Expected 2 parts")
}
first := parts[0]
second := parts[1]
sigverify := SignatureVerify{}
rest := second
switch first {
case "ostree-image-signed":
case "ostree-unverified-image":
sigverify = SignatureVerify{AllowInsecure: true}
case "ostree-unverified-registry":
sigverify = SignatureVerify{AllowInsecure: true}
rest = "registry:" + second
case "ostree-remote-registry":
subparts := strings.SplitN(rest, ":", 2)
sigverify = SignatureVerify{OstreeRemote: subparts[0], AllowInsecure: true}
rest = "registry:" + subparts[1]
case "ostree-remote-image":
subparts := strings.SplitN(rest, ":", 2)
sigverify = SignatureVerify{OstreeRemote: subparts[0], AllowInsecure: true}
rest = subparts[1]
default:
return nil, fmt.Errorf("invalid ostree image reference (unmatched scheme): %s", ir)
}

imgref, err := parseImageReference(rest)
if err != nil {
return nil, err
}
return &OstreeImageReference{Sigverify: sigverify, Imgref: *imgref}, nil
}
37 changes: 37 additions & 0 deletions pkg/imgref/imgref_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package imgref

import (
_ "embed"
"testing"

"github.com/stretchr/testify/assert"
)

func TestOstreeImageReference(t *testing.T) {
equivalent := []string{
"ostree-unverified-image:docker://quay.io/exampleos/blah",
"ostree-unverified-registry:quay.io/exampleos/blah",
}
for _, ir := range equivalent {
ir, err := Parse(ir)
assert.Nil(t, err)
assert.True(t, ir.Sigverify.AllowInsecure)
assert.Len(t, ir.Sigverify.OstreeRemote, 0)
assert.Equal(t, ir.Imgref.Transport, "registry")
assert.Equal(t, ir.Imgref.Image, "quay.io/exampleos/blah")
}

equivalent = []string{
"ostree-remote-registry:fedora:quay.io/fedora/fedora-coreos:stable",
"ostree-remote-image:fedora:registry:quay.io/fedora/fedora-coreos:stable",
"ostree-remote-image:fedora:docker://quay.io/fedora/fedora-coreos:stable",
}
for _, ir := range equivalent {
ir, err := Parse(ir)
assert.Nil(t, err)
assert.True(t, ir.Sigverify.AllowInsecure)
assert.Equal(t, ir.Sigverify.OstreeRemote, "fedora")
assert.Equal(t, ir.Imgref.Transport, "registry")
assert.Equal(t, ir.Imgref.Image, "quay.io/fedora/fedora-coreos:stable")
}
}