download all delegated roles when doing downloadTargets

Signed-off-by: David Lawrence <david.lawrence@docker.com> (github: endophage)
This commit is contained in:
David Lawrence 2015-12-15 15:15:37 -08:00
parent 90e22ff5ff
commit 33d39afdf5
2 changed files with 96 additions and 26 deletions

View File

@ -369,34 +369,47 @@ func (c *Client) downloadSnapshot() error {
return nil return nil
} }
// downloadTargets is responsible for downloading any targets file // downloadTargets downloads all targets and delegated targets for the repository.
// including delegates roles. // It uses a pre-order tree traversal as it's necessary to download parents first
// to obtain the keys to validate children.
func (c *Client) downloadTargets(role string) error { func (c *Client) downloadTargets(role string) error {
role = data.RoleName(role) // this will really only do something for base targets role stack := utils.NewStack()
if c.local.Snapshot == nil { stack.Push(role)
return ErrMissingMeta{role: role} for !stack.Empty() {
} role, err := stack.PopString()
snap := c.local.Snapshot.Signed if err != nil {
root := c.local.Root.Signed return err
r := c.keysDB.GetRole(role) }
if r == nil { role = data.RoleName(role) // this will really only do something for base targets role
return fmt.Errorf("Invalid role: %s", role) if c.local.Snapshot == nil {
} return ErrMissingMeta{role: role}
keyIDs := r.KeyIDs }
s, err := c.getTargetsFile(role, keyIDs, snap.Meta, root.ConsistentSnapshot, r.Threshold) snap := c.local.Snapshot.Signed
if err != nil { root := c.local.Root.Signed
logrus.Error("Error getting targets file:", err) r := c.keysDB.GetRole(role)
return err if r == nil {
} return fmt.Errorf("Invalid role: %s", role)
t, err := data.TargetsFromSigned(s) }
if err != nil { keyIDs := r.KeyIDs
return err s, err := c.getTargetsFile(role, keyIDs, snap.Meta, root.ConsistentSnapshot, r.Threshold)
} if err != nil {
err = c.local.SetTargets(role, t) logrus.Error("Error getting targets file:", err)
if err != nil { return err
return err }
} t, err := data.TargetsFromSigned(s)
if err != nil {
return err
}
err = c.local.SetTargets(role, t)
if err != nil {
return err
}
// push delegated roles contained in the targets file onto the stack
for _, r := range t.Signed.Delegations.Roles {
stack.Push(r.Name)
}
}
return nil return nil
} }

57
tuf/utils/stack.go Normal file
View File

@ -0,0 +1,57 @@
package utils
import (
"fmt"
)
type ErrEmptyStack struct {
action string
}
func (err ErrEmptyStack) Error() string {
return fmt.Sprintf("attempted to %s with empty stack", err.action)
}
type ErrBadTypeCast struct{}
func (err ErrBadTypeCast) Error() string {
return "attempted to do a typed pop and item was not of type"
}
type Stack []interface{}
func NewStack() *Stack {
s := make(Stack, 0)
return &s
}
func (s *Stack) Push(item interface{}) {
*s = append(*s, item)
}
func (s *Stack) Pop() (interface{}, error) {
l := len(*s)
if l > 0 {
item := (*s)[l-1]
*s = (*s)[:l-1]
return item, nil
}
return nil, ErrEmptyStack{action: "pop"}
}
func (s *Stack) PopString() (string, error) {
l := len(*s)
if l > 0 {
item := (*s)[l-1]
if item, ok := item.(string); ok {
*s = (*s)[:l-1]
return item, nil
}
return "", ErrBadTypeCast{}
}
return "", ErrEmptyStack{action: "pop"}
}
func (s Stack) Empty() bool {
return len(s) == 0
}