| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- package targets
- import (
- "errors"
- "github.com/DataDog/go-tuf/data"
- "github.com/DataDog/go-tuf/internal/sets"
- "github.com/DataDog/go-tuf/verify"
- )
- type Delegation struct {
- Delegator string
- Delegatee data.DelegatedRole
- DB *verify.DB
- }
- type delegationsIterator struct {
- stack []Delegation
- target string
- visitedRoles map[string]struct{}
- }
- var ErrTopLevelTargetsRoleMissing = errors.New("tuf: top level targets role missing from top level keys DB")
- // NewDelegationsIterator initialises an iterator with a first step
- // on top level targets.
- func NewDelegationsIterator(target string, topLevelKeysDB *verify.DB) (*delegationsIterator, error) {
- targetsRole := topLevelKeysDB.GetRole("targets")
- if targetsRole == nil {
- return nil, ErrTopLevelTargetsRoleMissing
- }
- i := &delegationsIterator{
- target: target,
- stack: []Delegation{
- {
- Delegatee: data.DelegatedRole{
- Name: "targets",
- KeyIDs: sets.StringSetToSlice(targetsRole.KeyIDs),
- Threshold: targetsRole.Threshold,
- },
- DB: topLevelKeysDB,
- },
- },
- visitedRoles: make(map[string]struct{}),
- }
- return i, nil
- }
- func (d *delegationsIterator) Next() (value Delegation, ok bool) {
- if len(d.stack) == 0 {
- return Delegation{}, false
- }
- delegation := d.stack[len(d.stack)-1]
- d.stack = d.stack[:len(d.stack)-1]
- // 5.6.7.1: If this role has been visited before, then skip this role (so
- // that cycles in the delegation graph are avoided).
- roleName := delegation.Delegatee.Name
- if _, ok := d.visitedRoles[roleName]; ok {
- return d.Next()
- }
- d.visitedRoles[roleName] = struct{}{}
- // 5.6.7.2 trim delegations to visit, only the current role and its delegations
- // will be considered
- // https://github.com/DataDog/specification/issues/168
- if delegation.Delegatee.Terminating {
- // Empty the stack.
- d.stack = d.stack[0:0]
- }
- return delegation, true
- }
- func (d *delegationsIterator) Add(roles []data.DelegatedRole, delegator string, db *verify.DB) error {
- for i := len(roles) - 1; i >= 0; i-- {
- // Push the roles onto the stack in reverse so we get an preorder traversal
- // of the delegations graph.
- r := roles[i]
- matchesPath, err := r.MatchesPath(d.target)
- if err != nil {
- return err
- }
- if matchesPath {
- delegation := Delegation{
- Delegator: delegator,
- Delegatee: r,
- DB: db,
- }
- d.stack = append(d.stack, delegation)
- }
- }
- return nil
- }
|