...

Source file src/github.com/theupdateframework/go-tuf/pkg/targets/delegation.go

Documentation: github.com/theupdateframework/go-tuf/pkg/targets

     1  package targets
     2  
     3  import (
     4  	"errors"
     5  
     6  	"github.com/theupdateframework/go-tuf/data"
     7  	"github.com/theupdateframework/go-tuf/internal/sets"
     8  	"github.com/theupdateframework/go-tuf/verify"
     9  )
    10  
    11  type Delegation struct {
    12  	Delegator string
    13  	Delegatee data.DelegatedRole
    14  	DB        *verify.DB
    15  }
    16  
    17  type delegationsIterator struct {
    18  	stack        []Delegation
    19  	target       string
    20  	visitedRoles map[string]struct{}
    21  	parents      map[string]string
    22  }
    23  
    24  var ErrTopLevelTargetsRoleMissing = errors.New("tuf: top level targets role missing from top level keys DB")
    25  
    26  // NewDelegationsIterator initialises an iterator with a first step
    27  // on top level targets.
    28  func NewDelegationsIterator(target string, topLevelKeysDB *verify.DB) (*delegationsIterator, error) {
    29  	targetsRole := topLevelKeysDB.GetRole("targets")
    30  	if targetsRole == nil {
    31  		return nil, ErrTopLevelTargetsRoleMissing
    32  	}
    33  
    34  	i := &delegationsIterator{
    35  		target: target,
    36  		stack: []Delegation{
    37  			{
    38  				Delegatee: data.DelegatedRole{
    39  					Name:      "targets",
    40  					KeyIDs:    sets.StringSetToSlice(targetsRole.KeyIDs),
    41  					Threshold: targetsRole.Threshold,
    42  				},
    43  				DB: topLevelKeysDB,
    44  			},
    45  		},
    46  		visitedRoles: make(map[string]struct{}),
    47  		parents:      make(map[string]string),
    48  	}
    49  	return i, nil
    50  }
    51  
    52  func (d *delegationsIterator) Next() (value Delegation, ok bool) {
    53  	if len(d.stack) == 0 {
    54  		return Delegation{}, false
    55  	}
    56  	delegation := d.stack[len(d.stack)-1]
    57  	d.stack = d.stack[:len(d.stack)-1]
    58  
    59  	// 5.6.7.1: If this role has been visited before, then skip this role (so
    60  	// that cycles in the delegation graph are avoided).
    61  	roleName := delegation.Delegatee.Name
    62  	if _, ok := d.visitedRoles[roleName]; ok {
    63  		return d.Next()
    64  	}
    65  	d.visitedRoles[roleName] = struct{}{}
    66  
    67  	// 5.6.7.2 trim delegations to visit, only the current role and its delegations
    68  	// will be considered
    69  	// https://github.com/theupdateframework/specification/issues/168
    70  	if delegation.Delegatee.Terminating {
    71  		// Empty the stack.
    72  		d.stack = d.stack[0:0]
    73  	}
    74  	return delegation, true
    75  }
    76  
    77  func (d *delegationsIterator) Add(roles []data.DelegatedRole, delegator string, db *verify.DB) error {
    78  	for i := len(roles) - 1; i >= 0; i-- {
    79  		// Push the roles onto the stack in reverse so we get an preorder traversal
    80  		// of the delegations graph.
    81  		r := roles[i]
    82  		matchesPath, err := r.MatchesPath(d.target)
    83  		if err != nil {
    84  			return err
    85  		}
    86  		if matchesPath {
    87  			delegation := Delegation{
    88  				Delegator: delegator,
    89  				Delegatee: r,
    90  				DB:        db,
    91  			}
    92  			d.stack = append(d.stack, delegation)
    93  			d.parents[r.Name] = delegator
    94  		}
    95  	}
    96  
    97  	return nil
    98  }
    99  
   100  func (d *delegationsIterator) Parent(role string) string {
   101  	return d.parents[role]
   102  }
   103  

View as plain text