From 99fca0f7463207820748d38c9be3484539332799 Mon Sep 17 00:00:00 2001 From: Emma Thorpe Date: Fri, 28 Aug 2026 11:33:12 +0100 Subject: [PATCH] docs(memory): record that Entra group member reads hide service principals az ad group member list and GET /groups/{id}/members return an empty collection, without error, for groups whose members are service principals. Records the reads that do work and the rule to trust a Terraform plan over that output. --- home/claude/memory/MEMORY.md | 1 + .../claude/memory/entra_group_member_reads.md | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 home/claude/memory/entra_group_member_reads.md diff --git a/home/claude/memory/MEMORY.md b/home/claude/memory/MEMORY.md index 9acb154..d4975d4 100644 --- a/home/claude/memory/MEMORY.md +++ b/home/claude/memory/MEMORY.md @@ -16,3 +16,4 @@ - [Nix shell tooling](nix_shell_tooling.md) — any nixpkgs tool runs ad hoc via `nix run`/`nix shell nixpkgs#`; a missing command is never a dead end - [WSP local build and test](wsp_local_build_and_test.md) — core-services-cloud on this box: dotnet via nix, artifactory creds from `~/.artifactoryenv` sourced per command, how to tell auth failure from a code failure - [WSP-32957 PIM migration](wsp_32957_pim_migration.md) — AKS RBAC to PIM + AutoPerm decommission; prod is in the Technical Preview subscription, three tenants; resume via `~/code/WSP-32957-CONTINUATION.md` +- [Entra group member reads](entra_group_member_reads.md) — `az ad group member list` hides service principal members; use the servicePrincipal cast or transitiveMemberOf, and trust the Terraform plan over it diff --git a/home/claude/memory/entra_group_member_reads.md b/home/claude/memory/entra_group_member_reads.md new file mode 100644 index 0000000..eb83cc1 --- /dev/null +++ b/home/claude/memory/entra_group_member_reads.md @@ -0,0 +1,28 @@ +--- +name: entra-group-member-reads +description: az ad group member list and Graph /members silently omit service principal members — use the servicePrincipal cast or transitiveMemberOf when a group is expected to hold an SPN. +metadata: + node_type: memory + type: reference +--- + +`az ad group member list --group ` and `GET /groups/{id}/members` both return an **empty collection**, with no error, for a group whose only members are service principals — at least when called with Lyra's user account. The read looks authoritative and is not. + +**Reliable reads instead:** + +```sh +# members, cast to the type that is being hidden +az rest --method get --url "https://graph.microsoft.com/v1.0/groups//members/microsoft.graph.servicePrincipal?\$select=id,displayName" + +# count, which does not filter +az rest --method get --url "https://graph.microsoft.com/v1.0/groups//members/\$count" --headers ConsistencyLevel=eventual + +# from the principal's side +az rest --method get --url "https://graph.microsoft.com/v1.0/servicePrincipals//transitiveMemberOf?\$select=id,displayName" +az rest --method post --url "https://graph.microsoft.com/v1.0/servicePrincipals//checkMemberGroups" \ + --body '{"groupIds":[""]}' --headers "Content-Type=application/json" +``` + +**How to apply:** any group that deployment or automation identities belong to — `*-cluster-admins`, `*-keyvault`, anything created by `rg-prereqs` — must be checked with one of the above before concluding it is empty. Cross-check against Terraform: a plan reporting "No changes" against a `members` attribute is strong evidence the membership is present, and outranks the `az` read. On 2026-08-28 the plain read produced a Bug (WSP-33432, cancelled) claiming five `*-cluster-admins` groups across three tenants had been emptied; all five held their deployment principals the whole time. + +Related: [[wsp-32957-pim-migration]]. -- 2.54.0