forked from toolshed/abra
chore: vendor
This commit is contained in:
257
vendor/github.com/theupdateframework/notary/client/reader.go
generated
vendored
Normal file
257
vendor/github.com/theupdateframework/notary/client/reader.go
generated
vendored
Normal file
@ -0,0 +1,257 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
canonicaljson "github.com/docker/go/canonical/json"
|
||||
store "github.com/theupdateframework/notary/storage"
|
||||
"github.com/theupdateframework/notary/tuf"
|
||||
"github.com/theupdateframework/notary/tuf/data"
|
||||
"github.com/theupdateframework/notary/tuf/utils"
|
||||
)
|
||||
|
||||
// Target represents a simplified version of the data TUF operates on, so external
|
||||
// applications don't have to depend on TUF data types.
|
||||
type Target struct {
|
||||
Name string // the name of the target
|
||||
Hashes data.Hashes // the hash of the target
|
||||
Length int64 // the size in bytes of the target
|
||||
Custom *canonicaljson.RawMessage // the custom data provided to describe the file at TARGETPATH
|
||||
}
|
||||
|
||||
// TargetWithRole represents a Target that exists in a particular role - this is
|
||||
// produced by ListTargets and GetTargetByName
|
||||
type TargetWithRole struct {
|
||||
Target
|
||||
Role data.RoleName
|
||||
}
|
||||
|
||||
// TargetSignedStruct is a struct that contains a Target, the role it was found in, and the list of signatures for that role
|
||||
type TargetSignedStruct struct {
|
||||
Role data.DelegationRole
|
||||
Target Target
|
||||
Signatures []data.Signature
|
||||
}
|
||||
|
||||
// ErrNoSuchTarget is returned when no valid trust data is found.
|
||||
type ErrNoSuchTarget string
|
||||
|
||||
func (f ErrNoSuchTarget) Error() string {
|
||||
return fmt.Sprintf("No valid trust data for %s", string(f))
|
||||
}
|
||||
|
||||
// RoleWithSignatures is a Role with its associated signatures
|
||||
type RoleWithSignatures struct {
|
||||
Signatures []data.Signature
|
||||
data.Role
|
||||
}
|
||||
|
||||
// NewReadOnly is the base method that returns a new notary repository for reading.
|
||||
// It expects an initialized cache. In case of a nil remote store, a default
|
||||
// offline store is used.
|
||||
func NewReadOnly(repo *tuf.Repo) ReadOnly {
|
||||
return &reader{tufRepo: repo}
|
||||
}
|
||||
|
||||
type reader struct {
|
||||
tufRepo *tuf.Repo
|
||||
}
|
||||
|
||||
// ListTargets lists all targets for the current repository. The list of
|
||||
// roles should be passed in order from highest to lowest priority.
|
||||
//
|
||||
// IMPORTANT: if you pass a set of roles such as [ "targets/a", "targets/x"
|
||||
// "targets/a/b" ], even though "targets/a/b" is part of the "targets/a" subtree
|
||||
// its entries will be strictly shadowed by those in other parts of the "targets/a"
|
||||
// subtree and also the "targets/x" subtree, as we will defer parsing it until
|
||||
// we explicitly reach it in our iteration of the provided list of roles.
|
||||
func (r *reader) ListTargets(roles ...data.RoleName) ([]*TargetWithRole, error) {
|
||||
if len(roles) == 0 {
|
||||
roles = []data.RoleName{data.CanonicalTargetsRole}
|
||||
}
|
||||
targets := make(map[string]*TargetWithRole)
|
||||
for _, role := range roles {
|
||||
// Define an array of roles to skip for this walk (see IMPORTANT comment above)
|
||||
skipRoles := utils.RoleNameSliceRemove(roles, role)
|
||||
|
||||
// Define a visitor function to populate the targets map in priority order
|
||||
listVisitorFunc := func(tgt *data.SignedTargets, validRole data.DelegationRole) interface{} {
|
||||
// We found targets so we should try to add them to our targets map
|
||||
for targetName, targetMeta := range tgt.Signed.Targets {
|
||||
// Follow the priority by not overriding previously set targets
|
||||
// and check that this path is valid with this role
|
||||
if _, ok := targets[targetName]; ok || !validRole.CheckPaths(targetName) {
|
||||
continue
|
||||
}
|
||||
targets[targetName] = &TargetWithRole{
|
||||
Target: Target{
|
||||
Name: targetName,
|
||||
Hashes: targetMeta.Hashes,
|
||||
Length: targetMeta.Length,
|
||||
Custom: targetMeta.Custom,
|
||||
},
|
||||
Role: validRole.Name,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
r.tufRepo.WalkTargets("", role, listVisitorFunc, skipRoles...)
|
||||
}
|
||||
|
||||
var targetList []*TargetWithRole
|
||||
for _, v := range targets {
|
||||
targetList = append(targetList, v)
|
||||
}
|
||||
|
||||
return targetList, nil
|
||||
}
|
||||
|
||||
// GetTargetByName returns a target by the given name. If no roles are passed
|
||||
// it uses the targets role and does a search of the entire delegation
|
||||
// graph, finding the first entry in a breadth first search of the delegations.
|
||||
// If roles are passed, they should be passed in descending priority and
|
||||
// the target entry found in the subtree of the highest priority role
|
||||
// will be returned.
|
||||
// See the IMPORTANT section on ListTargets above. Those roles also apply here.
|
||||
func (r *reader) GetTargetByName(name string, roles ...data.RoleName) (*TargetWithRole, error) {
|
||||
if len(roles) == 0 {
|
||||
roles = append(roles, data.CanonicalTargetsRole)
|
||||
}
|
||||
var resultMeta data.FileMeta
|
||||
var resultRoleName data.RoleName
|
||||
var foundTarget bool
|
||||
for _, role := range roles {
|
||||
// Define an array of roles to skip for this walk (see IMPORTANT comment above)
|
||||
skipRoles := utils.RoleNameSliceRemove(roles, role)
|
||||
|
||||
// Define a visitor function to find the specified target
|
||||
getTargetVisitorFunc := func(tgt *data.SignedTargets, validRole data.DelegationRole) interface{} {
|
||||
if tgt == nil {
|
||||
return nil
|
||||
}
|
||||
// We found the target and validated path compatibility in our walk,
|
||||
// so we should stop our walk and set the resultMeta and resultRoleName variables
|
||||
if resultMeta, foundTarget = tgt.Signed.Targets[name]; foundTarget {
|
||||
resultRoleName = validRole.Name
|
||||
return tuf.StopWalk{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// Check that we didn't error, and that we assigned to our target
|
||||
if err := r.tufRepo.WalkTargets(name, role, getTargetVisitorFunc, skipRoles...); err == nil && foundTarget {
|
||||
return &TargetWithRole{Target: Target{Name: name, Hashes: resultMeta.Hashes, Length: resultMeta.Length, Custom: resultMeta.Custom}, Role: resultRoleName}, nil
|
||||
}
|
||||
}
|
||||
return nil, ErrNoSuchTarget(name)
|
||||
|
||||
}
|
||||
|
||||
// GetAllTargetMetadataByName searches the entire delegation role tree to find the specified target by name for all
|
||||
// roles, and returns a list of TargetSignedStructs for each time it finds the specified target.
|
||||
// If given an empty string for a target name, it will return back all targets signed into the repository in every role
|
||||
func (r *reader) GetAllTargetMetadataByName(name string) ([]TargetSignedStruct, error) {
|
||||
var targetInfoList []TargetSignedStruct
|
||||
|
||||
// Define a visitor function to find the specified target
|
||||
getAllTargetInfoByNameVisitorFunc := func(tgt *data.SignedTargets, validRole data.DelegationRole) interface{} {
|
||||
if tgt == nil {
|
||||
return nil
|
||||
}
|
||||
// We found a target and validated path compatibility in our walk,
|
||||
// so add it to our list if we have a match
|
||||
// if we have an empty name, add all targets, else check if we have it
|
||||
var targetMetaToAdd data.Files
|
||||
if name == "" {
|
||||
targetMetaToAdd = tgt.Signed.Targets
|
||||
} else {
|
||||
if meta, ok := tgt.Signed.Targets[name]; ok {
|
||||
targetMetaToAdd = data.Files{name: meta}
|
||||
}
|
||||
}
|
||||
|
||||
for targetName, resultMeta := range targetMetaToAdd {
|
||||
targetInfo := TargetSignedStruct{
|
||||
Role: validRole,
|
||||
Target: Target{Name: targetName, Hashes: resultMeta.Hashes, Length: resultMeta.Length, Custom: resultMeta.Custom},
|
||||
Signatures: tgt.Signatures,
|
||||
}
|
||||
targetInfoList = append(targetInfoList, targetInfo)
|
||||
}
|
||||
// continue walking to all child roles
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check that we didn't error, and that we found the target at least once
|
||||
if err := r.tufRepo.WalkTargets(name, "", getAllTargetInfoByNameVisitorFunc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(targetInfoList) == 0 {
|
||||
return nil, ErrNoSuchTarget(name)
|
||||
}
|
||||
return targetInfoList, nil
|
||||
}
|
||||
|
||||
// ListRoles returns a list of RoleWithSignatures objects for this repo
|
||||
// This represents the latest metadata for each role in this repo
|
||||
func (r *reader) ListRoles() ([]RoleWithSignatures, error) {
|
||||
// Get all role info from our updated keysDB, can be empty
|
||||
roles := r.tufRepo.GetAllLoadedRoles()
|
||||
|
||||
var roleWithSigs []RoleWithSignatures
|
||||
|
||||
// Populate RoleWithSignatures with Role from keysDB and signatures from TUF metadata
|
||||
for _, role := range roles {
|
||||
roleWithSig := RoleWithSignatures{Role: *role, Signatures: nil}
|
||||
switch role.Name {
|
||||
case data.CanonicalRootRole:
|
||||
roleWithSig.Signatures = r.tufRepo.Root.Signatures
|
||||
case data.CanonicalTargetsRole:
|
||||
roleWithSig.Signatures = r.tufRepo.Targets[data.CanonicalTargetsRole].Signatures
|
||||
case data.CanonicalSnapshotRole:
|
||||
roleWithSig.Signatures = r.tufRepo.Snapshot.Signatures
|
||||
case data.CanonicalTimestampRole:
|
||||
roleWithSig.Signatures = r.tufRepo.Timestamp.Signatures
|
||||
default:
|
||||
if !data.IsDelegation(role.Name) {
|
||||
continue
|
||||
}
|
||||
if _, ok := r.tufRepo.Targets[role.Name]; ok {
|
||||
// We'll only find a signature if we've published any targets with this delegation
|
||||
roleWithSig.Signatures = r.tufRepo.Targets[role.Name].Signatures
|
||||
}
|
||||
}
|
||||
roleWithSigs = append(roleWithSigs, roleWithSig)
|
||||
}
|
||||
return roleWithSigs, nil
|
||||
}
|
||||
|
||||
// GetDelegationRoles returns the keys and roles of the repository's delegations
|
||||
// Also converts key IDs to canonical key IDs to keep consistent with signing prompts
|
||||
func (r *reader) GetDelegationRoles() ([]data.Role, error) {
|
||||
// All top level delegations (ex: targets/level1) are stored exclusively in targets.json
|
||||
_, ok := r.tufRepo.Targets[data.CanonicalTargetsRole]
|
||||
if !ok {
|
||||
return nil, store.ErrMetaNotFound{Resource: data.CanonicalTargetsRole.String()}
|
||||
}
|
||||
|
||||
// make a copy for traversing nested delegations
|
||||
allDelegations := []data.Role{}
|
||||
|
||||
// Define a visitor function to populate the delegations list and translate their key IDs to canonical IDs
|
||||
delegationCanonicalListVisitor := func(tgt *data.SignedTargets, validRole data.DelegationRole) interface{} {
|
||||
// For the return list, update with a copy that includes canonicalKeyIDs
|
||||
// These aren't validated by the validRole
|
||||
canonicalDelegations, err := translateDelegationsToCanonicalIDs(tgt.Signed.Delegations)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
allDelegations = append(allDelegations, canonicalDelegations...)
|
||||
return nil
|
||||
}
|
||||
err := r.tufRepo.WalkTargets("", "", delegationCanonicalListVisitor)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return allDelegations, nil
|
||||
}
|
Reference in New Issue
Block a user