attestation

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Sep 8, 2025 License: Apache-2.0 Imports: 3 Imported by: 49

README

AMPEL attestation framework

This repository contains the AMPEL attestation framework. Our framework builds on top of the in-toto attestation formats. In a sens it is the in-toto attestation framework as it is 100% compatible, only defining extra methods that make it possible to use attested data in AMPEL's policy enforcement context.

At this time, the framework only contains interface definitions for the attestation components, the query system and systems to store and retrieve them. Code here is intended to have a minimal dependency footprint. All implementations are stored in other repositories and projects (concrete pointers TBD).

Attestation Components

The framework splits the attestation stack in the following components:

Envelope

The envelope abstracts any wrapper (real or conceptual) around an attestation. Usually envelopes provide strong identity or cryptogrpahic safeguards on the attestation data.

Sometimes, envelopes wrap other wrappers. Ideally, parsers will stop at the outermost layer and squash any internal ones. In general, the envelope format is not relevant on the policy enforcement context. After parsing an attestation's envelope, the only preserved data is the signature/identity verification information.

Envelope examples include DSSE, sigstore bundles, etc. Envelopes can also be conceptual, for example an attestation paired with an esternal signature file can be coerced into an Envelope providing verification data.

Statement

The statement is a 1:1 map of an in-toto statement with addutional methods. Just as in vanila in-toto, a Statement's data is split between its subjects and a predicate. It has a Type and a Predicate type.

At this time, ampel only supports in-toto statements and while there are no plans to support other formats, anything that can be coerced into a predicate+subjects shape could potentially be used as a statement.

Subject

The subject data structure is also a 1:1 wrapper on the in-toto resource descriptor. It captures the hashes, name and/or URI of whetever the claims in the attestation are about.

Predicate

The predicate captures the claim data. Just as in-toto, the predicate is expected to be of any format, it has a PredicateType which is used to filter and categorize attested data.

In AMPEL, the predicate is the main work unit. Signature verification, attestation sorting and filtering, all are done before the runtime has access to the data. This is why, the Predicate in AMPEL is overloaded with extra data such as its origin, its siganture verification data, etc. When evaluating a policy, the runtime does not have access to the subject or envelope. Only the predicate but it is conveniently loaded with the applicable subject and signature data in case the policy needs them.

Attestation Repositories

Attestation repositories store and retrieve attestation data. Anything that implements the Repository interface can be used as a repository, from simple implementations like a directory reader to more complex ones like OCI registries, git repos or specialized storage systems.

If repositories don't wish to implement or expose all capabilities they can implement only the Fetcher the Storer interfaces.

Specialized Vaariants

As we identify useful capabilities, more fetcher and storer types will be defined. This allows implementations,such as the Carabiner collector, to leverage optimized capabilities from the repository implementaion backends.

At present we have defined the FetcherBySubject, FetcherByPredicateType and FetcherByPredicateTypeAndSubject specialized fetchers.

Attestation Queries

Once a repository is queried and returns a set of attestations, AMPEL can use attestation queries to sort or filter attestation sets returned from repositories.

Queries operate at the Envelope level and filter attestations based on their properties. AMPEL makes extensive use of queries and while the heavy lift of selecting approriate attestation is expected to be performed by the repository, AMPEL uses queries to refine the statements what will eventually be exposed to the runtime engines for evaluation. This means AMPEL can overcome the limitation of simple repository drivers (for example the JSONL driver) to provide missing filtering capabilities.


The contents of this repository are Copyright by Carabiner Systems, Inc and released under the Apache-2.0 license. Feel free to contribute patches, comments or bug reports.

Documentation

Index

Constants

View Source
const (
	QueryModeOr  = "OR"
	QueryModeAnd = "AND"
)

Variables

View Source
var (
	ErrFetcherMethodNotImplemented = errors.New("fetching method not implemented")
	ErrStorerMethodNotImplemented  = errors.New("storing method not implemented")
)
View Source
var ErrNotCorrectFormat = errors.New("data does not conform to parser's format")
View Source
var WithMode = func(mode string) optFunc {
	return func(qo *QueryOptions) {
		if mode == QueryModeAnd || mode == QueryModeOr {
			qo.Mode = mode
		}
	}
}

Functions

func SubjectsMatch

func SubjectsMatch(s1, s2 Subject) bool

SubjectsMatch compares two subjects and returns a boolean indicate if they are the same. Ideally this function should compare the full resource descriptor fields but, for now, it only checks that the hashes from s2 which are present in s1 match.

Types

type Certificate

type Certificate interface{} //nolint:iface // To be implemented

Signature abstracts a signature. At least for now.

type EnvVerOptsConvertable added in v0.2.0

type EnvVerOptsConvertable interface {
	ToEnvelopeVerificationOptions() EnvelopeVerificationOptions
}

EnvVerOptsConvertable is an interface that any verification material that can be converted to an EnvelopeVerificationOptions can implement to get data from the verifier.

type Envelope

type Envelope interface {
	GetStatement() Statement
	GetPredicate() Predicate
	GetSignatures() []Signature
	GetCertificate() Certificate
	GetVerification() Verification
	Verify(...any) error
}

Envelope is a construct that wraps a statement, its signatures and all the verification material. The goal of this abstraction is to get a single interface to verify statements, even when all the bits amy be in separate files.

type EnvelopeParser

type EnvelopeParser interface {
	ParseStream(r io.Reader) ([]Envelope, error)
	FileExtensions() []string
}

EnvelopeParser abstracts an object that reads data and on the other end returns an attestation envelope. It is the EnvelopeParser's job to verify any signatures or other cryptographic material protecting the contained attestation.

type EnvelopeVerificationOptions added in v0.2.0

type EnvelopeVerificationOptions struct {
	// AllowUnsigned causes the verification to fail if an envelope is not signed.
	AllowUnsigned bool
}

EnvelopeVerificationOptions are values used to verify signed envelopes that may be useful to all envelop implementations.

type FetchOptions

type FetchOptions struct {
	Limit int
	Query *Query
}

StoreOptions control how attestations are retrieved from a Fetcher. All repositories implementing the Fetcher interface are expected to honor FetchOptions.

type Fetcher

type Fetcher interface {
	Fetch(context.Context, FetchOptions) ([]Envelope, error)
}

AttestationFetcher is the the trait that repositories that can fetch attestations must implement

type FetcherByPredicateType added in v0.1.2

type FetcherByPredicateType interface {
	FetchByPredicateType(context.Context, FetchOptions, []PredicateType) ([]Envelope, error)
}

FetcherByPredicateType is a fetcher that can filter natively by predictae types.

type FetcherByPredicateTypeAndSubject added in v0.1.2

type FetcherByPredicateTypeAndSubject interface {
	FetchByPredicateTypeAndSubject(context.Context, FetchOptions, []PredicateType, []Subject) ([]Envelope, error)
}

FetcherByPredicateTypeAndSubject is a fetcher that can filter natively by predictae types and subject.

type FetcherBySubject added in v0.1.2

type FetcherBySubject interface {
	FetchBySubject(context.Context, FetchOptions, []Subject) ([]Envelope, error)
}

FetcherBySubject is a fetcher that can filter natively by subject hashes.

type Filter

type Filter interface {
	Matches(Envelope) bool
}

A filter abstracts logic that looks into an attestation's properties to determine if it matches some criteria.

type FilterSet

type FilterSet []Filter

Filterset is a group of filters that forma query

func (FilterSet) FilterList

func (fs FilterSet) FilterList(in []Envelope, funcs ...optFunc) []Envelope

FilterList runs a list of attestations through the configured filters and returns a new list with those that match.

func (FilterSet) MatchesAll

func (fs FilterSet) MatchesAll(att Envelope) bool

Matches returns a bool indicating if all filters match an envelope

func (FilterSet) MatchesOne

func (fs FilterSet) MatchesOne(att Envelope) bool

Matches returns a bool indicating if the attestaion matches at least one of the filters

type Predicate

type Predicate interface {
	GetType() PredicateType
	SetType(PredicateType) error
	GetParsed() any
	GetData() []byte
	GetVerification() Verification
	GetOrigin() Subject
	SetOrigin(Subject)
	SetVerification(Verification)
}

Predicate defines the methods that predicate handlers should implement to be compatible with the framework.

type PredicateParser

type PredicateParser interface {
	Parse([]byte) (Predicate, error)
	SupportsType(...PredicateType) bool
}

The predicate parser reads a predicate's data and returns an object that implements the Predicate interface.

type PredicateType

type PredicateType string

PredicateType overloads basic string to express predicate types.

type Query

type Query struct {
	Filters FilterSet
}

Query abstracts an attestation query. It controls the evaluation of a group of filters to be applied on a set of attestations.

func NewQuery

func NewQuery() *Query

func (*Query) Run

func (query *Query) Run(atts []Envelope, funcs ...optFunc) []Envelope

Run executes the query, running the attestations through the filters and returning those that match.

func (*Query) WithFilter

func (query *Query) WithFilter(filters ...Filter) *Query

WithFilter adds a filter to the Query

type QueryOptions

type QueryOptions struct {
	Mode string
}

QueryOptions

type Repository

type Repository interface{} //nolint:iface // To be implemented

Repository is an abstraction of a system that can store attestations, serve them or both. Repositories can express their capabilities by implementing the Storer and/or Fetcher interfaces and their specialized variants.

type Signature

type Signature interface{} //nolint:iface // To be implemented

Signature abstracts a signature. At least for now.

type Statement

type Statement interface {
	GetSubjects() []Subject
	GetPredicate() Predicate
	GetPredicateType() PredicateType
	GetType() string
	GetVerification() Verification
}

Statement mimica the in-toto statement in an interface to access its contents. and extends it to retrieve any signature verification data.

type StatementParser

type StatementParser interface {
	Parse([]byte) (Statement, error)
}

StatementParser is an object that parses data and returns a statement.

type StoreOptions

type StoreOptions struct{}

StoreOptions control how attestations are stored in the storer. All repositories implementing the Storer interface are expected to honor StoreOptions.

type Storer

type Storer interface {
	Store(context.Context, StoreOptions, []Envelope) error
}

Storer is a repository that can store attestations

type Subject

type Subject interface {
	GetName() string
	GetUri() string
	GetDigest() map[string]string
}

Subject abstracts a piece of software covered by an attestation. The purpose of the subject interface is to be able to define more methods on top of the standard in-toto ResourceDescriptor.

type Verification

type Verification interface {
	// GetVerified returns a bool indicating if the verification was successful.
	GetVerified() bool

	// MatchesIdentity gets a value that an implementation can turn into an
	// identity and returns a bool indicating if the signature verification
	// matches it.
	MatchesIdentity(any) bool
}

Verification is a minimal abstraction of an identity/signature verification results object. This is mostly a placeholder to mark where verification data fits in the attestation framework.

type VerificationOptions

type VerificationOptions interface{} //nolint:iface // To be implemented

Verification options abstracts the different options that can be tweaked to verify the various signature types

Jump to

Keyboard shortcuts

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