oci

package
v0.37.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 8, 2026 License: AGPL-3.0 Imports: 33 Imported by: 0

Documentation

Overview

Package oci contains UDS-specific OCI layout and registry orchestration.

Generic OCI mechanics belong to ORAS: content-addressed storage, descriptor verification, graph traversal, registry copies, retries, and repository access. This package keeps the UDS bundle pieces that upstream libraries cannot infer, including ADR-0015 child/root indexes, bundle media types, source reference dispatch, and archive push/pull workflows. Code outside this package should use these helpers for descriptor fetches instead of calling ORAS fetch functions directly.

Zarf package semantics belong in internal/zarf and upstream Zarf APIs. Code in this package should operate on standard OCI descriptors and ORAS targets, not reinterpret Zarf package structure.

Index

Constants

View Source
const (
	// Media types for UDS bundle OCI artifacts.
	MediaTypeBundleDefinition = "application/vnd.defenseunicorns.uds.bundle.definition.v1"
	MediaTypeBundleHCL        = "application/vnd.defenseunicorns.uds.bundle.hcl.v1"
	MediaTypeBundleValuesYAML = "application/vnd.defenseunicorns.uds.bundle.values.v1+yaml"

	// MediaTypeBundle is the artifactType of the canonical single-arch bundle
	// index (the child index a published tag's root index points at, and the
	// index.json inside a bundle .tar.zst). See ADR-0015.
	MediaTypeBundle = "application/vnd.defenseunicorns.uds.bundle.v1"

	// MediaTypeZarfLayer is the media type for Zarf package file layers.
	MediaTypeZarfLayer = "application/vnd.defenseunicorns.zarf.layer.v1"
	// AnnotationBundleArchitecture records the architecture of a child bundle index.
	AnnotationBundleArchitecture = "uds.dev/architecture"
	// AnnotationPackageName records the bundle package name that identifies a package descriptor.
	AnnotationPackageName = "uds.dev/package.name"
	// AnnotationPackageSource records the bundle package source for provenance.
	AnnotationPackageSource = "uds.dev/package.source"

	// AnnotationPackageVerification records a successful package verification during bundle creation.
	AnnotationPackageVerification = "uds.dev/package-verification"
	// AnnotationPackageVerificationVerified is the persisted value for a successful verification.
	AnnotationPackageVerificationVerified = "verified"
	// AnnotationReconfiguredFrom records the source bundle's child-index digest during reconfigure.
	AnnotationReconfiguredFrom = "org.defenseunicorns.uds.reconfigured-from"
)
View Source
const BundleSignatureFileName = "uds.bundle.sig"

BundleSignatureFileName is the archive-root filename for bundle signature evidence.

View Source
const (

	// MaxFetchBytesSize is the largest descriptor UDS CLI will buffer in memory.
	MaxFetchBytesSize = 16 << 20
)
View Source
const MediaTypeBundleSignature = cosignbundle.BundleV03MediaType

MediaTypeBundleSignature identifies standard Sigstore bundle evidence.

Variables

View Source
var (
	ErrStoreRootRequired            = errors.New("OCI store root is required")
	ErrBundleDefinitionNotFound     = errors.New("bundle definition manifest not found in index")
	ErrTagReferenceRequired         = errors.New("OCI source must use a tag reference, not a digest")
	ErrOpenLayout                   = errors.New("opening OCI layout")
	ErrCreateBlobDirectory          = errors.New("creating OCI blob directory")
	ErrReadIndex                    = errors.New("reading index.json")
	ErrParseIndex                   = errors.New("parsing index.json")
	ErrParseReference               = errors.New("parsing OCI reference")
	ErrFetchContent                 = errors.New("fetching OCI content")
	ErrCopyGraph                    = errors.New("copying OCI graph")
	ErrCheckTargetTag               = errors.New("checking target tag")
	ErrPushRootIndex                = errors.New("pushing root index")
	ErrListBlobs                    = errors.New("listing OCI blobs")
	ErrParseBlobDigest              = errors.New("parsing OCI blob digest")
	ErrRemoveUnreferencedBlob       = errors.New("removing unreferenced blob")
	ErrReadSuccessors               = errors.New("reading descriptor successors")
	ErrVerifyDescriptor             = errors.New("verifying descriptor")
	ErrLoadCredentials              = errors.New("loading docker credentials")
	ErrDetermineRegistryTransport   = errors.New("determining registry transport")
	ErrResolveReference             = errors.New("resolving OCI reference")
	ErrConfigureTransfer            = errors.New("configuring OCI transfer")
	ErrPushContent                  = errors.New("pushing OCI content")
	ErrPullContent                  = errors.New("pulling OCI content")
	ErrTagContent                   = errors.New("tagging OCI content")
	ErrCreateTemporaryDirectory     = errors.New("creating temporary directory")
	ErrCreateOCIDirectory           = errors.New("creating OCI directory")
	ErrCreateStore                  = errors.New("creating OCI store")
	ErrWriteIndex                   = errors.New("writing index.json")
	ErrRemoveDuplicateIndexBlob     = errors.New("removing duplicate index blob")
	ErrCreateBundleArchive          = errors.New("creating bundle archive")
	ErrBundleArchiveHookRequired    = errors.New("creating bundle archive: archive hook is required")
	ErrMissingArchitecture          = errors.New("bundle is missing its architecture annotation")
	ErrReadRootDescriptor           = errors.New("reading OCI root descriptor")
	ErrReadExistingRootIndex        = errors.New("reading existing root index")
	ErrMarshalRootIndex             = errors.New("marshaling root index")
	ErrParseExistingRegistryContent = errors.New("parsing existing registry content")
	ErrInvalidBundle                = errors.New("content is not a valid UDS bundle")
	ErrArchitectureUnavailable      = errors.New("bundle architecture is unavailable")
	ErrPushTagRequired              = errors.New("bundles must be pushed to a tag reference")
	ErrCheckBundleContent           = errors.New("checking bundle content")
	ErrBundleSignatureNotFound      = errors.New("bundle signature evidence not found")
	ErrBundleSignatureDuplicate     = errors.New("duplicate bundle signature evidence")
)

Functions

func BundleChildDescriptor

func BundleChildDescriptor(desc ocispec.Descriptor, arch string) ocispec.Descriptor

BundleChildDescriptor returns desc annotated as a bundle child index for arch.

func CopyGraph

CopyGraph copies the graph rooted at root from src to dst using ORAS defaults.

func EnsureTagAvailable

func EnsureTagAvailable(ctx context.Context, target oras.Target, tag string) error

EnsureTagAvailable returns an error when target already has tag or cannot check it.

func FetchBundleSignature

func FetchBundleSignature(ctx context.Context, source oras.Target, subject ocispec.Descriptor) ([]byte, error)

FetchBundleSignature discovers and fetches Sigstore evidence for subject.

func FetchBytes

func FetchBytes(ctx context.Context, fetcher content.Fetcher, desc ocispec.Descriptor) ([]byte, error)

FetchBytes fetches descriptor content, verifies it against the descriptor digest and size, and returns the full content in memory.

This is the buffered path. Use it only when the caller needs the complete []byte value, such as for OCI indexes, manifests, configs, or bundle definition layers. The size limit is checked before reading so a registry or archive cannot force unbounded memory use.

Do not use FetchBytes for package layers or arbitrary content blobs. Those can be large and should be copied by ORAS graph operations or streamed through Fetch with content.NewVerifyReader when verification is needed.

The fetcher passed to FetchBytes should not perform eager body reads before FetchBytes is called. For metadata-only reads from a local OCI layout, open the layout with OpenReadOnlyStore instead of OpenStore.

func FindBundleDefinition

func FindBundleDefinition(idx ocispec.Index) (ocispec.Descriptor, int, error)

FindBundleDefinition locates the bundle definition manifest in a spec index.

func IsBundleIndex

func IsBundleIndex(idx ocispec.Index) bool

IsBundleIndex reports whether idx is a canonical bundle index.

func IsImageManifestMediaType

func IsImageManifestMediaType(mediaType string) bool

IsImageManifestMediaType reports whether mediaType identifies an OCI or Docker image manifest.

func IsNotFound

func IsNotFound(err error) bool

IsNotFound reports whether err is an ORAS not-found error.

func IsOCIReference

func IsOCIReference(s string) bool

IsOCIReference checks if a string looks like an OCI registry reference (e.g., "oci://ghcr.io/org/repo:tag", "ghcr.io/org/repo:tag", or "registry.example.com/image").

func NewBundleIndex

func NewBundleIndex(manifests []ocispec.Descriptor, arch string) *ocispec.Index

NewBundleIndex builds a deterministic single-architecture bundle index.

func NewDescriptorFromBytes

func NewDescriptorFromBytes(mediaType string, data []byte) ocispec.Descriptor

NewDescriptorFromBytes returns the descriptor for data using ORAS digest and size calculation.

func NewRemoteRepository

func NewRemoteRepository(ctx context.Context, ref string, opts bundleinternal.ConfigOptions) (*orasregistry.Repository, error)

NewRemoteRepository creates an ORAS remote repository configured with registry transport settings and credentials loaded from the Docker credential store.

func OpenReadOnlyStore

func OpenReadOnlyStore(root string) (content.Fetcher, error)

OpenReadOnlyStore opens an existing OCI layout as a lazy descriptor fetcher.

Use OpenReadOnlyStore with FetchBytes for metadata-only local reads, such as inspect operations that need indexes, manifests, configs, or definition layers. This opener does not index the ORAS graph, so FetchBytes is the first code path that reads descriptor bodies and its size limit is effective.

Do not use OpenReadOnlyStore when the caller needs tags, resolution, graph traversal, graph verification, pushes, deletes, saves, or garbage collection; use OpenStore or CreateStore for those full-store operations.

func PackBundleDefinitionManifest

func PackBundleDefinitionManifest(ctx context.Context, store content.Storage, layers []ocispec.Descriptor) (ocispec.Descriptor, error)

PackBundleDefinitionManifest stores the bundle definition artifact manifest.

func PublishBundleRootIndex

func PublishBundleRootIndex(ctx context.Context, target oras.Target, tag string, child ocispec.Descriptor) error

PublishBundleRootIndex wraps child in the multi-architecture root index at tag.

func PublishBundleSignature

func PublishBundleSignature(ctx context.Context, target oras.Target, subject ocispec.Descriptor, data []byte, overwrite bool) error

PublishBundleSignature publishes singleton Sigstore evidence for a child bundle index.

func PushBytes

func PushBytes(ctx context.Context, pusher content.Pusher, mediaType string, data []byte, annotations map[string]string) (ocispec.Descriptor, error)

PushBytes stores data and returns the descriptor that addresses it.

func PushDescriptorBytes

func PushDescriptorBytes(ctx context.Context, pusher content.Pusher, desc ocispec.Descriptor, data []byte) error

PushDescriptorBytes stores data for desc and treats an existing content-addressed blob as success.

func PushManifestBytes

func PushManifestBytes(ctx context.Context, pusher content.Pusher, mediaType, artifactType string, data []byte) (ocispec.Descriptor, error)

PushManifestBytes stores manifest bytes and returns a descriptor annotated with the manifest artifact type.

func PushReferenceBytes

func PushReferenceBytes(ctx context.Context, target oras.Target, desc ocispec.Descriptor, data []byte, reference string) error

PushReferenceBytes stores manifest bytes at reference. Remote ORAS repositories need PushReference so the bytes go to the manifest endpoint; generic Push writes to the blob store there. Local/test targets that do not expose PushReference fall back to Push plus Tag.

func ReferenceIdentifier

func ReferenceIdentifier(ref string) (string, error)

ReferenceIdentifier returns the tag/digest portion of an OCI reference.

func ResolveBundleChild

func ResolveBundleChild(ctx context.Context, src oras.Target, reference, arch string) (ocispec.Descriptor, []byte, error)

ResolveBundleChild resolves reference to the canonical single-arch bundle index and returns its descriptor and raw bytes.

func ResolvePlainHTTP

func ResolvePlainHTTP(ctx context.Context, ref string, opts bundleinternal.ConfigOptions, transport http.RoundTripper) (bool, error)

ResolvePlainHTTP determines whether an OCI reference should use plain HTTP. Plain HTTP is only considered when the user explicitly enables it; HTTPS remains the default and is preferred whenever the registry supports it.

func SortDescriptors

func SortDescriptors(manifests []ocispec.Descriptor)

SortDescriptors sorts descriptors deterministically by digest and metadata.

func Tag

func Tag(ctx context.Context, target interface {
	Tag(context.Context, ocispec.Descriptor, string) error
}, desc ocispec.Descriptor, reference string) error

Tag records reference for desc on target.

func TaggedDerivativeReference

func TaggedDerivativeReference(source, suffix string) (string, string, string, error)

TaggedDerivativeReference returns source tag, target tag, and target reference for a suffixed derivative tag.

func TrimScheme

func TrimScheme(refName string) string

TrimScheme removes the scheme from a reference name (e.g., "oci://ghcr.io/org/repo:tag" -> "ghcr.io/org/repo:tag")

func VerifyLocalLayoutGraph

func VerifyLocalLayoutGraph(ctx context.Context, root string, index []byte) error

VerifyLocalLayoutGraph verifies every descriptor reachable from the OCI index in root.

func WriteIndex

func WriteIndex(path string, idx *ocispec.Index) error

WriteIndex writes an OCI image index.

Types

type ConflictingDescriptorSizeError

type ConflictingDescriptorSizeError struct {
	Digest       digest.Digest
	RecordedSize int64
	ActualSize   int64
}

func (ConflictingDescriptorSizeError) Error

type DescriptorTooLargeError

type DescriptorTooLargeError struct {
	Digest digest.Digest
	Size   int64
	Limit  int64
}

func (DescriptorTooLargeError) Error

func (e DescriptorTooLargeError) Error() string

type EmptyParameterError

type EmptyParameterError struct{ Name string }

func (EmptyParameterError) Error

func (e EmptyParameterError) Error() string

type InvalidDigestError

type InvalidDigestError struct {
	Digest string
	Err    error
}

func (InvalidDigestError) Error

func (e InvalidDigestError) Error() string

func (InvalidDigestError) Unwrap

func (e InvalidDigestError) Unwrap() error

type ManifestCountError

type ManifestCountError struct {
	Count int
	Want  int
}

func (ManifestCountError) Error

func (e ManifestCountError) Error() string

type PullHooks

type PullHooks struct {
	ToOrasTarget        func(ctx context.Context, ociReference string, opts *PullOptions) (oras.Target, error)
	ModifyOrasSettings  func(ctx context.Context, copyOptions *oras.CopyOptions) error
	VerifyBundle        func(ctx context.Context, index, evidence []byte) error
	CreateBundleArchive func(ctx context.Context, streams iostreams.IOStreams, ociDir, targetDir string, idx ocispec.Index, arch string) (string, error)
}

PullHooks provides extension points for OCI pulls.

type PullOptions

type PullOptions struct {
	Config                    *bundleinternal.UDSBundleConfig
	Streams                   iostreams.IOStreams
	SkipSignatureVerification bool
	PullHooks                 PullHooks
}

PullOptions configures an OCI pull operation.

func (PullOptions) Validate

func (o PullOptions) Validate() error

Validate validates pull options.

type PullResult

type PullResult struct {
	OCIReference string `json:"ociReference" yaml:"ociReference" text:"OCI Reference"`
	OutputPath   string `json:"outputPath" yaml:"outputPath" text:"Output Path"`
}

PullResult describes a completed OCI pull.

type Puller

type Puller interface {
	// PullBundle pulls a bundle from the given OCI reference and writes it to targetDir.
	PullBundle(ctx context.Context, ociReference, targetDir string, opts PullOptions) (*PullResult, error)
	// PullPackage pulls a single Zarf package from the given OCI reference to targetDir.
	PullPackage(ctx context.Context, ociReference, targetDir string, opts PullOptions) (*PullResult, error)
}

Puller pulls bundle artifacts from an OCI registry.

func NewDefaultPuller

func NewDefaultPuller() Puller

NewDefaultPuller returns the default Puller implementation.

type PushHooks

type PushHooks struct {
	ToOrasTarget func(ctx context.Context, ociReference string, opts *PushOptions) (oras.Target, error)
	// ModifyOrasSettings is not called when a bundle push is already fully published and no copy is required.
	ModifyOrasSettings func(ctx context.Context, copyOptions *oras.CopyOptions) error
}

PushHooks provides extension points for OCI pushes.

type PushOptions

type PushOptions struct {
	Config    *bundleinternal.UDSBundleConfig
	Streams   iostreams.IOStreams
	PushHooks PushHooks
}

PushOptions configures an OCI push operation.

func (PushOptions) Validate

func (o PushOptions) Validate() error

Validate validates push options.

type PushResult

type PushResult struct {
	OCIReference string `json:"ociReference" yaml:"ociReference" text:"OCI Reference"`
}

PushResult describes a completed OCI push.

type Pusher

type Pusher interface {
	// PushBundle pushes the OCI layout in bundleDir to the given OCI reference.
	// bundleDir must contain an oci/ subdirectory with a valid OCI layout (index.json + blobs/).
	PushBundle(ctx context.Context, bundleDir, ociReference string, opts PushOptions) (*PushResult, error)
	// PushPackage pushes a single Zarf package from packageDir to the given OCI reference.
	PushPackage(ctx context.Context, packageDir, ociReference string, opts PushOptions) (*PushResult, error)
}

Pusher pushes bundle artifacts to an OCI registry.

func NewDefaultPusher

func NewDefaultPusher() Pusher

NewDefaultPusher returns the default Pusher implementation.

type Store

type Store struct {
	*orasoci.Store
	// contains filtered or unexported fields
}

Store is a bundle OCI layout backed by ORAS content storage.

func CreateStore

func CreateStore(root string) (*Store, error)

CreateStore opens a mutable OCI layout at root, creating it when necessary.

Use CreateStore when the caller owns the layout and may write blobs, update tags, save indexes, run garbage collection, or verify/copy graphs. CreateStore opens the full ORAS OCI store, which indexes the layout graph while opening.

Do not use CreateStore for metadata-only inspection of untrusted archives; use OpenReadOnlyStore with FetchBytes instead so size limits apply before blob bodies are read.

func OpenStore

func OpenStore(root string) (*Store, error)

OpenStore opens an existing OCI layout as a full local store.

Use OpenStore when the caller needs full OCI layout behavior: tag resolution, graph traversal, graph verification, copying, deleting, saving indexes, or pruning unreferenced blobs. OpenStore does not intentionally modify the layout, but it opens the full ORAS store, which indexes the layout graph while opening.

Do not use OpenStore for metadata-only inspection of untrusted archives before bounded reads; use OpenReadOnlyStore with FetchBytes for that case.

func (*Store) BlobPath

func (s *Store) BlobPath(d godigest.Digest) (string, error)

BlobPath returns the filesystem path for a content digest.

func (*Store) PruneUnreferencedBlobs

func (s *Store) PruneUnreferencedBlobs(ctx context.Context, streams iostreams.IOStreams, manifests []ocispec.Descriptor) error

PruneUnreferencedBlobs removes blobs not referenced by manifests, including manifest and config blobs.

func (*Store) Push

func (s *Store) Push(ctx context.Context, desc ocispec.Descriptor, r io.Reader) error

Push stores verified content and treats an existing content-addressed blob as success.

func (*Store) PushBytes

func (s *Store) PushBytes(ctx context.Context, mediaType string, data []byte) (ocispec.Descriptor, error)

PushBytes stores data and returns its descriptor.

func (*Store) VerifyGraph

func (s *Store) VerifyGraph(ctx context.Context, roots []ocispec.Descriptor) error

VerifyGraph verifies the size and digest of every node reachable from roots.

Manifest-like nodes are read by ORAS while discovering successors. Leaf blobs can be package layers and may be large, so they are streamed through Fetch and content.NewVerifyReader instead of using FetchBytes/content.FetchAll.

type TargetTagExistsError

type TargetTagExistsError struct{ Tag string }

func (TargetTagExistsError) Error

func (e TargetTagExistsError) Error() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL