state: convert acl-roles.policies index to new pattern

This commit is contained in:
Daniel Nephin 2021-03-19 16:07:55 -04:00
parent 00b6f0b41a
commit 43df402e51
6 changed files with 50 additions and 77 deletions

View File

@ -113,57 +113,6 @@ func (s *TokenRolesIndex) PrefixFromArgs(args ...interface{}) ([]byte, error) {
return val, nil return val, nil
} }
type RolePoliciesIndex struct {
}
func (s *RolePoliciesIndex) FromObject(obj interface{}) (bool, [][]byte, error) {
role, ok := obj.(*structs.ACLRole)
if !ok {
return false, nil, fmt.Errorf("object is not an ACLRole")
}
links := role.Policies
numLinks := len(links)
if numLinks == 0 {
return false, nil, nil
}
vals := make([][]byte, 0, numLinks)
for _, link := range links {
vals = append(vals, []byte(link.ID+"\x00"))
}
return true, vals, nil
}
func (s *RolePoliciesIndex) FromArgs(args ...interface{}) ([]byte, error) {
if len(args) != 1 {
return nil, fmt.Errorf("must provide only a single argument")
}
arg, ok := args[0].(string)
if !ok {
return nil, fmt.Errorf("argument must be a string: %#v", args[0])
}
// Add the null character as a terminator
arg += "\x00"
return []byte(arg), nil
}
func (s *RolePoliciesIndex) PrefixFromArgs(args ...interface{}) ([]byte, error) {
val, err := s.FromArgs(args...)
if err != nil {
return nil, err
}
// Strip the null terminator, the rest is a prefix
n := len(val)
if n > 0 {
return val[:n-1], nil
}
return val, nil
}
type TokenExpirationIndex struct { type TokenExpirationIndex struct {
LocalFilter bool LocalFilter bool
} }
@ -544,22 +493,21 @@ func fixupTokenRoleLinks(tx ReadTxn, original *structs.ACLToken) (*structs.ACLTo
func resolveRolePolicyLinks(tx *txn, role *structs.ACLRole, allowMissing bool) error { func resolveRolePolicyLinks(tx *txn, role *structs.ACLRole, allowMissing bool) error {
for linkIndex, link := range role.Policies { for linkIndex, link := range role.Policies {
if link.ID != "" { if link.ID == "" {
policy, err := getPolicyWithTxn(tx, nil, link.ID, aclPolicyGetByID, &role.EnterpriseMeta)
if err != nil {
return err
}
if policy != nil {
// the name doesn't matter here
role.Policies[linkIndex].Name = policy.Name
} else if !allowMissing {
return fmt.Errorf("No such policy with ID: %s", link.ID)
}
} else {
return fmt.Errorf("Encountered a Role with policies linked by Name in the state store") return fmt.Errorf("Encountered a Role with policies linked by Name in the state store")
} }
policy, err := getPolicyWithTxn(tx, nil, link.ID, aclPolicyGetByID, &role.EnterpriseMeta)
if err != nil {
return err
}
if policy != nil {
// the name doesn't matter here
role.Policies[linkIndex].Name = policy.Name
} else if !allowMissing {
return fmt.Errorf("No such policy with ID: %s", link.ID)
}
} }
return nil return nil
} }
@ -1495,8 +1443,14 @@ func (s *Store) ACLRoleList(ws memdb.WatchSet, policy string, entMeta *structs.E
var iter memdb.ResultIterator var iter memdb.ResultIterator
var err error var err error
// TODO: accept non-pointer value
if entMeta == nil {
entMeta = structs.DefaultEnterpriseMeta()
}
if policy != "" { if policy != "" {
iter, err = aclRoleListByPolicy(tx, policy, entMeta) q := Query{Value: policy, EnterpriseMeta: *entMeta}
iter, err = tx.Get(tableACLRoles, indexPolicies, q)
} else { } else {
iter, err = tx.Get(tableACLRoles, indexName+"_prefix", entMeta) iter, err = tx.Get(tableACLRoles, indexName+"_prefix", entMeta)
} }

View File

@ -36,7 +36,8 @@ func aclChangeUnsubscribeEvent(tx ReadTxn, changes Changes) ([]stream.Event, err
} }
secretIDs = appendSecretIDsFromTokenIterator(secretIDs, tokens) secretIDs = appendSecretIDsFromTokenIterator(secretIDs, tokens)
roles, err := aclRoleListByPolicy(tx, policy.ID, &policy.EnterpriseMeta) q := Query{Value: policy.ID, EnterpriseMeta: policy.EnterpriseMeta}
roles, err := tx.Get(tableACLRoles, indexPolicies, q)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -53,6 +53,25 @@ func indexNameFromACLRole(raw interface{}) ([]byte, error) {
return b.Bytes(), nil return b.Bytes(), nil
} }
func multiIndexPolicyFromACLRole(raw interface{}) ([][]byte, error) {
role, ok := raw.(*structs.ACLRole)
if !ok {
return nil, fmt.Errorf("unexpected type %T for structs.ACLRole index", raw)
}
count := len(role.Policies)
if count == 0 {
return nil, errMissingValueForIndex
}
vals := make([][]byte, 0, count)
for _, link := range role.Policies {
vals = append(vals, []byte(strings.ToLower(link.ID)+"\x00"))
}
return vals, nil
}
func aclPolicyGetByID(tx ReadTxn, id string, _ *structs.EnterpriseMeta) (<-chan struct{}, interface{}, error) { func aclPolicyGetByID(tx ReadTxn, id string, _ *structs.EnterpriseMeta) (<-chan struct{}, interface{}, error) {
return tx.FirstWatch(tableACLPolicies, indexID, id) return tx.FirstWatch(tableACLPolicies, indexID, id)
} }
@ -174,10 +193,6 @@ func aclRoleGetByID(tx ReadTxn, id string, _ *structs.EnterpriseMeta) (<-chan st
return tx.FirstWatch(tableACLRoles, indexID, id) return tx.FirstWatch(tableACLRoles, indexID, id)
} }
func aclRoleListByPolicy(tx ReadTxn, policy string, _ *structs.EnterpriseMeta) (memdb.ResultIterator, error) {
return tx.Get(tableACLRoles, indexPolicies, policy)
}
func aclRoleDeleteWithRole(tx *txn, role *structs.ACLRole, idx uint64) error { func aclRoleDeleteWithRole(tx *txn, role *structs.ACLRole, idx uint64) error {
// remove the role // remove the role
if err := tx.Delete(tableACLRoles, role); err != nil { if err := tx.Delete(tableACLRoles, role); err != nil {

View File

@ -66,14 +66,14 @@ func testIndexerTableACLRoles() map[string]indexerTestCase {
}, },
indexPolicies: { indexPolicies: {
read: indexValue{ read: indexValue{
source: "PolicyId1", source: Query{Value: "PolicyId1"},
expected: []byte("PolicyId1\x00"), expected: []byte("policyid1\x00"),
}, },
writeMulti: indexValueMulti{ writeMulti: indexValueMulti{
source: obj, source: obj,
expected: [][]byte{ expected: [][]byte{
[]byte("PolicyId1\x00"), []byte("policyid1\x00"),
[]byte("PolicyId2\x00"), []byte("policyid2\x00"),
}, },
}, },
}, },

View File

@ -162,7 +162,10 @@ func rolesTableSchema() *memdb.TableSchema {
// Need to allow missing for the anonymous token // Need to allow missing for the anonymous token
AllowMissing: true, AllowMissing: true,
Unique: false, Unique: false,
Indexer: &RolePoliciesIndex{}, Indexer: indexerMulti{
readIndex: readIndex(indexFromQuery),
writeIndexMulti: writeIndexMulti(multiIndexPolicyFromACLRole),
},
}, },
}, },
} }

View File

@ -20,7 +20,7 @@ table=acl-roles
index=name unique index=name unique
indexer=github.com/hashicorp/consul/agent/consul/state.indexerSingleWithPrefix readIndex=github.com/hashicorp/consul/agent/consul/state.indexFromQuery writeIndex=github.com/hashicorp/consul/agent/consul/state.indexNameFromACLRole prefixIndex=github.com/hashicorp/consul/agent/consul/state.prefixIndexFromQuery indexer=github.com/hashicorp/consul/agent/consul/state.indexerSingleWithPrefix readIndex=github.com/hashicorp/consul/agent/consul/state.indexFromQuery writeIndex=github.com/hashicorp/consul/agent/consul/state.indexNameFromACLRole prefixIndex=github.com/hashicorp/consul/agent/consul/state.prefixIndexFromQuery
index=policies allow-missing index=policies allow-missing
indexer=github.com/hashicorp/consul/agent/consul/state.RolePoliciesIndex indexer=github.com/hashicorp/consul/agent/consul/state.indexerMulti readIndex=github.com/hashicorp/consul/agent/consul/state.indexFromQuery writeIndexMulti=github.com/hashicorp/consul/agent/consul/state.multiIndexPolicyFromACLRole
table=acl-tokens table=acl-tokens
index=accessor unique allow-missing index=accessor unique allow-missing