Identity: Remove unused MemDB indexes and unused functions (#4817)
* refactor delete utility * refactor delete alias utility * remove MemDBUpsertAlias * Remove MemDBAliasByCanonicalID * remove MemDBAliasesByMetadata * remove MemDBDeleteAliasByID * Remove MemDBUpsertEntity and MemDBEntityByNameInTxn * Remove is.MemDBEntitiesByBucketEntryKeyHash * Remove MemDBEntitiesByBucketEntryKeyHash and MemDBEntityByMergedEntityID * Remove MemDBEntities * Remove validateMemberGroupID * Remove validateEntityID, validateGroupID, deleteAliasFromEntity * Remove updateAliasInEntity * Remove satisfiesMetadataFilters and UpsertGroup * Remove MemDBUpsertGroup * Remove deleteGroupByID * Remove deleleGroupByName * Remove MemDBDeleteGroupByNameInTxn * Remove MemDBGroupsByPolicy and MemDBGroupsByPolicyInTxn * Remove MemDBGroupIterator * Remove MemDBGroupsByBucketEntryKeyHash * Remove deleteGroupAlias * Remove metadata index from entities table * Remove unneeded indexes from entity alias and group alias schema * Remove unneeded index from groups table schema * Fix test * s/entity/lockEntity * Don't expose the memdb instance outside identity store * More txn.Abort() corrections * switch back to deferring abort calls
This commit is contained in:
parent
619dd3c6ed
commit
57c7ecfcd4
|
@ -226,7 +226,7 @@ func (i *IdentityStore) Invalidate(ctx context.Context, key string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only update MemDB and don't touch the storage
|
// Only update MemDB and don't touch the storage
|
||||||
err = i.upsertGroupInTxn(txn, group, false)
|
err = i.UpsertGroupInTxn(txn, group, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
i.logger.Error("failed to update group in MemDB", "error", err)
|
i.logger.Error("failed to update group in MemDB", "error", err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -9,6 +9,8 @@ import (
|
||||||
"github.com/hashicorp/errwrap"
|
"github.com/hashicorp/errwrap"
|
||||||
memdb "github.com/hashicorp/go-memdb"
|
memdb "github.com/hashicorp/go-memdb"
|
||||||
"github.com/hashicorp/vault/helper/identity"
|
"github.com/hashicorp/vault/helper/identity"
|
||||||
|
"github.com/hashicorp/vault/helper/locksutil"
|
||||||
|
"github.com/hashicorp/vault/helper/storagepacker"
|
||||||
"github.com/hashicorp/vault/logical"
|
"github.com/hashicorp/vault/logical"
|
||||||
"github.com/hashicorp/vault/logical/framework"
|
"github.com/hashicorp/vault/logical/framework"
|
||||||
)
|
)
|
||||||
|
@ -291,19 +293,31 @@ func (i *IdentityStore) handleAliasUpdateCommon(req *logical.Request, d *framewo
|
||||||
|
|
||||||
if entity != nil && entity.ID != existingEntity.ID {
|
if entity != nil && entity.ID != existingEntity.ID {
|
||||||
// Alias should be transferred from 'existingEntity' to 'entity'
|
// Alias should be transferred from 'existingEntity' to 'entity'
|
||||||
err = i.deleteAliasFromEntity(existingEntity, alias)
|
for aliasIndex, item := range existingEntity.Aliases {
|
||||||
if err != nil {
|
if item.ID == alias.ID {
|
||||||
return nil, err
|
entity.Aliases = append(existingEntity.Aliases[:aliasIndex], existingEntity.Aliases[aliasIndex+1:]...)
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
previousEntity = existingEntity
|
previousEntity = existingEntity
|
||||||
entity.Aliases = append(entity.Aliases, alias)
|
entity.Aliases = append(entity.Aliases, alias)
|
||||||
resp.AddWarning(fmt.Sprintf("alias is being transferred from entity %q to %q", existingEntity.ID, entity.ID))
|
resp.AddWarning(fmt.Sprintf("alias is being transferred from entity %q to %q", existingEntity.ID, entity.ID))
|
||||||
} else {
|
} else {
|
||||||
// Update entity with modified alias
|
// Update entity with modified alias
|
||||||
err = i.updateAliasInEntity(existingEntity, alias)
|
aliasFound := false
|
||||||
if err != nil {
|
for aliasIndex, item := range existingEntity.Aliases {
|
||||||
return nil, err
|
if item.ID == alias.ID {
|
||||||
|
aliasFound = true
|
||||||
|
existingEntity.Aliases[aliasIndex] = alias
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !aliasFound {
|
||||||
|
return nil, fmt.Errorf("alias does not exist in entity")
|
||||||
|
}
|
||||||
|
|
||||||
entity = existingEntity
|
entity = existingEntity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -406,7 +420,103 @@ func (i *IdentityStore) pathAliasIDDelete() framework.OperationFunc {
|
||||||
return logical.ErrorResponse("missing alias ID"), nil
|
return logical.ErrorResponse("missing alias ID"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, i.deleteAlias(aliasID)
|
// Fetch the alias using its ID
|
||||||
|
alias, err := i.MemDBAliasByID(aliasID, false, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is no alias for the ID, do nothing
|
||||||
|
if alias == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the entity to which the alias is tied to
|
||||||
|
lockEntity, err := i.MemDBEntityByAliasID(alias.ID, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is no entity tied to a valid alias, something is wrong
|
||||||
|
if lockEntity == nil {
|
||||||
|
return nil, fmt.Errorf("alias not associated to an entity")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Acquire the lock to modify the entity storage entry
|
||||||
|
lock := locksutil.LockForKey(i.entityLocks, lockEntity.ID)
|
||||||
|
lock.Lock()
|
||||||
|
defer lock.Unlock()
|
||||||
|
|
||||||
|
// Create a MemDB transaction to delete entity
|
||||||
|
txn := i.db.Txn(true)
|
||||||
|
defer txn.Abort()
|
||||||
|
|
||||||
|
// Fetch the alias again after acquiring the lock using the transaction
|
||||||
|
// created above
|
||||||
|
alias, err = i.MemDBAliasByIDInTxn(txn, aliasID, false, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is no alias for the ID, do nothing
|
||||||
|
if alias == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch the entity again after acquiring the lock using the transaction
|
||||||
|
// created above
|
||||||
|
entity, err := i.MemDBEntityByAliasIDInTxn(txn, alias.ID, true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is no entity tied to a valid alias, something is wrong
|
||||||
|
if entity == nil {
|
||||||
|
return nil, fmt.Errorf("alias not associated to an entity")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lock switching should not end up in this code pointing to different
|
||||||
|
// entities
|
||||||
|
if lockEntity.ID != entity.ID {
|
||||||
|
return nil, fmt.Errorf("operating on an entity to which the lock doesn't belong to")
|
||||||
|
}
|
||||||
|
|
||||||
|
aliases := []*identity.Alias{
|
||||||
|
alias,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete alias from the entity object
|
||||||
|
err = i.deleteAliasesInEntityInTxn(txn, entity, aliases)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the entity index in the entities table
|
||||||
|
err = i.MemDBUpsertEntityInTxn(txn, entity)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Persist the entity object
|
||||||
|
entityAsAny, err := ptypes.MarshalAny(entity)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
item := &storagepacker.Item{
|
||||||
|
ID: entity.ID,
|
||||||
|
Message: entityAsAny,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = i.entityPacker.PutItem(item)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Committing the transaction *after* successfully updating entity in
|
||||||
|
// storage
|
||||||
|
txn.Commit()
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,10 +63,13 @@ func TestIdentityStore_MemDBAliasIndexes(t *testing.T) {
|
||||||
|
|
||||||
entity.BucketKeyHash = is.entityPacker.BucketKeyHashByItemID(entity.ID)
|
entity.BucketKeyHash = is.entityPacker.BucketKeyHashByItemID(entity.ID)
|
||||||
|
|
||||||
err = is.MemDBUpsertEntity(entity)
|
txn := is.db.Txn(true)
|
||||||
|
defer txn.Abort()
|
||||||
|
err = is.MemDBUpsertEntityInTxn(txn, entity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
txn.Commit()
|
||||||
|
|
||||||
alias := &identity.Alias{
|
alias := &identity.Alias{
|
||||||
CanonicalID: entity.ID,
|
CanonicalID: entity.ID,
|
||||||
|
@ -80,10 +83,13 @@ func TestIdentityStore_MemDBAliasIndexes(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err = is.MemDBUpsertAlias(alias, false)
|
txn = is.db.Txn(true)
|
||||||
|
defer txn.Abort()
|
||||||
|
err = is.MemDBUpsertAliasInTxn(txn, alias, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
txn.Commit()
|
||||||
|
|
||||||
aliasFetched, err := is.MemDBAliasByID("testaliasid", false, false)
|
aliasFetched, err := is.MemDBAliasByID("testaliasid", false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -94,15 +100,6 @@ func TestIdentityStore_MemDBAliasIndexes(t *testing.T) {
|
||||||
t.Fatalf("bad: mismatched aliases; expected: %#v\n actual: %#v\n", alias, aliasFetched)
|
t.Fatalf("bad: mismatched aliases; expected: %#v\n actual: %#v\n", alias, aliasFetched)
|
||||||
}
|
}
|
||||||
|
|
||||||
aliasFetched, err = is.MemDBAliasByCanonicalID(entity.ID, false, false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(alias, aliasFetched) {
|
|
||||||
t.Fatalf("bad: mismatched aliases; expected: %#v\n actual: %#v\n", alias, aliasFetched)
|
|
||||||
}
|
|
||||||
|
|
||||||
aliasFetched, err = is.MemDBAliasByFactors(validateMountResp.MountAccessor, "testaliasname", false, false)
|
aliasFetched, err = is.MemDBAliasByFactors(validateMountResp.MountAccessor, "testaliasname", false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -112,52 +109,6 @@ func TestIdentityStore_MemDBAliasIndexes(t *testing.T) {
|
||||||
t.Fatalf("bad: mismatched aliases; expected: %#v\n actual: %#v\n", alias, aliasFetched)
|
t.Fatalf("bad: mismatched aliases; expected: %#v\n actual: %#v\n", alias, aliasFetched)
|
||||||
}
|
}
|
||||||
|
|
||||||
aliasesFetched, err := is.MemDBAliasesByMetadata(map[string]string{
|
|
||||||
"testkey1": "testmetadatavalue1",
|
|
||||||
}, false, false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(aliasesFetched) != 1 {
|
|
||||||
t.Fatalf("bad: length of aliases; expected: 1, actual: %d", len(aliasesFetched))
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(alias, aliasesFetched[0]) {
|
|
||||||
t.Fatalf("bad: mismatched aliases; expected: %#v\n actual: %#v\n", alias, aliasFetched)
|
|
||||||
}
|
|
||||||
|
|
||||||
aliasesFetched, err = is.MemDBAliasesByMetadata(map[string]string{
|
|
||||||
"testkey2": "testmetadatavalue2",
|
|
||||||
}, false, false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(aliasesFetched) != 1 {
|
|
||||||
t.Fatalf("bad: length of aliases; expected: 1, actual: %d", len(aliasesFetched))
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(alias, aliasesFetched[0]) {
|
|
||||||
t.Fatalf("bad: mismatched aliases; expected: %#v\n actual: %#v\n", alias, aliasFetched)
|
|
||||||
}
|
|
||||||
|
|
||||||
aliasesFetched, err = is.MemDBAliasesByMetadata(map[string]string{
|
|
||||||
"testkey1": "testmetadatavalue1",
|
|
||||||
"testkey2": "testmetadatavalue2",
|
|
||||||
}, false, false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(aliasesFetched) != 1 {
|
|
||||||
t.Fatalf("bad: length of aliases; expected: 1, actual: %d", len(aliasesFetched))
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(alias, aliasesFetched[0]) {
|
|
||||||
t.Fatalf("bad: mismatched aliases; expected: %#v\n actual: %#v\n", alias, aliasFetched)
|
|
||||||
}
|
|
||||||
|
|
||||||
alias2 := &identity.Alias{
|
alias2 := &identity.Alias{
|
||||||
CanonicalID: entity.ID,
|
CanonicalID: entity.ID,
|
||||||
ID: "testaliasid2",
|
ID: "testaliasid2",
|
||||||
|
@ -170,37 +121,17 @@ func TestIdentityStore_MemDBAliasIndexes(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err = is.MemDBUpsertAlias(alias2, false)
|
txn = is.db.Txn(true)
|
||||||
|
defer txn.Abort()
|
||||||
|
err = is.MemDBUpsertAliasInTxn(txn, alias2, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
err = is.MemDBDeleteAliasByIDInTxn(txn, "testaliasid", false)
|
||||||
aliasesFetched, err = is.MemDBAliasesByMetadata(map[string]string{
|
|
||||||
"testkey1": "testmetadatavalue1",
|
|
||||||
}, false, false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(aliasesFetched) != 2 {
|
|
||||||
t.Fatalf("bad: length of aliases; expected: 2, actual: %d", len(aliasesFetched))
|
|
||||||
}
|
|
||||||
|
|
||||||
aliasesFetched, err = is.MemDBAliasesByMetadata(map[string]string{
|
|
||||||
"testkey3": "testmetadatavalue3",
|
|
||||||
}, false, false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(aliasesFetched) != 1 {
|
|
||||||
t.Fatalf("bad: length of aliases; expected: 1, actual: %d", len(aliasesFetched))
|
|
||||||
}
|
|
||||||
|
|
||||||
err = is.MemDBDeleteAliasByID("testaliasid", false)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
txn.Commit()
|
||||||
|
|
||||||
aliasFetched, err = is.MemDBAliasByID("testaliasid", false, false)
|
aliasFetched, err = is.MemDBAliasByID("testaliasid", false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -511,7 +511,60 @@ func (i *IdentityStore) pathEntityIDDelete() framework.OperationFunc {
|
||||||
return logical.ErrorResponse("missing entity id"), nil
|
return logical.ErrorResponse("missing entity id"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, i.deleteEntity(entityID)
|
// Since an entity ID is required to acquire the lock to modify the
|
||||||
|
// storage, fetch the entity without acquiring the lock
|
||||||
|
lockEntity, err := i.MemDBEntityByID(entityID, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if lockEntity == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Acquire the lock to modify the entity storage entry
|
||||||
|
lock := locksutil.LockForKey(i.entityLocks, lockEntity.ID)
|
||||||
|
lock.Lock()
|
||||||
|
defer lock.Unlock()
|
||||||
|
|
||||||
|
// Create a MemDB transaction to delete entity
|
||||||
|
txn := i.db.Txn(true)
|
||||||
|
defer txn.Abort()
|
||||||
|
|
||||||
|
// Fetch the entity using its ID
|
||||||
|
entity, err := i.MemDBEntityByIDInTxn(txn, entityID, true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is no entity for the ID, do nothing
|
||||||
|
if entity == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete all the aliases in the entity. This function will also remove
|
||||||
|
// the corresponding alias indexes too.
|
||||||
|
err = i.deleteAliasesInEntityInTxn(txn, entity, entity.Aliases)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the entity using the same transaction
|
||||||
|
err = i.MemDBDeleteEntityByIDInTxn(txn, entity.ID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the entity from storage
|
||||||
|
err = i.entityPacker.DeleteItem(entity.ID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Committing the transaction *after* successfully deleting entity
|
||||||
|
txn.Commit()
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,11 +573,16 @@ func (i *IdentityStore) pathEntityIDDelete() framework.OperationFunc {
|
||||||
func (i *IdentityStore) pathEntityIDList() framework.OperationFunc {
|
func (i *IdentityStore) pathEntityIDList() framework.OperationFunc {
|
||||||
return func(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
return func(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||||
ws := memdb.NewWatchSet()
|
ws := memdb.NewWatchSet()
|
||||||
iter, err := i.MemDBEntities(ws)
|
|
||||||
|
txn := i.db.Txn(false)
|
||||||
|
|
||||||
|
iter, err := txn.Get(entitiesTable, "id")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errwrap.Wrapf("failed to fetch iterator for entities in memdb: {{err}}", err)
|
return nil, errwrap.Wrapf("failed to fetch iterator for entities in memdb: {{err}}", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ws.Add(iter.WatchCh())
|
||||||
|
|
||||||
var entityIDs []string
|
var entityIDs []string
|
||||||
entityInfo := map[string]interface{}{}
|
entityInfo := map[string]interface{}{}
|
||||||
|
|
||||||
|
|
|
@ -222,11 +222,16 @@ func TestIdentityStore_MemDBImmutability(t *testing.T) {
|
||||||
|
|
||||||
entity.BucketKeyHash = is.entityPacker.BucketKeyHashByItemID(entity.ID)
|
entity.BucketKeyHash = is.entityPacker.BucketKeyHashByItemID(entity.ID)
|
||||||
|
|
||||||
err = is.MemDBUpsertEntity(entity)
|
txn := is.db.Txn(true)
|
||||||
|
defer txn.Abort()
|
||||||
|
|
||||||
|
err = is.MemDBUpsertEntityInTxn(txn, entity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
txn.Commit()
|
||||||
|
|
||||||
entityFetched, err := is.MemDBEntityByID(entity.ID, true)
|
entityFetched, err := is.MemDBEntityByID(entity.ID, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -478,10 +483,13 @@ func TestIdentityStore_MemDBEntityIndexes(t *testing.T) {
|
||||||
|
|
||||||
entity.BucketKeyHash = is.entityPacker.BucketKeyHashByItemID(entity.ID)
|
entity.BucketKeyHash = is.entityPacker.BucketKeyHashByItemID(entity.ID)
|
||||||
|
|
||||||
err = is.MemDBUpsertEntity(entity)
|
txn := is.db.Txn(true)
|
||||||
|
defer txn.Abort()
|
||||||
|
err = is.MemDBUpsertEntityInTxn(txn, entity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
txn.Commit()
|
||||||
|
|
||||||
// Fetch the entity using its ID
|
// Fetch the entity using its ID
|
||||||
entityFetched, err := is.MemDBEntityByID(entity.ID, false)
|
entityFetched, err := is.MemDBEntityByID(entity.ID, false)
|
||||||
|
@ -503,23 +511,8 @@ func TestIdentityStore_MemDBEntityIndexes(t *testing.T) {
|
||||||
t.Fatalf("entity mismatched entities; expected: %#v\n actual: %#v\n", entity, entityFetched)
|
t.Fatalf("entity mismatched entities; expected: %#v\n actual: %#v\n", entity, entityFetched)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch entities using the metadata
|
txn = is.db.Txn(false)
|
||||||
entitiesFetched, err := is.MemDBEntitiesByMetadata(map[string]string{
|
entitiesFetched, err := is.MemDBEntitiesByBucketEntryKeyHashInTxn(txn, entity.BucketKeyHash)
|
||||||
"someusefulkey": "someusefulvalue",
|
|
||||||
}, false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(entitiesFetched) != 1 {
|
|
||||||
t.Fatalf("bad: length of entities; expected: 1, actual: %d", len(entitiesFetched))
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(entity, entitiesFetched[0]) {
|
|
||||||
t.Fatalf("entity mismatch; entity: %#v\n entitiesFetched[0]: %#v\n", entity, entitiesFetched[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
entitiesFetched, err = is.MemDBEntitiesByBucketEntryKeyHash(entity.BucketKeyHash)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package command
|
package vault_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
|
@ -253,7 +253,48 @@ func (i *IdentityStore) pathGroupAliasIDDelete() framework.OperationFunc {
|
||||||
return logical.ErrorResponse("missing group alias ID"), nil
|
return logical.ErrorResponse("missing group alias ID"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, i.deleteGroupAlias(groupAliasID)
|
i.groupLock.Lock()
|
||||||
|
defer i.groupLock.Unlock()
|
||||||
|
|
||||||
|
txn := i.db.Txn(true)
|
||||||
|
defer txn.Abort()
|
||||||
|
|
||||||
|
alias, err := i.MemDBAliasByIDInTxn(txn, groupAliasID, false, true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if alias == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
group, err := i.MemDBGroupByAliasIDInTxn(txn, alias.ID, true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is no group tied to a valid alias, something is wrong
|
||||||
|
if group == nil {
|
||||||
|
return nil, fmt.Errorf("alias not associated to a group")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete group alias in memdb
|
||||||
|
err = i.MemDBDeleteAliasByIDInTxn(txn, group.Alias.ID, true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the alias
|
||||||
|
group.Alias = nil
|
||||||
|
|
||||||
|
err = i.UpsertGroupInTxn(txn, group, true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
txn.Commit()
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -163,15 +163,17 @@ func TestIdentityStore_GroupAliases_MemDBIndexes(t *testing.T) {
|
||||||
BucketKeyHash: i.groupPacker.BucketKeyHashByItemID("testgroupid"),
|
BucketKeyHash: i.groupPacker.BucketKeyHashByItemID("testgroupid"),
|
||||||
}
|
}
|
||||||
|
|
||||||
err = i.MemDBUpsertAlias(group.Alias, true)
|
txn := i.db.Txn(true)
|
||||||
|
defer txn.Abort()
|
||||||
|
err = i.MemDBUpsertAliasInTxn(txn, group.Alias, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
err = i.MemDBUpsertGroupInTxn(txn, group)
|
||||||
err = i.MemDBUpsertGroup(group)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
txn.Commit()
|
||||||
|
|
||||||
alias, err := i.MemDBAliasByID("testgroupaliasid", false, true)
|
alias, err := i.MemDBAliasByID("testgroupaliasid", false, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -301,10 +301,15 @@ func (i *IdentityStore) handleGroupReadCommon(group *identity.Group) (*logical.R
|
||||||
|
|
||||||
respData["alias"] = aliasMap
|
respData["alias"] = aliasMap
|
||||||
|
|
||||||
memberGroupIDs, err := i.memberGroupIDsByID(group.ID)
|
var memberGroupIDs []string
|
||||||
|
memberGroups, err := i.MemDBGroupsByParentGroupID(group.ID, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
for _, memberGroup := range memberGroups {
|
||||||
|
memberGroupIDs = append(memberGroupIDs, memberGroup.ID)
|
||||||
|
}
|
||||||
|
|
||||||
respData["member_group_ids"] = memberGroupIDs
|
respData["member_group_ids"] = memberGroupIDs
|
||||||
|
|
||||||
return &logical.Response{
|
return &logical.Response{
|
||||||
|
@ -318,7 +323,53 @@ func (i *IdentityStore) pathGroupIDDelete() framework.OperationFunc {
|
||||||
if groupID == "" {
|
if groupID == "" {
|
||||||
return logical.ErrorResponse("empty group ID"), nil
|
return logical.ErrorResponse("empty group ID"), nil
|
||||||
}
|
}
|
||||||
return nil, i.deleteGroupByID(groupID)
|
|
||||||
|
if groupID == "" {
|
||||||
|
return nil, fmt.Errorf("missing group ID")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Acquire the lock to modify the group storage entry
|
||||||
|
i.groupLock.Lock()
|
||||||
|
defer i.groupLock.Unlock()
|
||||||
|
|
||||||
|
// Create a MemDB transaction to delete group
|
||||||
|
txn := i.db.Txn(true)
|
||||||
|
defer txn.Abort()
|
||||||
|
|
||||||
|
group, err := i.MemDBGroupByIDInTxn(txn, groupID, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is no group for the ID, do nothing
|
||||||
|
if group == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete group alias from memdb
|
||||||
|
if group.Type == groupTypeExternal && group.Alias != nil {
|
||||||
|
err = i.MemDBDeleteAliasByIDInTxn(txn, group.Alias.ID, true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the group using the same transaction
|
||||||
|
err = i.MemDBDeleteGroupByIDInTxn(txn, group.ID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the group from storage
|
||||||
|
err = i.groupPacker.DeleteItem(group.ID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Committing the transaction *after* successfully deleting group
|
||||||
|
txn.Commit()
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,11 +377,16 @@ func (i *IdentityStore) pathGroupIDDelete() framework.OperationFunc {
|
||||||
func (i *IdentityStore) pathGroupIDList() framework.OperationFunc {
|
func (i *IdentityStore) pathGroupIDList() framework.OperationFunc {
|
||||||
return func(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
return func(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||||
ws := memdb.NewWatchSet()
|
ws := memdb.NewWatchSet()
|
||||||
iter, err := i.MemDBGroupIterator(ws)
|
|
||||||
|
txn := i.db.Txn(false)
|
||||||
|
|
||||||
|
iter, err := txn.Get(groupsTable, "id")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errwrap.Wrapf("failed to fetch iterator for group in memdb: {{err}}", err)
|
return nil, errwrap.Wrapf("failed to fetch iterator for group in memdb: {{err}}", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ws.Add(iter.WatchCh())
|
||||||
|
|
||||||
var groupIDs []string
|
var groupIDs []string
|
||||||
groupInfo := map[string]interface{}{}
|
groupInfo := map[string]interface{}{}
|
||||||
|
|
||||||
|
|
|
@ -118,10 +118,13 @@ func TestIdentityStore_MemDBGroupIndexes(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert it into memdb
|
// Insert it into memdb
|
||||||
err = i.MemDBUpsertGroup(group)
|
txn := i.db.Txn(true)
|
||||||
|
defer txn.Abort()
|
||||||
|
err = i.MemDBUpsertGroupInTxn(txn, group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
txn.Commit()
|
||||||
|
|
||||||
// Insert another dummy group
|
// Insert another dummy group
|
||||||
group = &identity.Group{
|
group = &identity.Group{
|
||||||
|
@ -138,10 +141,14 @@ func TestIdentityStore_MemDBGroupIndexes(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert it into memdb
|
// Insert it into memdb
|
||||||
err = i.MemDBUpsertGroup(group)
|
|
||||||
|
txn = i.db.Txn(true)
|
||||||
|
defer txn.Abort()
|
||||||
|
err = i.MemDBUpsertGroupInTxn(txn, group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
txn.Commit()
|
||||||
|
|
||||||
var fetchedGroup *identity.Group
|
var fetchedGroup *identity.Group
|
||||||
|
|
||||||
|
@ -181,23 +188,6 @@ func TestIdentityStore_MemDBGroupIndexes(t *testing.T) {
|
||||||
t.Fatalf("failed to fetch a indexed groups")
|
t.Fatalf("failed to fetch a indexed groups")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch groups based on policy name
|
|
||||||
fetchedGroups, err = i.MemDBGroupsByPolicy("testpolicy1", false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if len(fetchedGroups) != 1 || fetchedGroups[0].Name != "testgroupname" {
|
|
||||||
t.Fatalf("failed to fetch an indexed group")
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchedGroups, err = i.MemDBGroupsByPolicy("testpolicy2", false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if len(fetchedGroups) != 2 {
|
|
||||||
t.Fatalf("failed to fetch indexed groups")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch groups based on member entity ID
|
// Fetch groups based on member entity ID
|
||||||
fetchedGroups, err = i.MemDBGroupsByMemberEntityID("testentityid1", false, false)
|
fetchedGroups, err = i.MemDBGroupsByMemberEntityID("testentityid1", false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -47,13 +47,6 @@ func aliasesTableSchema() *memdb.TableSchema {
|
||||||
Field: "ID",
|
Field: "ID",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"canonical_id": &memdb.IndexSchema{
|
|
||||||
Name: "canonical_id",
|
|
||||||
Unique: false,
|
|
||||||
Indexer: &memdb.StringFieldIndex{
|
|
||||||
Field: "CanonicalID",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"factors": &memdb.IndexSchema{
|
"factors": &memdb.IndexSchema{
|
||||||
Name: "factors",
|
Name: "factors",
|
||||||
Unique: true,
|
Unique: true,
|
||||||
|
@ -68,14 +61,6 @@ func aliasesTableSchema() *memdb.TableSchema {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"metadata": &memdb.IndexSchema{
|
|
||||||
Name: "metadata",
|
|
||||||
Unique: false,
|
|
||||||
AllowMissing: true,
|
|
||||||
Indexer: &memdb.StringMapFieldIndex{
|
|
||||||
Field: "Metadata",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,14 +83,6 @@ func entitiesTableSchema() *memdb.TableSchema {
|
||||||
Field: "Name",
|
Field: "Name",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"metadata": &memdb.IndexSchema{
|
|
||||||
Name: "metadata",
|
|
||||||
Unique: false,
|
|
||||||
AllowMissing: true,
|
|
||||||
Indexer: &memdb.StringMapFieldIndex{
|
|
||||||
Field: "Metadata",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"merged_entity_ids": &memdb.IndexSchema{
|
"merged_entity_ids": &memdb.IndexSchema{
|
||||||
Name: "merged_entity_ids",
|
Name: "merged_entity_ids",
|
||||||
Unique: true,
|
Unique: true,
|
||||||
|
@ -160,14 +137,6 @@ func groupsTableSchema() *memdb.TableSchema {
|
||||||
Field: "ParentGroupIDs",
|
Field: "ParentGroupIDs",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"policies": {
|
|
||||||
Name: "policies",
|
|
||||||
Unique: false,
|
|
||||||
AllowMissing: true,
|
|
||||||
Indexer: &memdb.StringSliceFieldIndex{
|
|
||||||
Field: "Policies",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"bucket_key_hash": &memdb.IndexSchema{
|
"bucket_key_hash": &memdb.IndexSchema{
|
||||||
Name: "bucket_key_hash",
|
Name: "bucket_key_hash",
|
||||||
Unique: false,
|
Unique: false,
|
||||||
|
@ -191,13 +160,6 @@ func groupAliasesTableSchema() *memdb.TableSchema {
|
||||||
Field: "ID",
|
Field: "ID",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"canonical_id": &memdb.IndexSchema{
|
|
||||||
Name: "canonical_id",
|
|
||||||
Unique: false,
|
|
||||||
Indexer: &memdb.StringFieldIndex{
|
|
||||||
Field: "CanonicalID",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"factors": &memdb.IndexSchema{
|
"factors": &memdb.IndexSchema{
|
||||||
Name: "factors",
|
Name: "factors",
|
||||||
Unique: true,
|
Unique: true,
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue