diff --git a/vault/identity_store_group_aliases_test.go b/vault/identity_store_group_aliases_test.go index f5642e3a7524..2e9202be8ddc 100644 --- a/vault/identity_store_group_aliases_test.go +++ b/vault/identity_store_group_aliases_test.go @@ -8,6 +8,58 @@ import ( "github.com/hashicorp/vault/logical" ) +func TestIdentityStore_GroupAliasDeletionOnGroupDeletion(t *testing.T) { + var resp *logical.Response + var err error + + i, accessor, _ := testIdentityStoreWithGithubAuth(t) + + resp, err = i.HandleRequest(context.Background(), &logical.Request{ + Path: "group", + Operation: logical.UpdateOperation, + Data: map[string]interface{}{ + "type": "external", + }, + }) + if err != nil || (resp != nil && resp.IsError()) { + t.Fatalf("bad: resp: %#v\nerr: %v\n", resp, err) + } + groupID := resp.Data["id"].(string) + + resp, err = i.HandleRequest(context.Background(), &logical.Request{ + Path: "group-alias", + Operation: logical.UpdateOperation, + Data: map[string]interface{}{ + "name": "testgroupalias", + "mount_accessor": accessor, + "canonical_id": groupID, + }, + }) + if err != nil || (resp != nil && resp.IsError()) { + t.Fatalf("bad: resp: %#v\nerr: %v\n", resp, err) + } + groupAliasID := resp.Data["id"].(string) + + resp, err = i.HandleRequest(context.Background(), &logical.Request{ + Path: "group/id/" + groupID, + Operation: logical.DeleteOperation, + }) + if err != nil || (resp != nil && resp.IsError()) { + t.Fatalf("bad: resp: %#v\nerr: %v", resp, err) + } + + resp, err = i.HandleRequest(context.Background(), &logical.Request{ + Path: "group-alias/id/" + groupAliasID, + Operation: logical.ReadOperation, + }) + if err != nil || (resp != nil && resp.IsError()) { + t.Fatalf("bad: resp: %#v\nerr: %v", resp, err) + } + if resp != nil { + t.Fatalf("expected a nil response") + } +} + func TestIdentityStore_GroupAliases_CRUD(t *testing.T) { var resp *logical.Response var err error diff --git a/vault/identity_store_util.go b/vault/identity_store_util.go index 0d628e1bd8c8..8203a93f4fa6 100644 --- a/vault/identity_store_util.go +++ b/vault/identity_store_util.go @@ -1664,18 +1664,26 @@ func (i *IdentityStore) deleteGroupByID(groupID string) error { return err } - // If there is no entity for the ID, do nothing + // If there is no group for the ID, do nothing if group == nil { return 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 err + } + } + // Delete the group using the same transaction err = i.MemDBDeleteGroupByIDInTxn(txn, group.ID) if err != nil { return err } - // Delete the entity from storage + // Delete the group from storage err = i.groupPacker.DeleteItem(group.ID) if err != nil { return err diff --git a/website/source/docs/enterprise/identity/index.html.md b/website/source/docs/enterprise/identity/index.html.md index 7930f94c17e3..acfe1a5605b6 100644 --- a/website/source/docs/enterprise/identity/index.html.md +++ b/website/source/docs/enterprise/identity/index.html.md @@ -85,7 +85,7 @@ multiple entities as its members. A group can also have subgroups. Policies set on the group is granted to all members of the group. During request time, when the token's entity ID is being evaluated for the policies that it has access to; along with the policies on the entity itself, policies that are inherited -due to group memberships are be granted. +due to group memberships are also granted. ### Group Hierarchical Permissions