Skip to content

Add export of groups and service principals with error handling #6396

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: Dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Change log for Microsoft365DSC

# UNRELEASED

* AADEntitlementManagementRoleAssignment
* Added functionality to export groups and service principals.
Fixed an issue where the export of `Connected organization administrator` assignments would fail.
FIXES [#5620](https://github.com/microsoft/Microsoft365DSC/issues/5620)
FIXES [#5618](https://github.com/microsoft/Microsoft365DSC/issues/5618)

# 1.25.806.1

* AADApplication
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,40 +89,54 @@ function Get-TargetResource

if (-not [System.String]::IsNullOrEmpty($Id))
{
$getValue = Get-MgBetaRoleManagementEntitlementManagementRoleAssignment -UnifiedRoleAssignmentId $Id
$getValue = Get-MgBetaRoleManagementEntitlementManagementRoleAssignment -UnifiedRoleAssignmentId $Id `
-ExpandProperty 'Principal' `
-ErrorAction SilentlyContinue
}

$user = Get-MgUser -UserId $Principal
$roleInfo = Get-MgBetaRoleManagementEntitlementManagementRoleDefinition -Filter "DisplayName eq '$($RoleDefinition -replace "'", "''")'"

if ($null -eq $getValue)
{
if (-not [System.String]::IsNullOrEmpty($Id))
if ($null -eq $Script:AllRoleAssignments)
{
Write-Verbose -Message "Nothing with id {$Id} was found"
$Script:AllRoleAssignments = Get-MgBetaRoleManagementEntitlementManagementRoleAssignment `
-ExpandProperty 'Principal' `
-All
}

if (-not [string]::IsNullOrEmpty($Principal))
if ($null -eq $Script:AllRoleDefinitions)
{
$PrincipalId = $null
if ($null -ne $user)
{
$PrincipalId = $user.Id
[array]$Script:AllRoleDefinitions = Get-MgBetaRoleManagementEntitlementManagementRoleDefinition -All
$Script:AllRoleDefinitions += @{
Id = 'e65cf63f-9cc2-4b48-8871-cb667e9d90fb'
DisplayName = 'Connected organization administrator'
}
}

$RoleDefinitionId = $null
if ($null -ne $roleInfo)
{
$RoleDefinitionId = $roleInfo.Id
}
$getValue = Get-MgBetaRoleManagementEntitlementManagementRoleAssignment -Filter "PrincipalId eq '$PrincipalId' and RoleDefinitionId eq '$RoleDefinitionId'"
Write-Verbose -Message "Getting role assignment for Principal {$Principal}"
$getValue = $Script:AllRoleAssignments | Where-Object {
($_.Principal.AdditionalProperties.displayName -eq $Principal -or $_.Principal.AdditionalProperties.userPrincipalName -eq $Principal -or $_.Principal.Id -eq $Principal) `
-and ($_.RoleDefinitionId -eq $($Script:AllRoleDefinitions | Where-Object { $_.DisplayName -eq $RoleDefinition }).Id)
}
}
}
else
{
$getValue = $Script:exportedInstance
$user = Get-MgUser -UserId $Principal
}

switch ($getValue.Principal.AdditionalProperties)
{
'#microsoft.graph.user'
{
$principalName = $getValue.Principal.AdditionalProperties.userPrincipalName
}
'#microsoft.graph.group'
{
$principalName = Get-MgGroup -GroupId $getValue.PrincipalId
}
'#microsoft.graph.servicePrincipal'
{
$principalName = $getValue.Principal.AdditionalProperties.displayName
}
}

if ($null -eq $getValue)
Expand All @@ -135,8 +149,8 @@ function Get-TargetResource

$results = @{
Id = $getValue.Id
Principal = $user.UserPrincipalName
RoleDefinition = $roleInfo.DisplayName
Principal = $principalName
RoleDefinition = $RoleDefinition
DisplayName = $getValue.DisplayName
AppScopeId = $getValue.AppScopeId
DirectoryScopeId = $getValue.DirectoryScopeId
Expand Down Expand Up @@ -250,20 +264,38 @@ function Set-TargetResource
#endregion

$currentInstance = Get-TargetResource @PSBoundParameters
$setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters

$batchRequests = @(
@{
id = 'user'
method = 'GET'
url = "/users/$($Principal)&`$select=id,userPrincipalName,displayName"
}
@{
id = 'group'
method = 'GET'
url = "/groups?`$filter=displayName eq '$($Principal -replace "'", "''")'&`$select=id,displayName"
}
@{
id = 'servicePrincipal'
method = 'GET'
url = "/servicePrincipals?`$filter=displayName eq '$($Principal -replace "'", "''")'&`$select=id,displayName"
}
)
$batchResponses = Invoke-M365DSCGraphBatchRequest -Requests $batchRequests

$PSBoundParameters.Remove('Ensure') | Out-Null
$PSBoundParameters.Remove('Credential') | Out-Null
$PSBoundParameters.Remove('ApplicationId') | Out-Null
$PSBoundParameters.Remove('ApplicationSecret') | Out-Null
$PSBoundParameters.Remove('TenantId') | Out-Null
$PSBoundParameters.Remove('CertificateThumbprint') | Out-Null
$PSBoundParameters.Remove('ManagedIdentity') | Out-Null
$PSBoundParameters.Remove('AccessTokens') | Out-Null

$setParameters = ([Hashtable]$PSBoundParameters).clone()
$userInfo = Get-MgUser -UserId $Principal
$objectId = $batchResponses.body.value.id
if ($null -eq $objectId)
{
throw "Principal '$Principal' not found. Ensure the Principal exists and is correctly specified."
}
if ($objectId -is [array] -and $objectId.Count -gt 1)
{
throw "Multiple objects found for Principal '$Principal'. Please specify a unique identifier."
}
$roleInfo = Get-MgBetaRoleManagementEntitlementManagementRoleDefinition -Filter "DisplayName eq '$($RoleDefinition -replace "'", "''")'"
$setParameters.Add('PrincipalId', $userInfo.Id)
$setParameters.Add('PrincipalId', $objectId)
$setParameters.Add('RoleDefinitionId', $roleInfo.Id)
$setParameters.Remove('Principal') | Out-Null
$setParameters.Remove('RoleDefinition') | Out-Null
Expand Down Expand Up @@ -414,6 +446,7 @@ function Export-TargetResource

#region resource generator code
[array]$getValue = Get-MgBetaRoleManagementEntitlementManagementRoleAssignment `
-ExpandProperty 'Principal' `
-All `
-ErrorAction Stop

Expand All @@ -435,16 +468,40 @@ function Export-TargetResource
$Global:M365DSCExportResourceInstancesCount++
}

if ($null -eq $Script:AllRoleDefinitions)
{
[array]$Script:AllRoleDefinitions = Get-MgBetaRoleManagementEntitlementManagementRoleDefinition -All
$Script:AllRoleDefinitions += @{
Id = 'e65cf63f-9cc2-4b48-8871-cb667e9d90fb'
DisplayName = 'Connected organization administrator'
}
}

$displayedKey = $config.id
if (-not [String]::IsNullOrEmpty($config.displayName))
{
$displayedKey = $config.displayName
}
Write-M365DSCHost -Message " |---[$i/$($getValue.Count)] $displayedKey" -DeferWrite
$roleInfo = Get-MgBetaRoleManagementEntitlementManagementRoleDefinition -UnifiedRoleDefinitionId $config.RoleDefinitionId
$roleInfo = $Script:AllRoleDefinitions | Where-Object { $_.Id -eq $config.RoleDefinitionId }
switch ($config.Principal.AdditionalProperties.'@odata.type')
{
'#microsoft.graph.user'
{
$principalName = $config.Principal.AdditionalProperties.userPrincipalName
}
$null
{
$principalName = (Get-MgGroup -GroupId $config.PrincipalId).DisplayName
}
'#microsoft.graph.servicePrincipal'
{
$principalName = $config.Principal.AdditionalProperties.displayName
}
}
$params = @{
Id = $config.Id
Principal = $config.PrincipalId
Principal = $principalName
RoleDefinition = $roleInfo.DisplayName
Credential = $Credential
ApplicationId = $ApplicationId
Expand Down Expand Up @@ -496,4 +553,3 @@ function Export-TargetResource
}

Export-ModuleMember -Function *-TargetResource

Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@

## Description

This resource configures an Azure AD Entitlement Management Role assignments.
This resource configures an Azure AD Entitlement Management Role Assignment.
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,41 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture {
Mock -CommandName Remove-MgBetaRoleManagementEntitlementManagementRoleAssignment -MockWith {
}

Mock -CommandName Get-MgUser -MockWith {
return @{
UserPrincipalName = "[email protected]"
Id = "12345-12345-12345-12345-12345"
}
Mock -CommandName Invoke-M365DSCGraphBatchRequest -MockWith {
return @(
@{
id = 'user'
body = @{
value = @{
userPrincipalName = "[email protected]"
id = "12345-12345-12345-12345-12345"
}
}
}
)
}

Mock -CommandName Get-MgBetaRoleManagementEntitlementManagementRoleDefinition -MockWith {
return @(
@{
DisplayName = "Catalog creator"
Id = "12345-12345-12345-12345-12345"
}
)
}

Mock -CommandName Get-MgBetaRoleManagementEntitlementManagementRoleAssignment -MockWith {
return @{
DisplayName = "Catalog creator"
Id = "12345-12345-12345-12345-12345"
AppScopeId = "/"
PrincipalId = '12345-12345-12345-12345-12345'
Principal = @{
AdditionalProperties = @{
'@odata.type' = '#microsoft.graph.user'
userPrincipalName = "[email protected]"
}
}
RoleDefinitionId = '12345-12345-12345-12345-12345'
DirectoryScopeId = ''
}
}

Expand Down Expand Up @@ -106,15 +130,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture {
RoleDefinition = "Catalog creator";
Credential = $Credential
}

Mock -CommandName Get-MgBetaRoleManagementEntitlementManagementRoleAssignment -MockWith {
return @{
AppScopeId = "/"
PrincipalId = 'xxxxx-xxxxx-xxxxx-xxxxx-xxxxx'
RoleDefinitionId = 'xxxxx-xxxxx-xxxxx-xxxxx-xxxxx'
DirectoryScopeId = ''
}
}
}
It 'Should return Values from the Get method' {
(Get-TargetResource @testParams).Ensure | Should -Be 'Present'
Expand All @@ -132,14 +147,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture {
$testParams = @{
Credential = $Credential
}
Mock -CommandName Get-MgBetaRoleManagementEntitlementManagementRoleAssignment -MockWith {
return @{
AppScopeId = "/"
PrincipalId = 'xxxxx-xxxxx-xxxxx-xxxxx-xxxxx'
RoleDefinitionId = 'xxxxx-xxxxx-xxxxx-xxxxx-xxxxx'
DirectoryScopeId = ''
}
}
}

It 'Should Reverse Engineer resource from the Export method' {
Expand Down
6 changes: 5 additions & 1 deletion Tests/Unit/Stubs/Microsoft365.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -3728,7 +3728,11 @@ function Get-MgBetaRoleManagementEntitlementManagementRoleAssignment

[Parameter()]
[Switch]
$All
$All,

[Parameter()]
[System.String]
$ExpandProperty
)
}
function Update-MgBetaEntitlementManagementSetting
Expand Down
Loading