mirror of
https://github.com/vee1e/gittuf.git
synced 2026-09-03 11:17:08 +00:00
104 lines
3 KiB
Go
104 lines
3 KiB
Go
// Copyright The gittuf Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package policy
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/gittuf/gittuf/internal/gitinterface"
|
|
"github.com/gittuf/gittuf/internal/tuf"
|
|
)
|
|
|
|
type DelegationWithDepth struct {
|
|
Delegation tuf.Rule
|
|
Depth int
|
|
}
|
|
|
|
// ListRules returns a list of all the rules as an array of the delegations in a
|
|
// pre-order traversal of the delegation tree, with the depth of each
|
|
// delegation.
|
|
func ListRules(ctx context.Context, repo *gitinterface.Repository, targetRef string) ([]*DelegationWithDepth, error) {
|
|
state, err := LoadCurrentState(ctx, repo, targetRef)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if !state.HasTargetsRole(TargetsRoleName) {
|
|
return nil, nil
|
|
}
|
|
|
|
topLevelTargetsMetadata, err := state.GetTargetsMetadata(TargetsRoleName, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
delegationsToSearch := []*DelegationWithDepth{}
|
|
allDelegations := []*DelegationWithDepth{}
|
|
|
|
for _, topLevelDelegation := range topLevelTargetsMetadata.GetRules() {
|
|
if topLevelDelegation.ID() == tuf.AllowRuleName {
|
|
continue
|
|
}
|
|
delegationsToSearch = append(delegationsToSearch, &DelegationWithDepth{Delegation: topLevelDelegation, Depth: 0})
|
|
}
|
|
|
|
seenRoles := map[string]bool{TargetsRoleName: true}
|
|
|
|
for len(delegationsToSearch) > 0 {
|
|
currentDelegation := delegationsToSearch[0]
|
|
delegationsToSearch = delegationsToSearch[1:]
|
|
|
|
// allDelegations will be the returned list of all the delegations in pre-order traversal, no delegations will be popped off
|
|
allDelegations = append(allDelegations, currentDelegation)
|
|
|
|
if _, seen := seenRoles[currentDelegation.Delegation.ID()]; seen {
|
|
continue
|
|
}
|
|
|
|
if state.HasTargetsRole(currentDelegation.Delegation.ID()) {
|
|
currentMetadata, err := state.GetTargetsMetadata(currentDelegation.Delegation.ID(), true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
seenRoles[currentDelegation.Delegation.ID()] = true
|
|
|
|
// We construct localDelegations first so that we preserve the order
|
|
// of delegations in currentMetadata in delegationsToSearch
|
|
localDelegations := []*DelegationWithDepth{}
|
|
for _, delegation := range currentMetadata.GetRules() {
|
|
if delegation.ID() == tuf.AllowRuleName {
|
|
continue
|
|
}
|
|
localDelegations = append(localDelegations, &DelegationWithDepth{Delegation: delegation, Depth: currentDelegation.Depth + 1})
|
|
}
|
|
|
|
if len(localDelegations) > 0 {
|
|
delegationsToSearch = append(localDelegations, delegationsToSearch...)
|
|
}
|
|
}
|
|
}
|
|
|
|
return allDelegations, nil
|
|
}
|
|
|
|
// ListPrincipals returns the principals present in the specified rule file.
|
|
// `targetRef` can be used to control which policy reference is used.
|
|
func ListPrincipals(ctx context.Context, repo *gitinterface.Repository, targetRef, policyName string) (map[string]tuf.Principal, error) {
|
|
state, err := LoadCurrentState(ctx, repo, targetRef)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if !state.HasTargetsRole(policyName) {
|
|
return nil, ErrPolicyNotFound
|
|
}
|
|
|
|
metadata, err := state.GetTargetsMetadata(policyName, false)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return metadata.GetPrincipals(), nil
|
|
}
|