From 6cac30aa22f5a3c815345ae4de17abffca88f36a Mon Sep 17 00:00:00 2001 From: Dhia Ayachi Date: Fri, 10 Sep 2021 16:04:33 -0400 Subject: [PATCH] convert `Roles` index to use `indexerMulti` (#11013) * convert `Roles` index to use `indexerMulti` * add role test in oss * fix oss to use the right index func * preallocate slice --- agent/consul/state/acl.go | 51 ------------------------------ agent/consul/state/acl_oss.go | 2 +- agent/consul/state/acl_oss_test.go | 20 ++++++++++++ agent/consul/state/acl_schema.go | 30 +++++++++++++++++- 4 files changed, 50 insertions(+), 53 deletions(-) diff --git a/agent/consul/state/acl.go b/agent/consul/state/acl.go index 7e96d2594b..8854a877d2 100644 --- a/agent/consul/state/acl.go +++ b/agent/consul/state/acl.go @@ -11,57 +11,6 @@ import ( pbacl "github.com/hashicorp/consul/proto/pbacl" ) -type TokenRolesIndex struct { -} - -func (s *TokenRolesIndex) FromObject(obj interface{}) (bool, [][]byte, error) { - token, ok := obj.(*structs.ACLToken) - if !ok { - return false, nil, fmt.Errorf("object is not an ACLToken") - } - - links := token.Roles - - 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 *TokenRolesIndex) 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 *TokenRolesIndex) 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 { LocalFilter bool } diff --git a/agent/consul/state/acl_oss.go b/agent/consul/state/acl_oss.go index d612e584b7..815212a0a9 100644 --- a/agent/consul/state/acl_oss.go +++ b/agent/consul/state/acl_oss.go @@ -90,7 +90,7 @@ func aclTokenListByPolicy(tx ReadTxn, policy string, _ *structs.EnterpriseMeta) } func aclTokenListByRole(tx ReadTxn, role string, _ *structs.EnterpriseMeta) (memdb.ResultIterator, error) { - return tx.Get(tableACLTokens, "roles", role) + return tx.Get(tableACLTokens, indexRoles, Query{Value: role}) } func aclTokenListByAuthMethod(tx ReadTxn, authMethod string, _, _ *structs.EnterpriseMeta) (memdb.ResultIterator, error) { diff --git a/agent/consul/state/acl_oss_test.go b/agent/consul/state/acl_oss_test.go index 1bc03325a7..29eed374ad 100644 --- a/agent/consul/state/acl_oss_test.go +++ b/agent/consul/state/acl_oss_test.go @@ -37,15 +37,23 @@ func testIndexerTableACLPolicies() map[string]indexerTestCase { func testIndexerTableACLTokens() map[string]indexerTestCase { policyID1 := "123e4567-e89a-12d7-a456-426614174001" policyID2 := "123e4567-e89a-12d7-a456-426614174002" + roleID1 := "123e4567-e89a-12d7-a457-426614174001" + roleID2 := "123e4567-e89a-12d7-a457-426614174002" obj := &structs.ACLToken{ AccessorID: "123e4567-e89a-12d7-a456-426614174abc", SecretID: "123e4567-e89a-12d7-a456-426614174abd", + Policies: []structs.ACLTokenPolicyLink{ {ID: policyID1}, {ID: policyID2}, }, + Roles: []structs.ACLTokenRoleLink{ + {ID: roleID1}, {ID: roleID2}, + }, } encodedPID1 := []byte{0x12, 0x3e, 0x45, 0x67, 0xe8, 0x9a, 0x12, 0xd7, 0xa4, 0x56, 0x42, 0x66, 0x14, 0x17, 0x40, 0x01} encodedPID2 := []byte{0x12, 0x3e, 0x45, 0x67, 0xe8, 0x9a, 0x12, 0xd7, 0xa4, 0x56, 0x42, 0x66, 0x14, 0x17, 0x40, 0x02} + encodedRID1 := []byte{0x12, 0x3e, 0x45, 0x67, 0xe8, 0x9a, 0x12, 0xd7, 0xa4, 0x57, 0x42, 0x66, 0x14, 0x17, 0x40, 0x1} + encodedRID2 := []byte{0x12, 0x3e, 0x45, 0x67, 0xe8, 0x9a, 0x12, 0xd7, 0xa4, 0x57, 0x42, 0x66, 0x14, 0x17, 0x40, 0x2} return map[string]indexerTestCase{ indexPolicies: { read: indexValue{ @@ -59,6 +67,18 @@ func testIndexerTableACLTokens() map[string]indexerTestCase { expected: [][]byte{encodedPID1, encodedPID2}, }, }, + indexRoles: { + read: indexValue{ + source: Query{ + Value: roleID1, + }, + expected: encodedRID1, + }, + writeMulti: indexValueMulti{ + source: obj, + expected: [][]byte{encodedRID1, encodedRID2}, + }, + }, } } diff --git a/agent/consul/state/acl_schema.go b/agent/consul/state/acl_schema.go index 7ff88948cb..3ef2c1fa08 100644 --- a/agent/consul/state/acl_schema.go +++ b/agent/consul/state/acl_schema.go @@ -61,7 +61,10 @@ func tokensTableSchema() *memdb.TableSchema { Name: indexRoles, AllowMissing: true, Unique: false, - Indexer: &TokenRolesIndex{}, + Indexer: indexerMulti{ + readIndex: readIndex(indexFromUUIDQuery), + writeIndexMulti: writeIndexMulti(indexRolesFromACLToken), + }, }, indexAuthMethod: { Name: indexAuthMethod, @@ -378,3 +381,28 @@ func indexPoliciesFromACLToken(raw interface{}) ([][]byte, error) { return vals, nil } + +func indexRolesFromACLToken(raw interface{}) ([][]byte, error) { + token, ok := raw.(*structs.ACLToken) + if !ok { + return nil, fmt.Errorf("unexpected type %T for structs.ACLToken index", raw) + } + links := token.Roles + + numLinks := len(links) + if numLinks == 0 { + return nil, errMissingValueForIndex + } + + vals := make([][]byte, numLinks) + + for i, link := range links { + id, err := uuidStringToBytes(link.ID) + if err != nil { + return nil, err + } + vals[i] = id + } + + return vals, nil +}