mirror of
https://github.com/vee1e/gittuf.git
synced 2026-09-01 18:27:06 +00:00
Restructure storage so gittuf verification can run over backends other
than the git binary (e.g. go-git):
- pkg/githash: concrete Git object hash, stdlib-only.
gitinterface.Hash aliases it.
- pkg/gitstore: the single Storer interface (24 methods) that all
storage consumers program against, plus the shared
ErrReferenceNotFound sentinel. *gitinterface.Repository satisfies it
structurally (compile-time asserted). Also defines ConfigKey, the
canonical type for the Git config settings gittuf reads.
- pkg/rsl (from internal/rsl): entry model, codec, and readers over
gitstore.Storer; zero gitinterface/sigstore dependencies. rsl.Hash
aliases githash.Hash; nil is the unset-Hash sentinel and IsZero
matches nil and empty as well as both format zeros (no
object-format-unaware ZeroHash). Entry commits (empty tree on the
RSL ref) are owned by the package; no storer adapter.
- internal/signerverifier/gitobject: verifies commit/tag signatures
over (payload, signature) bytes, Rekor URL as an option. The storage
half is Repository.GetObjectSignature. Removes sigstore, cosign, and
gitsign from gitinterface's dependency tree.
- internal/propagation: propagation workflow, moved off pkg/rsl's
public API (its tuf directive types are internal).
- internal/{attestations,cache,policy}: storage via gitstore.Storer;
tree writing via WriteTree(blobs, subtrees).
Breaking changes to pkg/gitinterface: Repository.VerifySignature and
the verification sentinels are removed (use gitobject.Verify);
ErrReferenceNotFound now aliases gitstore's. Repository.GetGitConfig
(which returned the whole config map) is replaced by
LookupConfig(gitstore.ConfigKey), returning a single setting's value.
Policy resolves the Rekor override from git config once per
verification and extracts signed payloads once per object instead of
per key attempt.
Assisted-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Paulo Gomes <paulo@entire.io>
116 lines
5.1 KiB
Go
116 lines
5.1 KiB
Go
// Copyright The gittuf Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
// Package gitstore defines the Git storage interface gittuf's packages
|
|
// consume. It depends only on the standard library and pkg/githash, so
|
|
// dependency-light packages (rsl, and eventually policy) can name their
|
|
// storage without importing gitinterface's signing/attestation stack.
|
|
// *gitinterface.Repository satisfies Storer structurally. Other backends
|
|
// (e.g. go-git) can implement it directly.
|
|
package gitstore
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/gittuf/gittuf/pkg/githash"
|
|
)
|
|
|
|
// ErrReferenceNotFound must be returned (via errors.Is) by a Storer's
|
|
// GetReference when the requested reference does not exist.
|
|
// gitinterface.ErrReferenceNotFound is an alias of this sentinel.
|
|
var ErrReferenceNotFound = errors.New("requested Git reference not found")
|
|
|
|
// Storer is the union of Git storage operations gittuf's consumers need.
|
|
type Storer interface {
|
|
// GetReference returns the tip of the specified reference, or an error
|
|
// matching ErrReferenceNotFound if the reference does not exist.
|
|
GetReference(refName string) (githash.Hash, error)
|
|
|
|
// SetReference sets the specified reference to the provided Git ID.
|
|
SetReference(refName string, gitID githash.Hash) error
|
|
|
|
// DeleteReference deletes the specified reference.
|
|
DeleteReference(refName string) error
|
|
|
|
// ReadBlob returns the contents of the specified blob.
|
|
ReadBlob(blobID githash.Hash) ([]byte, error)
|
|
|
|
// WriteBlob writes the contents as a blob and returns its ID.
|
|
WriteBlob(contents []byte) (githash.Hash, error)
|
|
|
|
// EmptyTree returns the ID of the empty tree.
|
|
EmptyTree() (githash.Hash, error)
|
|
|
|
// WriteTree writes a tree from the given entries and returns its ID.
|
|
// Intermediate trees implied by "/" in an entry's path are created
|
|
// automatically. Order is irrelevant to the result. It returns
|
|
// ErrDuplicateTreePath if two entries share a path.
|
|
WriteTree(entries []TreeEntry) (githash.Hash, error)
|
|
|
|
// GetAllFilesInTree returns the recursively flattened path → blobID
|
|
// mapping of the specified tree.
|
|
GetAllFilesInTree(treeID githash.Hash) (map[string]githash.Hash, error)
|
|
|
|
// GetEntriesInTree returns the immediate entries of the specified tree
|
|
// (non-recursive), each carrying its name, ID, and kind.
|
|
GetEntriesInTree(treeID githash.Hash) ([]TreeEntry, error)
|
|
|
|
// GetPathIDInTree returns the ID of the object at the specified
|
|
// slash-separated path within the specified tree.
|
|
GetPathIDInTree(treeID githash.Hash, treePath string) (githash.Hash, error)
|
|
|
|
// GetCommitTreeID returns the ID of the specified commit's tree.
|
|
GetCommitTreeID(commitID githash.Hash) (githash.Hash, error)
|
|
|
|
// GetCommitMessage returns the specified commit's message.
|
|
GetCommitMessage(commitID githash.Hash) (string, error)
|
|
|
|
// GetCommitParentIDs returns the IDs of the specified commit's parents.
|
|
GetCommitParentIDs(commitID githash.Hash) ([]githash.Hash, error)
|
|
|
|
// GetCommitsBetweenRange returns the commits reachable from commitNewID
|
|
// but not from commitOldID. A zero commitOldID (nil, empty, or the
|
|
// all-zeroes hash of either object format) means no lower bound, and
|
|
// all commits reachable from commitNewID are returned.
|
|
GetCommitsBetweenRange(commitNewID, commitOldID githash.Hash) ([]githash.Hash, error)
|
|
|
|
// GetFilePathsChangedByCommit returns the paths changed by the specified
|
|
// commit relative to its parents.
|
|
GetFilePathsChangedByCommit(commitID githash.Hash) ([]string, error)
|
|
|
|
// KnowsCommit reports whether ancestorID is an ancestor of commitID.
|
|
KnowsCommit(commitID, ancestorID githash.Hash) (bool, error)
|
|
|
|
// GetMergeTree returns the tree resulting from merging the two commits.
|
|
// This is the hardest method for backends not built on the git binary.
|
|
GetMergeTree(commitAID, commitBID githash.Hash) (githash.Hash, error)
|
|
|
|
// GetTagTarget returns the ID of the object the specified tag points to.
|
|
GetTagTarget(tagID githash.Hash) (githash.Hash, error)
|
|
|
|
// GetObjectSignature returns the signed payload and detached signature
|
|
// of the specified commit or tag. The signature is empty when the object
|
|
// is unsigned.
|
|
GetObjectSignature(objectID githash.Hash) ([]byte, []byte, error)
|
|
|
|
// Commit commits the specified tree to targetRef, signing it per the
|
|
// store's configuration when sign is true, and returns the commit ID.
|
|
Commit(treeID githash.Hash, targetRef, message string, sign bool) (githash.Hash, error)
|
|
|
|
// CommitUsingSpecificKey is Commit signing with the provided PEM encoded
|
|
// key. Intended for gittuf's developer mode and tests.
|
|
CommitUsingSpecificKey(treeID githash.Hash, targetRef, message string, signingKeyPEMBytes []byte) (githash.Hash, error)
|
|
|
|
// ZeroHash returns the all-zeroes hash matching the store's object
|
|
// format.
|
|
ZeroHash() githash.Hash
|
|
|
|
// LookupConfig returns the value of a single Git config setting. ok is
|
|
// false when the key is not set (distinct from set-but-empty, which
|
|
// returns "" with ok true).
|
|
LookupConfig(key ConfigKey) (value string, ok bool, err error)
|
|
|
|
// ResetDueToError force-resets the specified reference to commitID and
|
|
// returns cause, wrapped if the reset itself fails.
|
|
ResetDueToError(cause error, refName string, commitID githash.Hash) error
|
|
}
|