forked from toolshed/abra
chore: vendor
This commit is contained in:
339
vendor/github.com/theupdateframework/notary/tuf/data/roles.go
generated
vendored
Normal file
339
vendor/github.com/theupdateframework/notary/tuf/data/roles.go
generated
vendored
Normal file
@ -0,0 +1,339 @@
|
||||
package data
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Canonical base role names
|
||||
var (
|
||||
CanonicalRootRole RoleName = "root"
|
||||
CanonicalTargetsRole RoleName = "targets"
|
||||
CanonicalSnapshotRole RoleName = "snapshot"
|
||||
CanonicalTimestampRole RoleName = "timestamp"
|
||||
)
|
||||
|
||||
// BaseRoles is an easy to iterate list of the top level
|
||||
// roles.
|
||||
var BaseRoles = []RoleName{
|
||||
CanonicalRootRole,
|
||||
CanonicalTargetsRole,
|
||||
CanonicalSnapshotRole,
|
||||
CanonicalTimestampRole,
|
||||
}
|
||||
|
||||
// Regex for validating delegation names
|
||||
var delegationRegexp = regexp.MustCompile("^[-a-z0-9_/]+$")
|
||||
|
||||
// ErrNoSuchRole indicates the roles doesn't exist
|
||||
type ErrNoSuchRole struct {
|
||||
Role RoleName
|
||||
}
|
||||
|
||||
func (e ErrNoSuchRole) Error() string {
|
||||
return fmt.Sprintf("role does not exist: %s", e.Role)
|
||||
}
|
||||
|
||||
// ErrInvalidRole represents an error regarding a role. Typically
|
||||
// something like a role for which sone of the public keys were
|
||||
// not found in the TUF repo.
|
||||
type ErrInvalidRole struct {
|
||||
Role RoleName
|
||||
Reason string
|
||||
}
|
||||
|
||||
func (e ErrInvalidRole) Error() string {
|
||||
if e.Reason != "" {
|
||||
return fmt.Sprintf("tuf: invalid role %s. %s", e.Role, e.Reason)
|
||||
}
|
||||
return fmt.Sprintf("tuf: invalid role %s.", e.Role)
|
||||
}
|
||||
|
||||
// ValidRole only determines the name is semantically
|
||||
// correct. For target delegated roles, it does NOT check
|
||||
// the appropriate parent roles exist.
|
||||
func ValidRole(name RoleName) bool {
|
||||
if IsDelegation(name) {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, v := range BaseRoles {
|
||||
if name == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsDelegation checks if the role is a delegation or a root role
|
||||
func IsDelegation(role RoleName) bool {
|
||||
strRole := role.String()
|
||||
targetsBase := CanonicalTargetsRole + "/"
|
||||
|
||||
whitelistedChars := delegationRegexp.MatchString(strRole)
|
||||
|
||||
// Limit size of full role string to 255 chars for db column size limit
|
||||
correctLength := len(role) < 256
|
||||
|
||||
// Removes ., .., extra slashes, and trailing slash
|
||||
isClean := path.Clean(strRole) == strRole
|
||||
return strings.HasPrefix(strRole, targetsBase.String()) &&
|
||||
whitelistedChars &&
|
||||
correctLength &&
|
||||
isClean
|
||||
}
|
||||
|
||||
// IsBaseRole checks if the role is a base role
|
||||
func IsBaseRole(role RoleName) bool {
|
||||
for _, baseRole := range BaseRoles {
|
||||
if role == baseRole {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsWildDelegation determines if a role represents a valid wildcard delegation
|
||||
// path, i.e. targets/*, targets/foo/*.
|
||||
// The wildcard may only appear as the final part of the delegation and must
|
||||
// be a whole segment, i.e. targets/foo* is not a valid wildcard delegation.
|
||||
func IsWildDelegation(role RoleName) bool {
|
||||
if path.Clean(role.String()) != role.String() {
|
||||
return false
|
||||
}
|
||||
base := role.Parent()
|
||||
if !(IsDelegation(base) || base == CanonicalTargetsRole) {
|
||||
return false
|
||||
}
|
||||
return role[len(role)-2:] == "/*"
|
||||
}
|
||||
|
||||
// BaseRole is an internal representation of a root/targets/snapshot/timestamp role, with its public keys included
|
||||
type BaseRole struct {
|
||||
Keys map[string]PublicKey
|
||||
Name RoleName
|
||||
Threshold int
|
||||
}
|
||||
|
||||
// NewBaseRole creates a new BaseRole object with the provided parameters
|
||||
func NewBaseRole(name RoleName, threshold int, keys ...PublicKey) BaseRole {
|
||||
r := BaseRole{
|
||||
Name: name,
|
||||
Threshold: threshold,
|
||||
Keys: make(map[string]PublicKey),
|
||||
}
|
||||
for _, k := range keys {
|
||||
r.Keys[k.ID()] = k
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// ListKeys retrieves the public keys valid for this role
|
||||
func (b BaseRole) ListKeys() KeyList {
|
||||
return listKeys(b.Keys)
|
||||
}
|
||||
|
||||
// ListKeyIDs retrieves the list of key IDs valid for this role
|
||||
func (b BaseRole) ListKeyIDs() []string {
|
||||
return listKeyIDs(b.Keys)
|
||||
}
|
||||
|
||||
// Equals returns whether this BaseRole equals another BaseRole
|
||||
func (b BaseRole) Equals(o BaseRole) bool {
|
||||
if b.Threshold != o.Threshold || b.Name != o.Name || len(b.Keys) != len(o.Keys) {
|
||||
return false
|
||||
}
|
||||
|
||||
for keyID, key := range b.Keys {
|
||||
oKey, ok := o.Keys[keyID]
|
||||
if !ok || key.ID() != oKey.ID() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// DelegationRole is an internal representation of a delegation role, with its public keys included
|
||||
type DelegationRole struct {
|
||||
BaseRole
|
||||
Paths []string
|
||||
}
|
||||
|
||||
func listKeys(keyMap map[string]PublicKey) KeyList {
|
||||
keys := KeyList{}
|
||||
for _, key := range keyMap {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
func listKeyIDs(keyMap map[string]PublicKey) []string {
|
||||
keyIDs := []string{}
|
||||
for id := range keyMap {
|
||||
keyIDs = append(keyIDs, id)
|
||||
}
|
||||
return keyIDs
|
||||
}
|
||||
|
||||
// Restrict restricts the paths and path hash prefixes for the passed in delegation role,
|
||||
// returning a copy of the role with validated paths as if it was a direct child
|
||||
func (d DelegationRole) Restrict(child DelegationRole) (DelegationRole, error) {
|
||||
if !d.IsParentOf(child) {
|
||||
return DelegationRole{}, fmt.Errorf("%s is not a parent of %s", d.Name, child.Name)
|
||||
}
|
||||
return DelegationRole{
|
||||
BaseRole: BaseRole{
|
||||
Keys: child.Keys,
|
||||
Name: child.Name,
|
||||
Threshold: child.Threshold,
|
||||
},
|
||||
Paths: RestrictDelegationPathPrefixes(d.Paths, child.Paths),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// IsParentOf returns whether the passed in delegation role is the direct child of this role,
|
||||
// determined by delegation name.
|
||||
// Ex: targets/a is a direct parent of targets/a/b, but targets/a is not a direct parent of targets/a/b/c
|
||||
func (d DelegationRole) IsParentOf(child DelegationRole) bool {
|
||||
return path.Dir(child.Name.String()) == d.Name.String()
|
||||
}
|
||||
|
||||
// CheckPaths checks if a given path is valid for the role
|
||||
func (d DelegationRole) CheckPaths(path string) bool {
|
||||
return checkPaths(path, d.Paths)
|
||||
}
|
||||
|
||||
func checkPaths(path string, permitted []string) bool {
|
||||
for _, p := range permitted {
|
||||
if strings.HasPrefix(path, p) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// RestrictDelegationPathPrefixes returns the list of valid delegationPaths that are prefixed by parentPaths
|
||||
func RestrictDelegationPathPrefixes(parentPaths, delegationPaths []string) []string {
|
||||
validPaths := []string{}
|
||||
if len(delegationPaths) == 0 {
|
||||
return validPaths
|
||||
}
|
||||
|
||||
// Validate each individual delegation path
|
||||
for _, delgPath := range delegationPaths {
|
||||
isPrefixed := false
|
||||
for _, parentPath := range parentPaths {
|
||||
if strings.HasPrefix(delgPath, parentPath) {
|
||||
isPrefixed = true
|
||||
break
|
||||
}
|
||||
}
|
||||
// If the delegation path did not match prefix against any parent path, it is not valid
|
||||
if isPrefixed {
|
||||
validPaths = append(validPaths, delgPath)
|
||||
}
|
||||
}
|
||||
return validPaths
|
||||
}
|
||||
|
||||
// RootRole is a cut down role as it appears in the root.json
|
||||
// Eventually should only be used for immediately before and after serialization/deserialization
|
||||
type RootRole struct {
|
||||
KeyIDs []string `json:"keyids"`
|
||||
Threshold int `json:"threshold"`
|
||||
}
|
||||
|
||||
// Role is a more verbose role as they appear in targets delegations
|
||||
// Eventually should only be used for immediately before and after serialization/deserialization
|
||||
type Role struct {
|
||||
RootRole
|
||||
Name RoleName `json:"name"`
|
||||
Paths []string `json:"paths,omitempty"`
|
||||
}
|
||||
|
||||
// NewRole creates a new Role object from the given parameters
|
||||
func NewRole(name RoleName, threshold int, keyIDs, paths []string) (*Role, error) {
|
||||
if IsDelegation(name) {
|
||||
if len(paths) == 0 {
|
||||
logrus.Debugf("role %s with no Paths will never be able to publish content until one or more are added", name)
|
||||
}
|
||||
}
|
||||
if threshold < 1 {
|
||||
return nil, ErrInvalidRole{Role: name}
|
||||
}
|
||||
if !ValidRole(name) {
|
||||
return nil, ErrInvalidRole{Role: name}
|
||||
}
|
||||
return &Role{
|
||||
RootRole: RootRole{
|
||||
KeyIDs: keyIDs,
|
||||
Threshold: threshold,
|
||||
},
|
||||
Name: name,
|
||||
Paths: paths,
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
// CheckPaths checks if a given path is valid for the role
|
||||
func (r Role) CheckPaths(path string) bool {
|
||||
return checkPaths(path, r.Paths)
|
||||
}
|
||||
|
||||
// AddKeys merges the ids into the current list of role key ids
|
||||
func (r *Role) AddKeys(ids []string) {
|
||||
r.KeyIDs = mergeStrSlices(r.KeyIDs, ids)
|
||||
}
|
||||
|
||||
// AddPaths merges the paths into the current list of role paths
|
||||
func (r *Role) AddPaths(paths []string) error {
|
||||
if len(paths) == 0 {
|
||||
return nil
|
||||
}
|
||||
r.Paths = mergeStrSlices(r.Paths, paths)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveKeys removes the ids from the current list of key ids
|
||||
func (r *Role) RemoveKeys(ids []string) {
|
||||
r.KeyIDs = subtractStrSlices(r.KeyIDs, ids)
|
||||
}
|
||||
|
||||
// RemovePaths removes the paths from the current list of role paths
|
||||
func (r *Role) RemovePaths(paths []string) {
|
||||
r.Paths = subtractStrSlices(r.Paths, paths)
|
||||
}
|
||||
|
||||
func mergeStrSlices(orig, new []string) []string {
|
||||
have := make(map[string]bool)
|
||||
for _, e := range orig {
|
||||
have[e] = true
|
||||
}
|
||||
merged := make([]string, len(orig), len(orig)+len(new))
|
||||
copy(merged, orig)
|
||||
for _, e := range new {
|
||||
if !have[e] {
|
||||
merged = append(merged, e)
|
||||
}
|
||||
}
|
||||
return merged
|
||||
}
|
||||
|
||||
func subtractStrSlices(orig, remove []string) []string {
|
||||
kill := make(map[string]bool)
|
||||
for _, e := range remove {
|
||||
kill[e] = true
|
||||
}
|
||||
var keep []string
|
||||
for _, e := range orig {
|
||||
if !kill[e] {
|
||||
keep = append(keep, e)
|
||||
}
|
||||
}
|
||||
return keep
|
||||
}
|
Reference in New Issue
Block a user