Documentation
¶
Overview ¶
Package oci stores and retrieves DevProof subjects as OCI objects.
The local image layout implemented here is the Phase 1 transport: it is a real, spec-shaped OCI layout that other tooling can read, which makes the hardest guarantees — canonical bytes and safe expansion — testable without a registry in the picture.
Index ¶
- Constants
- type Index
- type IndexItem
- type Layout
- func (l *Layout) AddManifest(descriptor artifact.Descriptor, artifactType, tag string) error
- func (l *Layout) AddReferrer(descriptor artifact.Descriptor, artifactType, subjectDigest string) error
- func (l *Layout) Close() error
- func (l *Layout) FindManifest(reference string) (IndexItem, error)
- func (l *Layout) GetBlob(digest canonical.Digest, limit int64) ([]byte, error)
- func (l *Layout) Index() (*Index, error)
- func (l *Layout) OpenBlob(digest canonical.Digest) (io.ReadCloser, int64, error)
- func (l *Layout) Path() string
- func (l *Layout) PutBlob(content []byte) (canonical.Digest, error)
- func (l *Layout) PutBlobStream(content io.Reader, want canonical.Digest, size int64) (retErr error)
- func (l *Layout) SetIndex(items []IndexItem) error
- type LayoutTransport
- func (t *LayoutTransport) Attach(ctx context.Context, ref artifact.Reference, subject artifact.Descriptor, ...) (artifact.Descriptor, artifact.EvidenceStorage, error)
- func (t *LayoutTransport) Close() error
- func (t *LayoutTransport) Fetch(_ context.Context, ref artifact.Reference, target artifact.Descriptor) (io.ReadCloser, error)
- func (t *LayoutTransport) Push(_ context.Context, ref artifact.Reference, target artifact.Descriptor, ...) error
- func (t *LayoutTransport) Record(ref artifact.Reference, target artifact.Descriptor) error
- func (t *LayoutTransport) Referrers(_ context.Context, ref artifact.Reference, subject artifact.Descriptor, ...) ([]artifact.Descriptor, artifact.EvidenceStorage, error)
- func (t *LayoutTransport) Resolve(_ context.Context, ref artifact.Reference) (artifact.Descriptor, error)
- func (t *LayoutTransport) Scheme() string
- func (t *LayoutTransport) Tag(_ context.Context, ref artifact.Reference, target artifact.Descriptor, ...) error
- type Registry
- func (r *Registry) Attach(ctx context.Context, ref artifact.Reference, subject artifact.Descriptor, ...) (artifact.Descriptor, artifact.EvidenceStorage, error)
- func (r *Registry) Close() error
- func (r *Registry) Fetch(ctx context.Context, ref artifact.Reference, target artifact.Descriptor) (io.ReadCloser, error)
- func (r *Registry) Push(ctx context.Context, ref artifact.Reference, target artifact.Descriptor, ...) error
- func (r *Registry) Referrers(ctx context.Context, ref artifact.Reference, subject artifact.Descriptor, ...) ([]artifact.Descriptor, artifact.EvidenceStorage, error)
- func (r *Registry) Resolve(ctx context.Context, ref artifact.Reference) (artifact.Descriptor, error)
- func (r *Registry) Scheme() string
- func (r *Registry) Tag(ctx context.Context, ref artifact.Reference, target artifact.Descriptor, ...) error
- type RegistryOptions
Constants ¶
const ( // MediaTypeImageIndex is the OCI index media type. MediaTypeImageIndex = "application/vnd.oci.image.index.v1+json" // AnnotationRefName is the conventional annotation carrying a tag. // It lives on the index, never on the subject manifest: an annotation on // the subject would change its digest (DP-002). AnnotationRefName = "org.opencontainers.image.ref.name" )
OCI image layout file names and values, from the image-spec.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Index ¶
type Index struct {
SchemaVersion int `json:"schemaVersion"`
MediaType string `json:"mediaType"`
Manifests []IndexItem `json:"manifests"`
}
Index is the layout's index.json.
type IndexItem ¶
type IndexItem struct {
MediaType string `json:"mediaType"`
Digest string `json:"digest"`
Size int64 `json:"size"`
ArtifactType string `json:"artifactType,omitempty"`
Annotations map[string]string `json:"annotations,omitempty"`
// Subject names the manifest this one is a referrer for. A layout has no
// referrers API, so the index is where that relationship is recorded.
Subject string `json:"subject,omitempty"`
}
IndexItem references a manifest in the layout.
Unlike a subject manifest, an index entry may carry annotations: the index is a local directory listing, not content anybody addresses by digest, so a tag recorded here cannot change what the subject is.
func (IndexItem) Descriptor ¶
func (i IndexItem) Descriptor() artifact.Descriptor
Descriptor returns the item as a plain descriptor.
type Layout ¶
type Layout struct {
// contains filtered or unexported fields
}
Layout is an OCI image layout directory.
Every operation goes through an os.Root held on the layout directory, so a blob path derived from a digest cannot escape it even if the digest string were somehow attacker-controlled.
func Create ¶
Create makes a new OCI image layout at dir.
The directory must not already be a layout. Writing into an existing one would mean inheriting blobs and an index that this process never verified.
func (*Layout) AddManifest ¶
func (l *Layout) AddManifest(descriptor artifact.Descriptor, artifactType, tag string) error
AddManifest records a subject in the index, optionally under a tag.
A tag is written only after the manifest it names is already present, which is the local equivalent of the publication barrier a registry push observes (DP-007): a name never points at content that has not landed.
func (*Layout) AddReferrer ¶
func (l *Layout) AddReferrer(descriptor artifact.Descriptor, artifactType, subjectDigest string) error
AddReferrer records an evidence manifest against its subject.
Unlike AddManifest this never carries a tag and never replaces an existing entry with a different digest: a subject may have several pieces of evidence, and attaching one must not remove another (DP-003).
func (*Layout) FindManifest ¶
FindManifest resolves a reference, which may be a digest or a tag.
A tag is resolved to a digest here and the digest is what every later step uses, so a tag that moves mid-operation cannot change what was verified (DP-007).
func (*Layout) GetBlob ¶
GetBlob reads a blob, verifying it against its digest.
limit bounds the read so that a layout directory someone else can write cannot force an unbounded allocation.
func (*Layout) OpenBlob ¶
OpenBlob returns a streaming reader over a blob.
The caller is responsible for verifying the digest as it reads; this exists for the layer, which is too large to hold in memory just to check it once.
func (*Layout) PutBlob ¶
PutBlob stores content under its digest.
The digest is recomputed from the bytes rather than trusted from the caller, because a blob filed under the wrong name is a blob that will later verify against a descriptor it does not match. Writing is atomic: content lands at a temporary name, is synced, and is renamed into place, so a crash never leaves a truncated blob at a digest-shaped path where a reader would take its name as proof of its content.
func (*Layout) PutBlobStream ¶
PutBlobStream stores a blob by streaming it, verifying as it goes.
The layer can be far larger than memory, and reading it into a slice just to hash it once would make peak memory track payload size. Instead the content is hashed while it is written to a temporary file, and the file is published under its digest only once the digest is known to be the expected one.
want is the digest the caller expects. A blob is never filed under a digest it does not have, so a source that served different bytes is caught here rather than becoming a corrupt layout.
type LayoutTransport ¶
type LayoutTransport struct {
// contains filtered or unexported fields
}
LayoutTransport exposes local OCI image layouts through the same contract as a registry.
Having one contract is what keeps the publication rules — blobs before the manifest, read back before tagging, tag last — in one place. A local destination that had its own code path would be the one where those rules quietly diverged, and it is the path most people develop against.
func NewLayoutTransport ¶
func NewLayoutTransport() *LayoutTransport
NewLayoutTransport returns a transport for local layouts.
func (*LayoutTransport) Attach ¶
func (t *LayoutTransport) Attach( ctx context.Context, ref artifact.Reference, subject artifact.Descriptor, blob artifact.Descriptor, content io.Reader, artifactType string, ) (artifact.Descriptor, artifact.EvidenceStorage, error)
Attach stores an evidence blob and the referrer manifest naming it.
func (*LayoutTransport) Close ¶
func (t *LayoutTransport) Close() error
Close releases every layout this transport opened.
func (*LayoutTransport) Fetch ¶
func (t *LayoutTransport) Fetch(_ context.Context, ref artifact.Reference, target artifact.Descriptor) (io.ReadCloser, error)
Fetch returns the content a descriptor names.
func (*LayoutTransport) Push ¶
func (t *LayoutTransport) Push(_ context.Context, ref artifact.Reference, target artifact.Descriptor, content io.Reader) error
Push stores content under its descriptor.
func (*LayoutTransport) Record ¶
func (t *LayoutTransport) Record(ref artifact.Reference, target artifact.Descriptor) error
Record registers a manifest in the index without assigning a tag.
A layout has no way to enumerate manifests other than its index, so an untagged subject still has to be recorded or it would be unreachable. This is layout-specific: a registry keeps a manifest addressable by digest with no index entry at all.
func (*LayoutTransport) Referrers ¶
func (t *LayoutTransport) Referrers( _ context.Context, ref artifact.Reference, subject artifact.Descriptor, artifactType string, ) ([]artifact.Descriptor, artifact.EvidenceStorage, error)
Referrers lists evidence attached to a subject in a layout.
A layout has no referrers API, so the index is scanned for manifests whose subject is the one asked about. That is a real set, unlike the registry fallback tag, so the storage mode reported is the referrers one.
func (*LayoutTransport) Resolve ¶
func (t *LayoutTransport) Resolve(_ context.Context, ref artifact.Reference) (artifact.Descriptor, error)
Resolve freezes a reference to one descriptor.
func (*LayoutTransport) Scheme ¶
func (t *LayoutTransport) Scheme() string
Scheme is the reference scheme this transport handles.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry is an OCI Distribution transport.
func NewRegistry ¶
func NewRegistry(opts RegistryOptions) *Registry
NewRegistry returns a registry transport.
func (*Registry) Attach ¶
func (r *Registry) Attach( ctx context.Context, ref artifact.Reference, subject artifact.Descriptor, blob artifact.Descriptor, content io.Reader, artifactType string, ) (artifact.Descriptor, artifact.EvidenceStorage, error)
Attach stores an evidence blob and the referrer manifest naming it.
func (*Registry) Fetch ¶
func (r *Registry) Fetch(ctx context.Context, ref artifact.Reference, target artifact.Descriptor) (io.ReadCloser, error)
Fetch returns the content a descriptor names.
func (*Registry) Push ¶
func (r *Registry) Push(ctx context.Context, ref artifact.Reference, target artifact.Descriptor, content io.Reader) error
Push stores content under its descriptor. Content that is already present is not an error.
func (*Registry) Referrers ¶
func (r *Registry) Referrers( ctx context.Context, ref artifact.Reference, subject artifact.Descriptor, artifactType string, ) ([]artifact.Descriptor, artifact.EvidenceStorage, error)
Referrers lists evidence attached to a subject.
Where the registry has no referrers API, the fallback tag is consulted instead and the storage mode says so. A caller that cannot accept the fallback's replace-rather-than-accumulate semantics can refuse it by policy, but only if it is told which mode answered (DP-028).
func (*Registry) Resolve ¶
func (r *Registry) Resolve(ctx context.Context, ref artifact.Reference) (artifact.Descriptor, error)
Resolve freezes a reference to one descriptor.
type RegistryOptions ¶
type RegistryOptions struct {
// Credentials supplies per-host credentials. Nil means anonymous.
Credentials artifact.CredentialProvider
// PlainHTTP disables TLS.
PlainHTTP bool
// Timeout bounds a single request attempt.
Timeout time.Duration
}
RegistryOptions configures a registry transport.