en-US/about_Omnicit.EntraRBAC.help.txt
|
TOPIC about_Omnicit.EntraRBAC SHORT DESCRIPTION Manage Entra ID and Azure RBAC building blocks across tenants. LONG DESCRIPTION Omnicit.EntraRBAC manages Entra ID groups and PIM, Administrative Units, Entitlement Management, Access Reviews, Azure resources and RBAC, and Azure PIM across multiple tenants, plus a JSON inventory and a declarative apply engine. Authenticate with Connect-OER, then use the OER cmdlets. Configuration per tenant is stored in Tenant Profile files managed by New/Get/Set/Remove-OERConfiguration. Calling Connect-OER is optional. Every cmdlet that reaches Graph or Azure authenticates on first use, reusing a cached token for the same tenant and identity. Cmdlets that reach Azure Resource Manager need an ARM token; pass -IncludeARM to Connect-OER to acquire one up front. All state-changing cmdlets support -WhatIf and -Confirm. Deletions of high-value objects use ConfirmImpact High and warn before the destructive call. Use Get-Command -Module Omnicit.EntraRBAC to list all 92 cmdlets, and Get-Help <cmdlet> -Full for parameters and examples. Use Get-OERRequiredScope for the permissions any of them needs; see PERMISSIONS below. COMMAND COHORTS The cohorts below are for orientation only. They are NOT permission boundaries, so none of them carries a scope line -- ask Get-OERRequiredScope instead. Authentication and Tenant Profiles Connect-OER, Disconnect-OER New-OERConfiguration, Get-OERConfiguration, Set-OERConfiguration, Remove-OERConfiguration Groups and PIM for Groups New-OERGroup, Get-OERGroup, Set-OERGroup, Remove-OERGroup Add-OERGroupMember, Get-OERGroupMember, Remove-OERGroupMember Add-OERGroupEligibility, Get-OERGroupEligibility, Remove-OERGroupEligibility Get-OERGroupPimPolicy, Set-OERGroupPimPolicy Administrative Units New-OERAdministrativeUnit, Get-OERAdministrativeUnit, Set-OERAdministrativeUnit, Remove-OERAdministrativeUnit Add-OERAdministrativeUnitMember, Remove-OERAdministrativeUnitMember Add-OERAdministrativeUnitScopedRole, Get-OERAdministrativeUnitScopedRole, Remove-OERAdministrativeUnitScopedRole New-OERGroup -AdministrativeUnit places a new group into an AU at creation time. Entitlement Management Catalogs: New-OERCatalog, Get-OERCatalog, Set-OERCatalog, Remove-OERCatalog Catalog resources: Add-OERCatalogResource, Get-OERCatalogResource, Remove-OERCatalogResource Access packages: New-OERAccessPackage, Get-OERAccessPackage, Set-OERAccessPackage, Remove-OERAccessPackage Resource roles: Add-OERAccessPackageResourceRole, Get-OERAccessPackageResourceRole, Remove-OERAccessPackageResourceRole Policy builders: New-OERAccessPackageApprovalStage, New-OERAccessPackageRequestorScope, New-OERAccessPackageRequestorSettings Policies: New-OERAccessPackageAssignmentPolicy, Get-OERAccessPackageAssignmentPolicy, Set-OERAccessPackageAssignmentPolicy, Remove-OERAccessPackageAssignmentPolicy Assignments: New-OERAccessPackageAssignment, Get-OERAccessPackageAssignment, Remove-OERAccessPackageAssignment Access Reviews New-OERAccessReviewDefinition, Get-OERAccessReviewDefinition, Set-OERAccessReviewDefinition, Remove-OERAccessReviewDefinition New-OERAccessReviewStage composes one stage of a multi-stage review. Get-OERAccessReviewInstance, Get-OERAccessReviewInstanceDecision, Stop-OERAccessReviewInstance, Invoke-OERAccessReviewInstanceDecision, Send-OERAccessReviewReminder Directory roles Get-OERDirectoryRoleManagementPolicy, Set-OERDirectoryRoleManagementPolicy Azure inventory, RBAC, resource groups and resources Get-OERManagementGroup, Get-OERSubscription, Get-OERRoleDefinition Get-OERRoleAssignment, New-OERRoleAssignment, Set-OERRoleAssignment, Remove-OERRoleAssignment New-OERResourceGroup, Get-OERResourceGroup, Set-OERResourceGroup, Remove-OERResourceGroup, Get-OERResource Azure PIM Eligibility: New-OEREligibleRoleAssignment, Get-OEREligibleRoleAssignment, Remove-OEREligibleRoleAssignment Active: New-OERActiveRoleAssignment, Get-OERActiveRoleAssignment, Remove-OERActiveRoleAssignment Activation: Enable-OEREligibleRoleAssignment, Disable-OEREligibleRoleAssignment Policy: Get-OERRoleManagementPolicy, Set-OERRoleManagementPolicy, New-OERPolicyNotificationRule Inventory and JSON orchestration Get-OERInventory reads tenant state into a round-trippable inventory object. Export-OERInventory writes that state to a bundle folder (JSON, schema, LLM prompt, README). Test-OERStructure validates a structure document offline with no tenant call. Invoke-OERStructure applies one idempotently in dependency order, with -WhatIf plan mode and opt-in child-scope -Prune. Permissions Get-OERRequiredScope reports the Graph permissions and Azure RBAC roles one or more cmdlets need. See PERMISSIONS below. Conditional Access Get-OERAuthenticationContext PERMISSIONS Ask the module rather than reading a table kept in step by hand: Get-OERRequiredScope -Cmdlet New-OERGroup Get-OERRequiredScope -Cmdlet Get-OERGroup* -Unique Get-OERRequiredScope -Unique It reads a static table, so it needs no tenant and no sign-in and answers before Connect-OER. Three things worth knowing about the answers: - The area a cmdlet belongs to is not its permission boundary. Microsoft Graph grants permissions by the resource a call touches, so one scope line covering a whole cohort is wrong by construction. The three *AdministrativeUnitScopedRole cmdlets write directory role memberships rather than unit memberships and need a role-management write permission; Get-OERGroupPimPolicy and Set-OERGroupPimPolicy hit roleManagementPolicies and need the RoleManagementPolicy permissions, not the eligibility permissions the other PIM-for-Groups cmdlets use. - Each answer is transitive. It covers the cmdlet's own calls plus every call its internal helpers make, including the directory reads behind friendly-name parameters such as -User, -Group and -ServicePrincipal. Consenting to what is listed is enough for every parameter form; the Note property says so where a permission is needed for only one of them. - The Transport property disambiguates an empty list: Graph, Arm, GraphAndArm, or None for a cmdlet that touches no tenant at all. An empty GraphScope on an ARM-only cmdlet means "none needed", never "unknown". Where an entry lists User.ReadBasic.All, Group.Read.All and Application.Read.All, a single Directory.Read.All covers all three; the narrower permissions are listed because the module prefers least privilege. Where an entry lists Directory.Read.All instead, that cmdlet reads directoryObjects, which accepts nothing narrower, so the covered permissions are deliberately NOT also listed and the Note property says which parameter makes the call. Azure cmdlets additionally need an ARM token: pass -IncludeARM to Connect-OER, or let the cmdlet acquire one. TENANT PROFILE A Tenant Profile is a PSD1 file holding per-tenant configuration, stored under <home>/.config/Omnicit.EntraRBAC/Profiles/<alias>.psd1 and managed with New-OERConfiguration, Get-OERConfiguration, Set-OERConfiguration and Remove-OERConfiguration. <home> is the current user's profile folder as .NET reports it, falling back to $HOME: the same directory as $env:USERPROFILE on Windows, and the user's home directory on Linux and macOS. Connect-OER -TenantAlias <alias> resolves the TenantId from it. Only TenantId is required; every other section is optional. @{ TenantId = '00000000-0000-0000-0000-000000000000' Naming = @{ Group = 'role_sec_{area}_{tier}' AU = '{prefix}_au_{name}' Catalog = 'CAT-{org}-{scope}' } Defaults = @{ PrimaryApprovers = @('<guid>', '<guid>') EscalationApprovers = @('<guid>') Catalog = 'CAT-IT-PRG-Core' AuthenticationContextId = 'c1' ActivationMaxHours = 8 } } Naming templates substitute {token} placeholders case-insensitively. An unresolved placeholder is an error, so a malformed name is never produced. Set-OERConfiguration preserves sections you do not supply; New-OERConfiguration is create-only and errors if the alias already exists. A profile may also carry an optional Environment key naming the sovereign cloud that tenant lives in: Global, USGov, USGovDoD or China. See SOVEREIGN CLOUDS below. SWITCHING TENANTS One PowerShell session works in one tenant at a time. Whether a later Connect-OER call naming a different tenant actually switches depends on the sign-in type: Client secret Reuses the credential built for the earlier tenant, so the switching sign-in fails by default -- or, with AZURE_IDENTITY_DISABLE_MULTITENANTAUTH set, silently reaches the earlier tenant instead -- until you run Connect-OER ... -Force Device code Does not send the tenant you name; its token may come from the signed-in account's own tenant when that account cannot obtain one in the tenant you name -- and the switching call may not return at all: see the known limitation below Managed identity Does not send the tenant you name; its token normally comes from the identity's own tenant Interactive Signs in to the tenant you name Certificate Signs in to the tenant you name KNOWN LIMITATION -- a device code tenant switch can stop responding. In a PowerShell process where a device code sign-in has already completed, a further device code sign-in naming a different tenant, with no -Force, never returns: no device code is printed, no error is raised, and the call does not come back. Ctrl+C is the only escape, and it leaves the credential AzAuth keeps for the process in an unknown state, so exit the PowerShell session afterwards rather than retrying in it. Pass Connect-OER ... -Force on the switching call -- measured to cure it every time it was used -- or start a new PowerShell session, which begins from a fresh credential. Not every device code tenant switch is affected: the first device code sign-in in a process is fine, and so is a switch made straight after a sign-in with -IncludeARM, whose Azure Resource Manager token is acquired under a different application and so leaves AzAuth holding a freshly built credential. The module warns in two cases. It warns before a client secret sign-in for the same application when the tenant you name differs from the one the credential AzAuth is currently holding for that application was built for, and no Force is on the call: you did not pass -Force, and the module did not add Force itself for a sovereign-cloud switch. AzAuth only rebuilds that credential for -Force, for a different application, or for a different kind of sign-in -- a plain retry of the same switch, with none of those, reuses the same credential and keeps warning every time, whether the earlier attempt was silently answered from the old tenant or refused outright. This is the module's own view: a Get-AzToken call made outside the module does not update it, and it resets only when Omnicit.EntraRBAC itself is re-imported. It also warns after a sign-in of any type that names a tenant by domain, when that tenant differs from the one named by the last session this module established in the process and the token was issued by the same tenant that issued that session's token. That comparison survives Disconnect-OER, so disconnecting and reconnecting to another tenant is still checked, but it does not fire for a sign-in that names no tenant, and it cannot check the very first sign-in in a process or the first one after Omnicit.EntraRBAC is re-imported. Neither warning stops the sign-in, but under -WarningAction Stop (or $WarningPreference = 'Stop') either one does -- the pre-call warning before any token is requested, the post-call warning before the session is created -- the same safe direction as the module's existing ambient AZURE_AUTHORITY_HOST warning. Disconnect-OER clears only this module's own session state; it does not clear the credential AzAuth keeps for the process, and the tenant-switch check above does not depend on that state -- it keeps its own record, so disconnecting and reconnecting to another tenant is still checked. Connect-OER -Force is the supported way, inside the same PowerShell process, to move a client secret sign-in to a new tenant. Name tenants by their tenant ID (a GUID) -- including a Tenant Profile's TenantId -- rather than by domain: with a GUID the module refuses a token issued for another tenant outright, where a domain-named request can only be warned about. # Move a client secret sign-in for the same application to # another tenant Connect-OER -TenantId '00000000-0000-0000-0000-000000000000' ` -ClientId $AppId -ClientSecret $Secret -Force SOVEREIGN CLOUDS Connect-OER -Environment selects the sovereign cloud a session signs in to and calls. Four values are supported: Global (default) Worldwide commercial cloud graph.microsoft.com / management.azure.com USGov GCC High graph.microsoft.us / management.usgovcloudapi.net USGovDoD DoD dod-graph.microsoft.us / management.usgovcloudapi.net China 21Vianet microsoftgraph.chinacloudapi.cn / management.chinacloudapi.cn Microsoft 365 GCC uses the commercial (Global) endpoints and needs no -Environment at all. Only GCC High, DoD and a 21Vianet tenant are separate cloud boundaries; GCC itself is not. The chosen cloud becomes part of the session: every later cmdlet calls the cloud the session was established in, and switching clouds re-authenticates instead of reusing a token minted at the previous cloud's authority. Connect-OER -TenantId 'contoso.onmicrosoft.us' -Environment USGov -IncludeARM A Tenant Profile's optional Environment key stores the cloud for that tenant, so Connect-OER -TenantAlias picks it up automatically without repeating -Environment on every call; an explicit -Environment on the command line still overrides it. Name the tenant explicitly and consistently. The session is keyed on the tenant exactly as you spell it, so a later call naming a tenant the session was not established for inherits nothing from it -- including the same tenant written as a GUID one time and as a domain the next, and a Connect-OER -Environment USGov with no -TenantId at all, which records the tenant as 'organizations' rather than as yours. The cloud then resets to Global and that call signs in at the commercial authority. Its token and its endpoints stay consistent with each other, so nothing crosses a cloud boundary, but the sign-in fails at the authority with an error that names the tenant and never the cloud, which makes it easy to misread. Pass the same -TenantId spelling on every call, or use a Tenant Profile whose Environment key carries the cloud for you. Known limitation: PIM-for-Groups is pinned to the Microsoft Graph beta endpoint (see PERMISSIONS above), and beta endpoint availability in US Government and China clouds is not established. A sovereign tenant that needs PIM-for-Groups may find that pinned beta path behaves differently, or not at all, from the commercial cloud this module is built and tested against. AZURE RESOURCE TARGETING Azure RBAC and PIM assignment cmdlets (New/Get-OERRoleAssignment, New/Get/Remove-OEREligibleRoleAssignment, New/Get/Remove-OERActiveRoleAssignment, Enable/Disable-OEREligibleRoleAssignment) accept a resource scope in three forms: - Raw scope id: -Scope '<full ARM resource id>' - Friendly decomposition: -Subscription <s> -ResourceGroup <rg> -ResourceType <type> -ResourceName <name> - Management group: -ManagementGroup <name-or-id> Get-OERRoleManagementPolicy and Set-OERRoleManagementPolicy accept the same scope forms minus -ResourceType and -ResourceName, because a role management policy is assigned at a management group, subscription or resource group scope. By contrast Set-OERRoleAssignment and Remove-OERRoleAssignment take -Id only: they act on one existing assignment, which already carries its own scope. Get-OERResource lists Azure resources within a subscription or resource group (client-side -Name/-ResourceType filters) and, with -IncludeRoleAssignments (optionally -ResolveNames), reports the role-assignment delegations on each resource. Output is tagged Omnicit.EntraRBAC.Resource and binds directly into the assignment cmdlets by property name -- for example: Get-OERResource -Subscription Prod -ResourceGroup rg-app -Name stgfoo | New-OERRoleAssignment -Role Reader -Group role_sec_readers ARM OBJECT IDS Get-OERResource, Get-OERResourceGroup, Get-OERSubscription and Get-OERManagementGroup expose the full ARM resource path as ResourceId, never as a bare Id. This is deliberate: -PolicyId on Get-OERRoleManagementPolicy/Set-OERRoleManagementPolicy and -RoleEligibilityScheduleId on Enable-OEREligibleRoleAssignment both carry an Id alias and bind from the pipeline by property name, so a bare Id on an ARM-resource object would silently mis-route as a policy id or an eligibility schedule id instead of the resource path it actually is. Get-OERRoleDefinition follows the same no-bare-Id rule but stores the ARM role definition path the other way round: RoleDefinitionId is the one STORED value (so a piped role definition still binds -Role on New-OERRoleAssignment, and its PIM siblings, through that alias), and ResourceId is exposed as an AliasProperty of it rather than a second stored copy. Either property reads the same value; there is deliberately no bare Id that could mis-bind downstream. Role-ASSIGNMENT-shaped objects (RoleAssignment, EligibleRoleAssignment, ActiveRoleAssignment) are a different case: they identify an assignment INSTANCE, not an ARM resource, so their own domain-specific id (RoleAssignmentId, RoleEligibilityScheduleId, RoleAssignmentScheduleId) is the right property to carry, not ResourceId. Set-OERRoleAssignment and Remove-OERRoleAssignment act on -Id alone (the RoleAssignmentId, which already embeds the scope) rather than on the friendly -Subscription/-ResourceGroup/-ManagementGroup decomposition above. ACCESS PACKAGE ASSIGNMENT POLICY -- GRANULAR SETTINGS New-OERAccessPackageRequestorSettings builds a requestor-settings object that controls how users and managers may submit requests: $Rs = New-OERAccessPackageRequestorSettings -AllowSelfRequest ` -AllowManagerRequest -ManagerLevel 1 -AllowSelfExtend All -Allow* parameters are switches. Pass the result to New-OERAccessPackageAssignmentPolicy or Set-OERAccessPackageAssignmentPolicy via -RequestorSettings. Both policy cmdlets also accept (the toggles are switches): -RequireApproval -- enable the approval workflow -RequireRequestorJustification -- require a justification from the requestor -RequireApprovalForUpdate -- require approval for extension requests -DurationInHours <int> -- assignment lifetime in hours (PT{n}H) -DisableAssignmentNotifications -- suppress built-in assignment emails New-OERAccessPackageApprovalStage accepts -ApproverInfoVisibility (Default / Visible / NotVisible) to control whether approver identity is shown to the requestor. Set-OERAccessPackageAssignmentPolicy is a read-modify-write (GET then PUT): fields you do not supply are preserved from the live policy (including the out-of-scope reviewSettings and custom questions). On both New- and Set-OERAccessPackageAssignmentPolicy the Description parameter defaults to the policy display name when omitted. Limitations: policy-embedded access reviews (reviewSettings) and custom requestor questions cannot be expressed in an apply document -- they are preserved by the read-modify-write. Fallback approvers are preserved when their stage is unchanged but are dropped when the stage is rebuilt. DURATION VOCABULARY Most cmdlets that accept a lifetime or expiration share the same duration vocabulary. (A few narrowly-scoped parameters, such as Set-OERRoleManagementPolicy -ActivationMaxHours and New-OERAccessPackageApprovalStage -EscalationDays, keep their own already-unit-specific name instead.) -Duration <string> -- raw ISO 8601 duration (P365D, PT8H) -DurationDays <int> -- whole days, converted to P{n}D -DurationHours <int> -- whole hours, converted to PT{n}H -DurationInDays / -DurationInHours (access packages, access reviews) and -EligibleDuration / -ActiveDuration (PIM policies) are the canonical parameter names; -DurationDays / -DurationHours and -EligibleDurationDays / -ActiveDurationDays are the module-standard aliases this unification added. Exception: Add-OERGroupEligibility -Duration also accepts a bare whole day count (-Duration 365 means 365 days) for back-compat with its original shipped signature. This is deliberate and scoped to that one cmdlet -- New-OEREligibleRoleAssignment -Duration, by contrast, validates strictly against the ISO 8601 pattern and rejects a bare number such as 365 outright. SEE ALSO Connect-OER Get-OERConfiguration Get-OERGroup Get-OERAdministrativeUnit Get-OERAccessPackage Get-OERAccessReviewDefinition Get-OERRoleAssignment Get-OEREligibleRoleAssignment Get-OERRoleManagementPolicy Get-OERInventory Invoke-OERStructure |