// AddTargets will attempt to add the given targets specifically to // the directed role. If the metadata for the role doesn't exist yet, // AddTargets will create one. func (tr *Repo) AddTargets(role string, targets data.Files) (data.Files, error) { err := tr.VerifyCanSign(role) if err != nil { return nil, err } // check the role's metadata t, ok := tr.Targets[role] if !ok { // the targetfile may not exist yet - if not, then create it var err error t, err = tr.InitTargets(role) if err != nil { return nil, err } } var r data.DelegationRole if role != data.CanonicalTargetsRole { // we only call r.CheckPaths if the role is not "targets" // so r being nil is fine in the case role == "targets" r, err = tr.GetDelegationRole(role) if err != nil { return nil, err } } invalid := make(data.Files) for path, target := range targets { if role == data.CanonicalTargetsRole || r.CheckPaths(path) { t.Signed.Targets[path] = target } else { invalid[path] = target } } t.Dirty = true if len(invalid) > 0 { return invalid, fmt.Errorf("Could not add all targets") } return nil, nil }
// helper function that returns whether the delegation Role is valid against the given path // Will return true if given an empty candidatePath func isValidPath(candidatePath string, delgRole data.DelegationRole) bool { return candidatePath == "" || delgRole.CheckPaths(candidatePath) }
func TestDelegationRolesParent(t *testing.T) { delgA := data.DelegationRole{ BaseRole: data.BaseRole{ Keys: nil, Name: "targets/a", Threshold: 1, }, Paths: []string{"path", "anotherpath"}, } delgB := data.DelegationRole{ BaseRole: data.BaseRole{ Keys: nil, Name: "targets/a/b", Threshold: 1, }, Paths: []string{"path/b", "anotherpath/b", "b/invalidpath"}, } // Assert direct parent relationship assert.True(t, delgA.IsParentOf(delgB)) assert.False(t, delgB.IsParentOf(delgA)) assert.False(t, delgA.IsParentOf(delgA)) delgC := data.DelegationRole{ BaseRole: data.BaseRole{ Keys: nil, Name: "targets/a/b/c", Threshold: 1, }, Paths: []string{"path/b", "anotherpath/b/c", "c/invalidpath"}, } // Assert direct parent relationship assert.True(t, delgB.IsParentOf(delgC)) assert.False(t, delgB.IsParentOf(delgB)) assert.False(t, delgA.IsParentOf(delgC)) assert.False(t, delgC.IsParentOf(delgB)) assert.False(t, delgC.IsParentOf(delgA)) assert.False(t, delgC.IsParentOf(delgC)) // Check that parents correctly restrict paths restrictedDelgB, err := delgA.Restrict(delgB) assert.NoError(t, err) assert.Contains(t, restrictedDelgB.Paths, "path/b") assert.Contains(t, restrictedDelgB.Paths, "anotherpath/b") assert.NotContains(t, restrictedDelgB.Paths, "b/invalidpath") _, err = delgB.Restrict(delgA) assert.Error(t, err) _, err = delgA.Restrict(delgC) assert.Error(t, err) _, err = delgC.Restrict(delgB) assert.Error(t, err) _, err = delgC.Restrict(delgA) assert.Error(t, err) // Make delgA have no paths and check that it changes delgB and delgC accordingly when chained delgA.Paths = []string{} restrictedDelgB, err = delgA.Restrict(delgB) assert.NoError(t, err) assert.Empty(t, restrictedDelgB.Paths) restrictedDelgC, err := restrictedDelgB.Restrict(delgC) assert.NoError(t, err) assert.Empty(t, restrictedDelgC.Paths) }