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) LocalOnly() bool
- 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) LocalOnly ¶ added in v0.2.0
func (t *LayoutTransport) LocalOnly() bool
LocalOnly reports that this transport never opens a network connection.
An OCI image layout is a directory. Every operation here is a file operation against it, so an offline client can use this transport and only this one (DP-013).
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 every manifest the index lists is read and asked what it is a referrer for. The answer comes from the subject descriptor inside the manifest, which is where the OCI image specification puts the relationship and where every other implementation looks.
The index also carries a "subject" member on each entry, which this package writes and the layout specification does not define. It is a convenience for anyone reading index.json, and it used to be the only thing consulted -- so a generic copy or rewrite that produced a perfectly valid index silently made attached evidence undiscoverable while leaving the manifests that hold the real relationship untouched.
This 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.