ratify

package module
v0.0.0-...-8f7f89a Latest Latest
Warning

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

Go to latest
Published: Sep 12, 2025 License: Apache-2.0 Imports: 20 Imported by: 2

README

Ratify Go Library

[!WARNING] This project is currently under initial development. APIs may and will be changed incompatibly from one commit to another.

Build Status Codecov Go Reference

ratify-go provides core functionality for the ratify library.

Versioning

The ratify-go library follows Semantic Versioning, where breaking changes are reserved for MAJOR releases, and MINOR and PATCH releases must be 100% backwards compatible.

Documentation

Contributing

Thanks for your interest in contributing! There are many ways to contribute to this project. Get started here: CONTRIBUTING.md

Code of Conduct

This project has adopted the CNCF Code of Conduct.

Documentation

Overview

Package ratify provides core functionality for the ratify library.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Evaluator

type Evaluator interface {
	// Pruned determines whether verification for a given subject-artifact pair
	// should be skipped.
	// It returns [PrunedStateVerifierPruned] if the verifier is not required to
	// verify the subject against the artifact.
	// It returns [PrunedStateArtifactPruned] if the artifact is not required to
	// be verified against.
	// It returns [PrunedStateSubjectPruned] if the subject is not required to
	// be verified.
	// It returns [PrunedStateNone] if the verifier is required to verify the
	// subject against the artifact.
	Pruned(ctx context.Context, subjectDigest, artifactDigest, verifierName string) (PrunedState, error)

	// AddResult adds the verification result of the subject against the
	// artifact to the evaluator for further evaluation.
	AddResult(ctx context.Context, subjectDigest, artifactDigest string, artifactResult *VerificationResult) error

	// Commit commits the verification results of the subject. No more results
	// will be added for the subject after this call.
	Commit(ctx context.Context, subjectDigest string) error

	// Evaluate makes the final decision based on aggregated verification
	// results added so far.
	Evaluate(ctx context.Context) (bool, error)
}

Evaluator is an interface that defines methods to aggregate and evaluate verification results generated for an artifact per validation request.

type Executor

type Executor struct {
	// Executor should configure exactly one store to fetch supply chain
	// content. Required.
	Store Store

	// Executor could use multiple verifiers to validate artifacts. Required.
	Verifiers []Verifier

	// Executor should have at most one policy enforcer to evalute reports. If
	// not set, the validation result will be returned without evaluation.
	// Optional.
	PolicyEnforcer PolicyEnforcer

	// Concurrency limits the maximum number of concurrent execution per
	// validation request. If less than or equal to 0, a default (currently 3)
	// is used.
	Concurrency int
}

Executor is defined to validate artifacts.

func NewExecutor

func NewExecutor(store Store, verifiers []Verifier, policyEnforcer PolicyEnforcer) (*Executor, error)

NewExecutor creates a new executor with the given verifiers, store, and policy enforcer.

func (*Executor) ValidateArtifact

func (e *Executor) ValidateArtifact(ctx context.Context, opts ValidateArtifactOptions) (*ValidationResult, error)

ValidateArtifact returns the result of verifying an artifact.

type OCIStore

type OCIStore struct {
	// contains filtered or unexported fields
}

OCIStore is a read-only store implementation based on OCI image layout.

func NewOCIStoreFromFS

func NewOCIStoreFromFS(ctx context.Context, fsys fs.FS) (*OCIStore, error)

NewOCIStoreFromFS creates a new OCIStore from the given filesystem in OCI image layout.

func NewOCIStoreFromTar

func NewOCIStoreFromTar(ctx context.Context, path string) (*OCIStore, error)

NewOCIStoreFromTar creates a new OCIStore from the given tarball in OCI image layout.

func (*OCIStore) FetchBlob

func (s *OCIStore) FetchBlob(ctx context.Context, _ string, desc ocispec.Descriptor) ([]byte, error)

FetchBlobContent returns the blob by the given reference.

func (*OCIStore) FetchManifest

func (s *OCIStore) FetchManifest(ctx context.Context, _ string, desc ocispec.Descriptor) ([]byte, error)

FetchManifest returns the referenced manifest as given by the descriptor.

func (*OCIStore) ListReferrers

func (s *OCIStore) ListReferrers(ctx context.Context, ref string, artifactTypes []string, fn func(referrers []ocispec.Descriptor) error) error

ListReferrers returns the immediate set of supply chain artifacts for the given subject reference.

func (*OCIStore) Resolve

func (s *OCIStore) Resolve(ctx context.Context, ref string) (ocispec.Descriptor, error)

Resolve resolves to a descriptor for the given artifact reference.

type PolicyEnforcer

type PolicyEnforcer interface {
	// Evaluator returns an [Evaluator] for the given subject digest.
	Evaluator(ctx context.Context, subjectDigest string) (Evaluator, error)
}

PolicyEnforcer is an interface that generates an evaluator upon a validation request.

type PrunedState

type PrunedState int

PrunedState is the state how an artifact is pruned from the evaluation graph.

const (
	// PrunedStateNone is the state when the artifact is not pruned from the
	// evaluation graph.
	PrunedStateNone PrunedState = iota
	// PrunedStateVerifierPruned is the state when the verifier is not required
	// to verify the subject against the artifact to make a decision.
	PrunedStateVerifierPruned
	// PrunedStateArtifactPruned is the state when the artifact is not required
	// to be verified against to make a decision.
	PrunedStateArtifactPruned
	// PrunedStateSubjectPruned is the state when the subject is not required to
	// be verified to make a decision.
	PrunedStateSubjectPruned
)

type RegistryCredential

type RegistryCredential = auth.Credential

RegistryCredential represents the credential to access the registry.

type RegistryCredentialGetter

type RegistryCredentialGetter interface {
	// Get returns the credential for the registry identified by the server
	// address.
	Get(ctx context.Context, serverAddress string) (RegistryCredential, error)
}

RegistryCredentialGetter provides the credential for the registry identified by the server address. This interface can be viewed as a read-only version of credentials.Store.

type RegistryStore

type RegistryStore struct {
	// contains filtered or unexported fields
}

RegistryStore is a store that interacts with a remote registry.

func NewRegistryStore

func NewRegistryStore(opts RegistryStoreOptions) *RegistryStore

NewRegistryStore creates a new RegistryStore with options.

func (*RegistryStore) FetchBlob

func (s *RegistryStore) FetchBlob(ctx context.Context, repoRef string, desc ocispec.Descriptor) ([]byte, error)

FetchBlob returns the blob by the given reference. WARNING: This API is intended to use for small objects like signatures, SBoMs.

func (*RegistryStore) FetchManifest

func (s *RegistryStore) FetchManifest(ctx context.Context, repoRef string, desc ocispec.Descriptor) ([]byte, error)

FetchManifest returns the referenced manifest as given by the descriptor.

func (*RegistryStore) ListReferrers

func (s *RegistryStore) ListReferrers(ctx context.Context, ref string, artifactTypes []string, fn func(referrers []ocispec.Descriptor) error) error

ListReferrers returns the immediate set of supply chain artifacts for the given subject reference. Note: This API supports pagination. fn should be set to handle the underlying pagination. If AllowCosignTag was enabled in RegistryStoreOptions, it will also attempt to fetch cosign signatures with the sha256-<hash>.sig tag format.

func (*RegistryStore) Resolve

func (s *RegistryStore) Resolve(ctx context.Context, ref string) (ocispec.Descriptor, error)

Resolve resolves to a descriptor for the given artifact reference.

type RegistryStoreOptions

type RegistryStoreOptions struct {
	// HTTPClient is the HTTP client to use for the registry requests.
	// If nil, [http.DefaultClient] will be used.
	HTTPClient *http.Client

	// PlainHTTP signals the transport to access the remote repository via HTTP
	// instead of HTTPS.
	PlainHTTP bool

	// UserAgent is the user agent string to use for the registry requests.
	// If empty, "ratify-go" will be used.
	UserAgent string

	// CredentialProvider provides the credential for the registry.
	CredentialProvider RegistryCredentialGetter

	// MaxBlobBytes limits the maximum size of the fetched blob content bytes.
	// If less than or equal to zero, a default value (32 MiB) will be used.
	MaxBlobBytes int64

	// MaxManifestBytes limits the maximum size of the fetched manifest bytes.
	// If less than or equal to zero, a default value (4 MiB) will be used.
	MaxManifestBytes int64

	// AllowCosignTag enables fetching cosign signatures with the tag format
	// when listing referrers.
	AllowCosignTag bool
}

RegistryStoreOptions provides options for creating a new RegistryStore.

type Store

type Store interface {
	// Resolve resolves to a descriptor for the given artifact reference.
	Resolve(ctx context.Context, ref string) (ocispec.Descriptor, error)

	// ListReferrers returns the immediate set of supply chain artifacts for the
	// given subject reference.
	// Note: This API supports pagination. fn should be set to handle the
	// underlying pagination.
	ListReferrers(ctx context.Context, ref string, artifactTypes []string, fn func(referrers []ocispec.Descriptor) error) error

	// FetchBlob returns the blob by the given reference.
	// WARNING: This API is intended to use for small objects like signatures,
	// SBoMs.
	FetchBlob(ctx context.Context, repo string, desc ocispec.Descriptor) ([]byte, error)

	// FetchManifest returns the referenced manifest as given by the descriptor.
	FetchManifest(ctx context.Context, repo string, desc ocispec.Descriptor) ([]byte, error)
}

Store is an interface that defines methods to query the graph of supply chain content including its related content

type StoreMux

type StoreMux struct {
	// contains filtered or unexported fields
}

StoreMux is a store multiplexer. It matches the registry name of each incoming request against a list of registered patterns and calls the store for the pattern that most closely matches the registry name.

Patterns

Patterns can match the registry name and the repository name. If patterns are registered only with the registry name, wildcard DNS records (see RFC 1034, Section 4.3.3, RFC 4592, and RFC 6125, Section 6.4.3) are accepted. Some examples:

  • "registry.example" matches any request to the host "registry.example"
  • "registry.example/foo" matches any request to the repository "foo" on the host "registry.example"
  • "*.example" matches any request to any host in the "example" domain
  • "*.example:5000" matches any request to the host "*.example" on port 5000

Patterns with repository names does not support wildcard DNS records. For example, "*.example/foo" is not a valid pattern. Top level domain wildcard is also not supported. That is, "*" is not a valid pattern.

Precedence

If two or more patterns match a request, then the most specific pattern takes precedence. For example, if both "registry.example/foo" and "registry.example" are registered, then the former takes precedence.

Example
// Create stores for demonstration.
// Each store is an OCI image layout with a single artifact with a different
// tag.
ctx := context.Background()
var stores []ratify.Store
for _, tag := range []string{"foo", "bar", "hello", "world"} {
	fsys := fstest.MapFS{
		"blob/sha256/03c6d9dcb63b03c5489db13cedbc549f2de807f43440df549644866a24a3561b": &fstest.MapFile{
			Data: []byte(`{"schemaVersion":2,"mediaType":"application/vnd.oci.image.manifest.v1+json","artifactType":"application/vnd.unknown.artifact.v1","config":{"mediaType":"application/vnd.oci.empty.v1+json","digest":"sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a","size":2,"data":"e30="},"layers":[{"mediaType":"application/vnd.oci.empty.v1+json","digest":"sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a","size":2,"data":"e30="}],"annotations":{"org.opencontainers.image.created":"2025-01-26T07:32:59Z"}}`),
		},
		"blob/sha256/44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a": &fstest.MapFile{
			Data: []byte(`{}`),
		},
		"index.json": &fstest.MapFile{
			Data: []byte(`{"schemaVersion":2,"manifests":[{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:03c6d9dcb63b03c5489db13cedbc549f2de807f43440df549644866a24a3561b","size":535,"annotations":{"org.opencontainers.image.created":"2025-01-26T07:32:59Z","org.opencontainers.image.ref.name":"` + tag + `"},"artifactType":"application/vnd.unknown.artifact.v1"}]}`),
		},
		"oci-layout": &fstest.MapFile{
			Data: []byte(`{"imageLayoutVersion": "1.0.0"}`),
		},
	}
	store, err := ratify.NewOCIStoreFromFS(ctx, fsys)
	if err != nil {
		panic(err)
	}
	stores = append(stores, store)
}

// Create a new store multiplexer
store := ratify.NewStoreMux()

// Register store with exact repository name match.
store.Register("registry.example/test", stores[0])

// Register store for an registry.
store.Register("registry.example", stores[1])

// Register store with wildcard DNS record.
store.Register("*.example", stores[2])

// Register a fallback store for unmatched requests.
store.RegisterFallback(stores[3])

// Reference should be resolvable by the matching store.
_, err := store.Resolve(ctx, "registry.example/test:foo")
if err != nil {
	panic(err)
}
_, err = store.Resolve(ctx, "registry.example/another-test:bar")
if err != nil {
	panic(err)
}
_, err = store.Resolve(ctx, "test.example/test:hello")
if err != nil {
	panic(err)
}
_, err = store.Resolve(ctx, "another.registry.example/test:world")
if err != nil {
	panic(err)
}
Example (MixRegistryStore)

ExampleStoreMux_mixRegistryStore demonstrates how to access different registries with different network configurations using a single store by multiplexing.

// Create a new store multiplexer
mux := ratify.NewStoreMux()

// Create a global registry store with default options.
// Developers should replace the default options with actual configuration.
store := ratify.NewRegistryStore(ratify.RegistryStoreOptions{})
if err := mux.RegisterFallback(store); err != nil {
	panic(err)
}

// Create a registry store for local registry.
// A local registry is accessed over plain HTTP unlike the global registry.
store = ratify.NewRegistryStore(ratify.RegistryStoreOptions{
	PlainHTTP: true,
})
if err := mux.Register("localhost:5000", store); err != nil {
	panic(err)
}

// Create a registry store with client certificate authentication.
store = ratify.NewRegistryStore(ratify.RegistryStoreOptions{
	HTTPClient: &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				Certificates: []tls.Certificate{
					// add client certificate with private key
				},
			},
		},
	},
})
if err := mux.Register("private.registry.example", store); err != nil {
	panic(err)
}

// Create a registry store for an insecure registry.
store = ratify.NewRegistryStore(ratify.RegistryStoreOptions{
	HTTPClient: &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	},
})
if err := mux.Register("insecure.registry.example", store); err != nil {
	panic(err)
}

func NewStoreMux

func NewStoreMux() *StoreMux

NewStoreMux creates a new StoreMux.

func (*StoreMux) FetchBlob

func (s *StoreMux) FetchBlob(ctx context.Context, repo string, desc ocispec.Descriptor) ([]byte, error)

FetchBlob returns the blob by the given reference. WARNING: This API is intended to use for small objects like signatures, SBoMs.

func (*StoreMux) FetchManifest

func (s *StoreMux) FetchManifest(ctx context.Context, repo string, desc ocispec.Descriptor) ([]byte, error)

FetchManifest returns the referenced manifest as given by the descriptor.

func (*StoreMux) ListReferrers

func (s *StoreMux) ListReferrers(ctx context.Context, ref string, artifactTypes []string, fn func(referrers []ocispec.Descriptor) error) error

ListReferrers returns the immediate set of supply chain artifacts for the given subject reference. Note: This API supports pagination. fn should be set to handle the underlying pagination.

func (*StoreMux) Register

func (s *StoreMux) Register(pattern string, store Store) error

Register registers a store for the given pattern.

func (*StoreMux) RegisterFallback

func (s *StoreMux) RegisterFallback(store Store) error

RegisterFallback registers a fallback store, which is used if no other store matches.

func (*StoreMux) Resolve

func (s *StoreMux) Resolve(ctx context.Context, ref string) (ocispec.Descriptor, error)

Resolve resolves to a descriptor for the given artifact reference.

type ThresholdPolicyEnforcer

type ThresholdPolicyEnforcer struct {
	// contains filtered or unexported fields
}

ThresholdPolicyEnforcer is an implementation of the PolicyEnforcer interface.

func NewThresholdPolicyEnforcer

func NewThresholdPolicyEnforcer(policy *ThresholdPolicyRule) (*ThresholdPolicyEnforcer, error)

NewThresholdPolicyEnforcer creates a new ThresholdPolicyEnforcer with the given policy rule. The policy rule must be non-nil.

func (*ThresholdPolicyEnforcer) Evaluator

func (e *ThresholdPolicyEnforcer) Evaluator(ctx context.Context, subjectDigest string) (Evaluator, error)

Evaluator returns a thresholdEvaluator for the given subject digest.

type ThresholdPolicyRule

type ThresholdPolicyRule struct {
	// Verifier is the Verifier to be used for this rule.
	// If set, the rule requires the Verifier to verify the corresponding
	// artifact. Either Verifier or Rules must be set.
	// Optional.
	Verifier string

	// Threshold is the required number of satisfied nested rules defined in
	// this rule. If not set or set to 0, all nested rules must be satisfied.
	// Optional.
	Threshold int

	// Rules hold nested rules that could be applied to referrer artifacts.
	// Optional.
	Rules []*ThresholdPolicyRule
	// contains filtered or unexported fields
}

ThresholdPolicyRule defines the policy rule for ThresholdPolicyEnforcer.

type ValidateArtifactOptions

type ValidateArtifactOptions struct {
	// Subject is the reference of the artifact to be validated. Required.
	Subject string

	// ReferenceTypes is a list of reference types that should be verified
	// against in associated artifacts. Empty list means all artifacts should be
	// verified. Optional.
	ReferenceTypes []string
}

ValidateArtifactOptions describes the artifact validation options.

type ValidationReport

type ValidationReport struct {
	// Subject is the subject reference of the artifact being verified.
	// Required.
	Subject string

	// Results are generated by verifiers while verifying the subject against
	// the referrer artifact. Required.
	// e.g. If the Subject is a container image, Artifact is a descriptor to
	// Notation signature. Results are generated by Notation verifiers verifying
	// the image against the signature.
	Results []*VerificationResult

	// Artifact is the descriptor of the referrer artifact being verified
	// against with. Required.
	Artifact ocispec.Descriptor

	// ArtifactReports is reports of verifying referrer artifacts. Optional.
	// e.g. If the Subject is a container image, Artifact is a descriptor to
	// SBOM which is signed by a Notation signature. ArtifactReports are
	// generated by the executor verifying the SBOM against the signature.
	ArtifactReports []*ValidationReport
}

ValidationReport describes the results of verifying an artifact and its nested artifacts by available verifiers.

type ValidationResult

type ValidationResult struct {
	// Succeeded represents the outcome determined by the policy enforcer based
	// on the aggregated verifier reports. And if an error occurs during the
	// validation process prior to policy evaluation, it will be set to `false`.
	// If the policy enforcer is not set in the executor, this field will be set
	// to `false`. In such cases, this field should be ignored. Required.
	Succeeded bool

	// ArtifactReports is aggregated reports of verifying associated artifacts.
	// This field can be nil if an error occured during validation or no reports
	// were generated. Optional.
	ArtifactReports []*ValidationReport
}

ValidationResult aggregates verifier reports and the final verification result evaluated by the policy enforcer.

type VerificationResult

type VerificationResult struct {
	// Err is the error that occurred when the verification failed.
	// If the verification is successful, this field should be nil. Optional.
	Err error

	// Description describes the verification result if needed. Optional.
	Description string

	// Verifier refers to the verifier that generated the result. Required.
	Verifier Verifier

	// Detail is additional information that can be used to provide more context
	// about the verification result. Optional.
	Detail any
}

VerificationResult defines the verification result that a verifier plugin must return.

type Verifier

type Verifier interface {
	// Name returns the name of the verifier.
	Name() string

	// Type returns the type name of the verifier.
	Type() string

	// Verifiable returns if the verifier can verify against the given artifact.
	Verifiable(artifact ocispec.Descriptor) bool

	// Verify verifies the subject in the store against the artifact and
	// returns the verification result.
	Verify(ctx context.Context, opts *VerifyOptions) (*VerificationResult, error)
}

Verifier is an interface that defines methods to verify an artifact associated with a subject.

type VerifyOptions

type VerifyOptions struct {
	// Store is the store to access the artifacts. Required.
	Store Store

	// Repository represents the fully qualified repository name of the subject,
	// including the registry name.
	// Required.
	Repository string

	// SubjectDescriptor is the descriptor of the subject being verified.
	// Required.
	SubjectDescriptor ocispec.Descriptor

	// ArtifactDescriptor is the descriptor of the artifact being verified
	// against. Required.
	ArtifactDescriptor ocispec.Descriptor
}

VerifyOptions represents the options to verify a subject against an artifact.

Directories

Path Synopsis
internal
set

Jump to

Keyboard shortcuts

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