Documentation
¶
Overview ¶
Package attestation provides a Verifier object that orchestrates loading, signature verification, and per-predicate-type semantic verification of in-toto attestations. The shape is one method per predicate family (VerifyVSA today, VerifyBuild / VerifySource to follow), each built on top of the same generic Load and VerifySignatures primitives.
Envelope and Statement are re-exported from github.com/carabiner-dev/attestation as type aliases so callers only need to import this package.
Index ¶
- Variables
- type Envelope
- type Selection
- type SignatureOptions
- type Statement
- type VSACheck
- type VSAOptions
- type VSAResult
- type Verifier
- func (*Verifier) Fetch(ctx context.Context, path string) ([]Envelope, error)
- func (v *Verifier) Load(path string) (Envelope, error)
- func (*Verifier) VerifyIdentity(env Envelope, expected []*sapi.Identity) error
- func (*Verifier) VerifySignatures(env Envelope, opts SignatureOptions) error
- func (*Verifier) VerifyVSA(_ context.Context, env Envelope, opts *VSAOptions) (*VSAResult, error)
- type VerifierBinding
Constants ¶
This section is empty.
Variables ¶
var ErrAmbiguousAttestation = errors.New("ambiguous attestation")
ErrAmbiguousAttestation is returned by Select when several envelopes in a file could be the one to verify and nothing tells them apart.
var ErrIdentityMismatch = errors.New("envelope signer does not match any expected identity")
ErrIdentityMismatch is returned by VerifyIdentity when none of the expected identities match the envelope's verified signers. Like ErrSignatureRequired, it's a verification outcome — callers should translate it to their "verification failed" exit path rather than treating it as an execution error.
var ErrNoApplicableAttestation = errors.New("no applicable attestation")
ErrNoApplicableAttestation is returned by Select when none of the envelopes in a file is one the caller can verify.
var ErrSignatureRequired = errors.New("envelope is unsigned and signatures are required")
ErrSignatureRequired is returned by VerifySignatures when the envelope is unsigned and SignatureOptions.Required is true. It is a verification outcome rather than an execution error — callers should translate it to their domain's "verification failed" exit path (e.g. exit code 1) rather than treating it as a setup problem.
var ErrSignatureUnverifiable = errors.New("envelope is signed but cannot be verified")
ErrSignatureUnverifiable is returned by VerifySignatures when the envelope carries signatures but the verifier had nothing to check them against: no --key for a DSSE envelope, or no configured verifier for the bundle's kind. The signature was neither confirmed nor refuted. Callers may treat it as a configuration problem rather than a verification failure.
var ErrSignatureUnverified = errors.New("envelope signature did not verify")
ErrSignatureUnverified is returned by VerifySignatures when the envelope carries signatures that were checked against the available key or trust material and did not verify. When the envelope records a reason, the returned error wraps this sentinel and carries it. Like ErrSignatureRequired it is a verification outcome, not an execution error.
var ErrVerifierUnbound = errors.New("verifier has no authorized signer")
ErrVerifierUnbound is returned by VerifyVSA when an accepted verifier has no authorized signer — neither its own nor a wildcard — and VSAOptions.AllowUnbound is false. A VSA's verifier.id is a claim written by whoever produced the document; without a signer bound to it, matching the id proves nothing about who issued the VSA.
Functions ¶
This section is empty.
Types ¶
type Envelope ¶
type Envelope = cdattestation.Envelope
Envelope is an in-toto attestation envelope (bare statement, DSSE, or Sigstore bundle). Re-exported from the carabiner attestation package as a type alias so callers of this library don't need a separate import for the envelope abstraction.
func Select ¶
Select picks the envelope a verification is about. A single envelope is returned as is, whatever it holds: the verification itself will say whether it applies. Among several, those of the selection's predicate types about its subjects remain; a preference breaks a tie between types, and what is left must be exactly one.
type Selection ¶
type Selection struct {
// Kind names what is being looked for, for messages ("build
// provenance", "VSA").
Kind string
// PredicateTypes are the predicate types the caller verifies. Empty
// accepts any.
PredicateTypes []string
// Subjects, when given, must all be subjects of the attestation.
Subjects []*subject.Expected
// NoGitDigestAliases matches subject digests by exact algorithm
// name; see subject.WithGitDigestAliases.
NoGitDigestAliases bool
// Prefer breaks a tie among candidates of different predicate
// types: the first type listed that any candidate has wins.
Prefer []string
}
Selection says which of the attestations in a file a verification is about. Files often hold several: a commit's git note accumulates the source provenance, tag provenance and VSAs sourcetool pushes, and a release's attestations file may carry provenance next to other attestations.
type SignatureOptions ¶
type SignatureOptions struct {
// Keys is the set of public-key providers used to verify DSSE
// signatures on the envelope. Sigstore bundles verify against an
// embedded trust root regardless and do not require entries here.
Keys []key.PublicKeyProvider
// RekorVerification enables verifying keyless DSSE envelopes — ones
// carrying a Sigstore certificate on their signatures — against the
// Rekor transparency log at RekorURL (the signer's default instance
// when empty). An unreachable log records the envelope as
// unverifiable rather than failing the call.
RekorVerification bool
// RekorURL is the transparency log to query; empty means the
// signer's default.
RekorURL string
// Required, when true, makes VerifySignatures return
// ErrSignatureRequired if the envelope carries zero signatures,
// ErrSignatureUnverifiable if it carries signatures the verifier
// had no material to check, and ErrSignatureUnverified if the
// signatures were checked and did not verify. Use this to enforce
// a "must be signed and verified" policy.
Required bool
}
SignatureOptions parameterizes VerifySignatures. Keys are passed to the envelope's Verify implementation; Required toggles the "unsigned → error" policy independent of any keys.
type Statement ¶
type Statement = cdattestation.Statement
Statement is an in-toto statement (subject + predicate). Re-exported from the carabiner attestation package.
type VSACheck ¶
type VSACheck struct {
// Name is a human-readable description of what was checked
// (e.g. `Verifier == "https://verify.example.com"`).
Name string
// Pass reports whether the check succeeded.
Pass bool
// Message is populated on failure with the observed value
// (e.g. `verifier.id = "..."`). Empty when Pass is true.
Message string
}
VSACheck is the result of one hardcoded VSA check.
type VSAOptions ¶
type VSAOptions struct {
Verifiers []VerifierBinding
Signers []*sapi.Identity
AllowUnbound bool
// Registry binds verifier ids to their signers, for accepted
// verifiers given without one; see verifiers.Registry.
Registry *verifiers.Registry
Subjects []*subject.Expected
NoGitDigestAliases bool
Levels []string
Resource string
Policy string
Dependencies []string
}
VSAOptions configures the hardcoded checks VerifyVSA runs against an attestation's normalized VSA representation.
Field semantics:
- Verifiers lists the accepted verifiers, OR-matched on ID against VSA.Verifier.ID. At least one is required; a VSA with no asserted verifier identity carries very weak trust value.
- Signers are wildcard identities authorized to sign for every accepted verifier. A verifier's own Signers add to them.
- The signer check binds the matched verifier to who actually signed the envelope: the envelope's verified signature must match one of the identities authorized for that verifier. It runs whenever the matched verifier has any authorized signer.
- Registry supplies the signer of an accepted verifier given without one, when it knows the id, along with the ref policy that signer must satisfy.
- AllowUnbound permits verifiers with no authorized signer at all, in which case only the ID is matched. Off by default, VerifyVSA returns ErrVerifierUnbound instead.
- Subjects are the artifacts the caller holds and expects the VSA to be about. Every one must match a VSA subject (sharing at least one digest algorithm and agreeing on every shared one) or the result fails; each outcome is reported in VSAResult.Subjects. Empty binds the VSA to nothing. By default a sha1 or sha256 digest meets a git object digest of the same hash; NoGitDigestAliases requires the exact algorithm names (see subject.WithGitDigestAliases).
- Levels is OR-matched against VSA.VerifiedLevels — at least one listed level must be satisfied. For canonical SLSA level strings (e.g. SLSA_BUILD_LEVEL_3) the match is "at-or-above": a VSA verifiedLevel of SLSA_BUILD_LEVEL_4 satisfies a want of SLSA_BUILD_LEVEL_3 within the same track. Non-canonical strings only match exactly. Skipped when empty.
- Resource and Policy are exact-match against ResourceURI and Policy.URI respectively. Skipped when empty.
- Dependencies is AND-matched: every key must appear in VSA.DependencyLevels (count values are not consulted). Skipped when empty.
type VSAResult ¶
type VSAResult struct {
// VSA is the normalized VSA predicate parsed from the envelope.
// Available to callers that want to display additional fields
// (e.g. dependency-level counts) alongside the check results.
VSA *vsa.VSA
// Checks is the per-check outcome. Always includes the always-on
// checks (result, verifier); optional checks appear when the
// corresponding VSAOptions field is non-empty.
Checks []VSACheck
// Signers lists the principals of the envelope's verified signers,
// when the envelope records them, for display alongside the
// verifier it vouched for. Empty for unsigned or unverified
// envelopes.
Signers []string
// Subjects holds the outcome of binding the VSA to the artifacts
// the caller holds, one entry per VSAOptions.Subjects entry in
// order. Empty when none were expected.
Subjects []subject.Match
}
VSAResult is what VerifyVSA returns. VSA is the normalized version-neutral predicate; Checks is the per-check outcome in display order — exactly the entries needed to render a result table for the user.
type Verifier ¶
type Verifier struct{}
Verifier orchestrates attestation verification. Methods on the Verifier split into two groups:
- Generic primitives — Load, VerifySignatures, VerifyIdentity — reusable across every supported attestation type.
- Per-predicate-family checks — VerifyVSA (and, in time, VerifyBuild / VerifySource) — run the semantic checks for that family against an already-loaded, signature-verified envelope.
The zero value is not usable; construct with New.
func New ¶
func New() *Verifier
New returns a Verifier ready to load and verify attestations. It takes no required arguments; per-call inputs (keys, expected identities, VSA fields, …) flow in via the method-specific Options arguments instead of constructor options.
func (*Verifier) Fetch ¶
Fetch loads the attestations at path, in order: every attestation file under a directory, one attestation per line of a JSON lines file (.jsonl, as a commit's git note or a release's attestations file are written), or the single bundle, DSSE envelope or bare statement any other file holds. The collector's drivers do the reading: the JSON lines one is not reached by its format detection, so it is chosen here by extension.
func (*Verifier) Load ¶
Load parses a single attestation envelope from path. Format auto-detection covers bare in-toto statements, DSSE envelopes, and Sigstore bundles; the returned Envelope already has its predicate parsed by the SLSA / VSA parser registry the package wires up via init().
Returns an error if the file produces zero envelopes or more than one; see Fetch and Select for files holding several.
func (*Verifier) VerifyIdentity ¶
VerifyIdentity confirms that the envelope was signed by at least one identity in expected (OR semantics: any match is sufficient). The check is meaningful only for envelopes whose Verification implementation supports identity matching — primarily Sigstore bundles, where signing certificates carry subject identities.
Returns ErrIdentityMismatch if no expected identity matches. If expected is empty, returns nil (no-op).
Call VerifySignatures first: identity matching reads from the envelope's verified-signature material, which the envelope only populates once cryptographic verification has succeeded.
func (*Verifier) VerifySignatures ¶
func (*Verifier) VerifySignatures(env Envelope, opts SignatureOptions) error
VerifySignatures runs the envelope's cryptographic signature verification and, when opts.Required is set, also enforces that the envelope is signed and that the signature verified. The checks are kept in one method because callers nearly always want both: running verification on whatever signatures are present, and demanding a verified signature when policy requires it.
A missing signal is not an error on its own: an unsigned envelope, or a signed one with no key material to check it against, passes when opts.Required is false. Errors from the envelope's Verify implementation (signature/key mismatches, trust-root failures for Sigstore bundles) always propagate.
With opts.Required set, the verdict is read from the Verification the envelope recorded rather than from the presence of signatures, since envelope implementations record a failed verification as a result instead of returning an error from Verify. It returns ErrSignatureRequired when the envelope carries no signatures, ErrSignatureUnverifiable when it carries signatures the verifier had no key or trust material to check, and ErrSignatureUnverified — with the recorded reason, when there is one — when they were checked and did not verify.
func (*Verifier) VerifyVSA ¶
VerifyVSA extracts the VSA predicate from env (which must already have been signature-verified by the caller — see VerifySignatures), converts it to the normalized representation via pkg/slsa/vsa, and runs the hardcoded checks selected by opts.
Returns vsa.ErrNotVSA wrapped with the offending predicate type when env carries a non-VSA predicate, and ErrVerifierUnbound when an accepted verifier has no authorized signer and opts.AllowUnbound is false. Always-on checks (verificationResult == PASSED and the verifier match) always appear in the result; the signer check appears when the matched verifier has authorized signers, and the optional checks only when the corresponding VSAOptions field is set.
ctx is accepted for future cancellation/deadline plumbing; the current check set is purely in-memory and ignores it.
type VerifierBinding ¶
type VerifierBinding struct {
// ID is matched exactly against VSA.Verifier.ID.
ID string
// Signers are identities allowed to sign VSAs from this verifier,
// on top of any wildcard signers in VSAOptions.Signers. A verifier
// with neither is unbound: see VSAOptions.AllowUnbound.
Signers []*sapi.Identity
}
VerifierBinding names an accepted verifier and the signer identities authorized to issue VSAs on its behalf.