Skip to content

Commit 7e9e26d

Browse files
Merge pull request #5585 from microsoft/Dev
Release 1.24.1218.1
2 parents 2130ad3 + 312f02a commit 7e9e26d

File tree

74 files changed

+7642
-95
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+7642
-95
lines changed

CHANGELOG.md

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,46 @@
11
# Change log for Microsoft365DSC
22

3-
# UNRELEASED
3+
# 1.24.1218.1
4+
5+
* AADApplication
6+
* Added support for Oauth2PermissionScopes.
7+
* Fixes comparison issue for permissions.
8+
* EXOTransportRule
9+
* Fixes issue extracting arrays in Get-TargetResource.
10+
* FIXES [#5575](https://github.com/microsoft/Microsoft365DSC/issues/5575)
11+
* TeamsMeetingPolicy
12+
* Adds support for additional Copilot setting value.
13+
* FIXES [#5573](https://github.com/microsoft/Microsoft365DSC/issues/5573)
14+
* FIXES [#5550](https://github.com/microsoft/Microsoft365DSC/issues/5550)
15+
* MISC
16+
* Fixed the Fabric web request to use basic parsing.
17+
* Reset only necessary authentication context.
18+
* M365DSCUtil
19+
* Update `Get-M365DSCWorkloadsListFromResourceNames` function for more input types.
20+
FIXES [#5525](https://github.com/microsoft/Microsoft365DSC/issues/5525)
21+
* DEPENDENCIES
22+
* Updated Microsoft.PowerApps.Administration.PowerShell to version 2.0.202.
23+
* Updated MSCloudLoginAssistant to version 1.1.31.
424

525
# 1.24.1211.1
626

727
* AADApplication
828
* Changed logic to remove all permissions when an empty array is specified.
929
FIXES [#5534](https://github.com/microsoft/Microsoft365DSC/issues/5534)
30+
* Changed logic to update AppRoles by first disabling the entry.
31+
FIXES [#5524](https://github.com/microsoft/Microsoft365DSC/issues/5524)
1032
* AADFeatureRolloutPolicy
1133
* Fixed policy retrieval
1234
FIXES [#5521](https://github.com/microsoft/Microsoft365DSC/issues/5521)
35+
* AADRoleEligibilityScheduleRequest
36+
* Changed logic to retrieve instance by Service Principal with custom role.
37+
FIXES [#5532](https://github.com/microsoft/Microsoft365DSC/issues/5532)
1338
* IntuneDeviceManagementAndroidDeviceOwnerEnrollmentProfile
1439
* Fixing issue with the way the QrCodeImage property was exported and handled.
1540
* IntuneFirewallPolicyWindows10
1641
* Fix export of properties that appear multiple times in subsections.
42+
* IntuneSecurityBaselineWindows10
43+
* Initial release.
1744
* M365DSCDRGUtil
1845
* Improve settings catalog handling for nested objects.
1946
* M365DSCResourceGenerator

Modules/Microsoft365DSC/DSCResources/MSFT_AADAccessReviewDefinition/MSFT_AADAccessReviewDefinition.psm1

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,11 @@ function Export-TargetResource
792792
}
793793
foreach ($config in $getValue)
794794
{
795+
if ($null -ne $Global:M365DSCExportResourceInstancesCount)
796+
{
797+
$Global:M365DSCExportResourceInstancesCount++
798+
}
799+
795800
$displayedKey = $config.Id
796801
if (-not [String]::IsNullOrEmpty($config.displayName))
797802
{

Modules/Microsoft365DSC/DSCResources/MSFT_AADAdministrativeUnit/MSFT_AADAdministrativeUnit.psm1

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,9 +1149,8 @@ function Export-TargetResource
11491149
$currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Members' -IsCIMArray $true
11501150
$currentDSCBlock = $currentDSCBlock.Replace("`",`"`r`n", '')
11511151
$currentDSCBlock = $currentDSCBlock.Replace(",`r`n", '').Replace("`");`r`n", ");`r`n")
1152-
$currentDSCBlock = $currentDSCBlock.Replace("Members = @(`"", 'Members = @(')
1153-
$currentDSCBlock = $currentDSCBlock.Replace("`$OrganizationName'", "' + `$OrganizationName")
11541152
}
1153+
11551154
$dscContent += $currentDSCBlock
11561155
Save-M365DSCPartialExport -Content $currentDSCBlock `
11571156
-FileName $Global:PartialExportFileName

Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1

Lines changed: 135 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,24 @@ function Get-TargetResource
275275
$complexPreAuthorizedApplications += $myPreAuthorizedApplications
276276
}
277277
}
278+
279+
$complexOAuth2Scopes = @()
280+
foreach ($currentOAuth2Scope in $AADApp.api.Oauth2PermissionScopes)
281+
{
282+
$complexOAuth2Scopes += @{
283+
adminConsentDescription = $currentOAuth2Scope.adminConsentDescription
284+
adminConsentDisplayName = $currentOAuth2Scope.adminConsentDisplayName
285+
id = $currentOAuth2Scope.id
286+
isEnabled = $currentOAuth2Scope.isEnabled
287+
type = $currentOAuth2Scope.type
288+
userConsentDescription = $currentOAuth2Scope.userConsentDescription
289+
userConsentDisplayName = $currentOAuth2Scope.userConsentDisplayName
290+
value = $currentOAuth2Scope.value
291+
}
292+
}
293+
278294
$complexApi.Add('PreAuthorizedApplications', $complexPreAuthorizedApplications)
295+
$complexApi.Add('Oauth2PermissionScopes', $complexOAuth2Scopes)
279296
if ($complexApi.values.Where({ $null -ne $_ }).Count -eq 0)
280297
{
281298
$complexApi = $null
@@ -736,18 +753,56 @@ function Set-TargetResource
736753
}
737754
$currentParameters.Remove('AvailableToOtherTenants') | Out-Null
738755
$currentParameters.Remove('PublicClient') | Out-Null
756+
$currentParameters.Remove('Verbose') | Out-Null
739757

740-
if ($currentParameters.KnownClientApplications)
758+
#region API
759+
$apiValue = @{}
760+
if ($currentParameters.Api.KnownClientApplications)
761+
{
762+
$apiValue.Add('KnownClientApplications', $currentParameters.Api.KnownClientApplications)
763+
}
764+
if ($currentParameters.Api.Oauth2PermissionScopes)
741765
{
742-
$apiValue = @{
743-
KnownClientApplications = $currentParameters.KnownClientApplications
766+
Write-Verbose -Message "Oauth2PermissionScopes specified and is not empty"
767+
$scopeValue = @()
768+
foreach ($scope in $currentParameters.Api.Oauth2PermissionScopes)
769+
{
770+
$scopeEntry = @{
771+
adminConsentDescription = $scope.adminConsentDescription
772+
adminConsentDisplayName = $scope.adminConsentDisplayName
773+
isEnabled = $scope.isEnabled
774+
type = $scope.type
775+
userConsentDescription = $scope.userConsentDescription
776+
userConsentDisplayName = $scope.userConsentDisplayName
777+
value = $scope.value
778+
}
779+
if (-not [System.String]::IsNullOrEmpty($scope.id))
780+
{
781+
Write-Verbose -Message "Adding existing scope id {$($scope.id)}"
782+
$scopeEntry.Add('id', $scope.id)
783+
}
784+
else
785+
{
786+
Write-Verbose -Message "Generating new scope id"
787+
$scopeEntry.Add('id', (New-Guid).ToString())
788+
}
789+
790+
$scopeValue += $scopeEntry
744791
}
745-
$currentParameters.Add('Api', $apiValue)
746-
$currentParameters.Remove('KnownClientApplications') | Out-Null
792+
$apiValue.Add('Oauth2PermissionScopes', $scopeValue)
793+
}
794+
$currentParameters.Remove('KnownClientApplications') | Out-Null
795+
#endregion
796+
797+
if ($currentParameters.ContainsKey('Api'))
798+
{
799+
Write-Verbose "Found existing API parameter. Updating with $(Convert-M365DscHashtableToString -Hashtable $apiValue)"
800+
$currentParameters.Api = $apiValue
747801
}
748802
else
749803
{
750-
$currentParameters.Remove('KnownClientApplications') | Out-Null
804+
Write-Verbose "Adding API parameter with $(Convert-M365DscHashtableToString -Hashtable $apiValue)"
805+
$currentParameters.Add('Api', $apiValue)
751806
}
752807

753808
if ($ReplyUrls -or $LogoutURL -or $Homepage)
@@ -774,7 +829,6 @@ function Set-TargetResource
774829
$currentParameters.Remove('Homepage') | Out-Null
775830
$currentParameters.Remove('OnPremisesPublishing') | Out-Null
776831

777-
778832
$keys = (([Hashtable]$currentParameters).clone()).Keys
779833
foreach ($key in $keys)
780834
{
@@ -859,6 +913,7 @@ function Set-TargetResource
859913
$currentParameters.Remove('ApplicationTemplateId') | Out-Null
860914
Write-Verbose -Message "Creating New AzureAD Application {$DisplayName} with values:`r`n$($currentParameters | Out-String)"
861915

916+
Write-Verbose -Message "Parameters with API: $(ConvertTo-Json $currentParameters -Depth 10)"
862917
$currentAADApp = New-MgApplication @currentParameters
863918
Write-Verbose -Message "Azure AD Application {$DisplayName} was successfully created"
864919
$needToUpdatePermissions = $true
@@ -888,6 +943,8 @@ function Set-TargetResource
888943
}
889944

890945
$currentParameters.Add('ApplicationId', $AppIdValue)
946+
$currentParameters.Remove('AppRoles') | Out-Null
947+
891948
Write-Verbose -Message "Updating existing AzureAD Application {$DisplayName} with values:`r`n$($currentParameters | Out-String)"
892949
Update-MgApplication @currentParameters
893950

@@ -898,6 +955,62 @@ function Set-TargetResource
898955
$needToUpdatePermissions = $true
899956
$needToUpdateAuthenticationBehaviors = $true
900957
$needToUpdateKeyCredentials = $true
958+
959+
# Update AppRoles
960+
if ($null -ne $AppRoles)
961+
{
962+
Write-Verbose -Message "AppRoles were specified."
963+
964+
# Find roles to Remove
965+
$fixedRoles = @()
966+
$rolesToRemove = @()
967+
foreach ($currentRole in $currentAADApp.AppRoles)
968+
{
969+
$associatedDesiredRoleEntry = $AppRoles | Where-Object -FilterScript {$_.DisplayName -eq $currentRole.DisplayName}
970+
if ($null -eq $associatedDesiredRoleEntry)
971+
{
972+
Write-Verbose -Message "Could not find matching AppRole entry in Desired values for {$($currentRole.DisplayName)}. Will remove role."
973+
$fixedRole = $currentRole
974+
$fixedRole.IsEnabled = $false
975+
$fixedRoles += $fixedRole
976+
$rolesToRemove += $currentRole.DisplayName
977+
}
978+
else
979+
{
980+
Write-Verbose -Message "Found matching AppRole entry in Desired values for {$($currentRole.DisplayName)}. Keeping same value as current, but setting to disable."
981+
$entry = @{
982+
AllowedMemberTypes = $currentRole.AllowedMemberTypes
983+
Id = $currentRole.Id
984+
IsEnabled = $false
985+
Origin = $currentRole.Origin
986+
Value = $currentRole.Value
987+
DisplayName = $currentRole.DisplayName
988+
Description = $currentRole.Description
989+
}
990+
$fixedRoles += $entry
991+
}
992+
}
993+
994+
Write-Verbose -Message "Updating AppRoles with the disabled roles to remove: {$($rolesToRemove -join ',')}"
995+
Update-MgApplication -ApplicationId $currentAADApp.ObjectId -AppRoles $fixedRoles
996+
997+
Write-Verbose -Message "Updating the app a second time, this time removing the app roles {$($rolesToRemove -join ',')} and updating the others."
998+
$resultingAppRoles = @()
999+
foreach ($currentAppRole in $AppRoles)
1000+
{
1001+
$entry = @{
1002+
AllowedMemberTypes = $currentAppRole.AllowedMemberTypes
1003+
Id = $currentAppRole.Id
1004+
IsEnabled = $currentAppRole.IsEnabled
1005+
Origin = $currentAppRole.Origin
1006+
Value = $currentAppRole.Value
1007+
DisplayName = $currentAppRole.DisplayName
1008+
Description = $currentAppRole.Description
1009+
}
1010+
$resultingAppRoles += $entry
1011+
}
1012+
Update-MgApplication -ApplicationId $currentAADApp.ObjectId -AppRoles $resultingAppRoles
1013+
}
9011014
}
9021015
# App exists but should not
9031016
elseif ($Ensure -eq 'Absent' -and $currentAADApp.Ensure -eq 'Present')
@@ -985,7 +1098,7 @@ function Set-TargetResource
9851098
$allRequiredAccess = @()
9861099
}
9871100
else
988-
{
1101+
{
9891102
$allSourceAPIs = $Permissions.SourceAPI | Select-Object -Unique
9901103
$allRequiredAccess = @()
9911104

@@ -1039,6 +1152,10 @@ function Set-TargetResource
10391152
{
10401153
$roleId = $role.Id
10411154
}
1155+
if ([System.String]::IsNullOrEmpty($roleId))
1156+
{
1157+
throw "Could not find associated role {$($permission.Name)} for API {$($sourceAPI)}"
1158+
}
10421159
$appPermission = @{
10431160
Id = $roleId
10441161
Type = 'Role'
@@ -1054,6 +1171,7 @@ function Set-TargetResource
10541171
}
10551172

10561173
Write-Verbose -Message "Updating permissions for Azure AD Application {$($currentAADApp.DisplayName)} with RequiredResourceAccess:`r`n$($allRequiredAccess | Out-String)"
1174+
Write-Verbose -Message "ResourceAccess:`r`n$($allRequiredAccess.ResourceAccess | Out-String)"
10571175
Write-Verbose -Message "Current App Id: $($currentAADApp.AppId)"
10581176

10591177
# Even if the property is named ApplicationId, we need to pass in the ObjectId
@@ -1072,7 +1190,8 @@ function Set-TargetResource
10721190
requireClientServicePrincipal = $AuthenticationBehaviors.requireClientServicePrincipal
10731191
}
10741192

1075-
Update-MgBetaApplication -ApplicationId $currentAADApp.Id -AuthenticationBehaviors $IAuthenticationBehaviors | Out-Null
1193+
Update-MgBetaApplication -ApplicationId $currentAADApp.Id `
1194+
-AuthenticationBehaviors $IAuthenticationBehaviors | Out-Null
10761195
}
10771196

10781197
if ($needToUpdateKeyCredentials -and $KeyCredentials)
@@ -1307,8 +1426,8 @@ function Test-TargetResource
13071426

13081427
$CurrentValues = Get-TargetResource @PSBoundParameters
13091428

1310-
if ($CurrentValues.Permissions.Length -gt 0 -and `
1311-
$null -ne $CurrentValues.Permissions.Name)
1429+
if ($CurrentValues.Permissions.Length -gt 0 -and $null -ne $CurrentValues.Permissions.Name -and `
1430+
$null -ne $Permissions)
13121431
{
13131432
$differenceObject = $Permissions.Name
13141433
if ($null -eq $differenceObject)
@@ -1506,6 +1625,11 @@ function Export-TargetResource
15061625
CimInstanceName = 'MicrosoftGraphPreAuthorizedApplication'
15071626
IsRequired = $False
15081627
}
1628+
@{
1629+
Name = 'Oauth2PermissionScopes'
1630+
CimInstanceName = 'MSFT_MicrosoftGraphApiOauth2PermissionScopes'
1631+
IsRequired = $False
1632+
}
15091633
)
15101634
$complexTypeStringResult = Get-M365DSCDRGComplexTypeToString `
15111635
-ComplexObject $Results.Api `

Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,26 @@ class MSFT_MicrosoftGraphPreAuthorizedApplication
8282
[Write, Description("The unique identifier for the scopes the client application is granted.")] String PermissionIds[];
8383
};
8484

85+
[ClassVersion("1.0.0")]
86+
class MSFT_MicrosoftGraphApiOauth2PermissionScopes
87+
{
88+
[Write, Description("A description of the delegated permissions, intended to be read by an administrator granting the permission on behalf of all users. This text appears in tenant-wide admin consent experiences.")] String adminConsentDescription;
89+
[Write, Description("The permission's title, intended to be read by an administrator granting the permission on behalf of all users.")] String adminConsentDisplayName;
90+
[Write, Description("A description of the delegated permissions, intended to be read by a user granting the permission on their own behalf. This text appears in consent experiences where the user is consenting only on behalf of themselves.")] String userConsentDescription;
91+
[Write, Description("A title for the permission, intended to be read by a user granting the permission on their own behalf. This text appears in consent experiences where the user is consenting only on behalf of themselves.")] String userConsentDisplayName;
92+
[Write, Description("Specifies the value to include in the scp (scope) claim in access tokens. Must not exceed 120 characters in length.")] String value;
93+
[Write, Description("When you create or update a permission, this property must be set to true (which is the default). To delete a permission, this property must first be set to false. At that point, in a subsequent call, the permission may be removed.")] Boolean isEnabled;
94+
[Write, Description("The possible values are: User and Admin. Specifies whether this delegated permission should be considered safe for non-admin users to consent to on behalf of themselves, or whether an administrator consent should always be required.")] String type;
95+
[Write, Description("Unique delegated permission identifier inside the collection of delegated permissions defined for a resource application.")] String id;
96+
97+
};
98+
8599
[ClassVersion("1.0.0")]
86100
class MSFT_MicrosoftGraphApiApplication
87101
{
88102
[Write, Description("Lists the client applications that are preauthorized with the specified delegated permissions to access this application's APIs. Users aren't required to consent to any preauthorized application (for the permissions specified). However, any other permissions not listed in preAuthorizedApplications (requested through incremental consent for example) will require user consent."), EmbeddedInstance("MSFT_MicrosoftGraphPreAuthorizedApplication")] String PreAuthorizedApplications[];
103+
[Write, Description("List of associated API scopes."), EmbeddedInstance("MSFT_MicrosoftGraphAPIOauth2PermissionScopes")] String Oauth2PermissionScopes[];
104+
89105
};
90106

91107
[ClassVersion("1.0.0")]

Modules/Microsoft365DSC/DSCResources/MSFT_AADRoleAssignmentScheduleRequest/MSFT_AADRoleAssignmentScheduleRequest.psm1

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,24 @@ function Get-TargetResource
148148
[Array] $requests = Get-MgBetaRoleManagementDirectoryRoleAssignmentScheduleRequest -Filter "PrincipalId eq '$($PrincipalInstance.Id)' and RoleDefinitionId eq '$($RoleDefinitionId)' and DirectoryScopeId eq '$($DirectoryScopeId)'"
149149
if ($requests.Length -eq 0)
150150
{
151-
return $nullResult
151+
Write-Verbose -Message "Trying to retrieve by reverse RoleId retrieval"
152+
$partialRequests = Get-MgBetaRoleManagementDirectoryRoleAssignmentScheduleRequest -Filter "PrincipalId eq '$($PrincipalInstance.Id)' and DirectoryScopeId eq '$($DirectoryScopeId)'"
153+
$reverseRoleId = $null
154+
foreach ($partialRequest in $partialRequests)
155+
{
156+
$roleEntry = Get-MgBetaRoleManagementDirectoryRoleDefinition -UnifiedRoleDefinitionId $partialRequest.RoleDefinitionId | Where-Object -FilterScript {$_.DisplayName -eq $RoleDefinition}
157+
if ($null -ne $roleEntry)
158+
{
159+
$request = $partialRequest
160+
$RoleDefinitionId = $partialRequest.RoleDefinitionId
161+
break
162+
}
163+
}
164+
}
165+
else
166+
{
167+
$request = $requests[0]
152168
}
153-
154-
$request = $requests[0]
155169
}
156170

157171
$schedules = Get-MgBetaRoleManagementDirectoryRoleAssignmentSchedule -Filter "PrincipalId eq '$($request.PrincipalId)'"

Modules/Microsoft365DSC/DSCResources/MSFT_AADRoleEligibilityScheduleRequest/MSFT_AADRoleEligibilityScheduleRequest.psm1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@
138138
$PrincipalValue = $PrincipalInstance.DisplayName
139139
}
140140

141-
Write-Verbose -Message 'Found Principal'
141+
Write-Verbose -Message "Found Principal {$PrincipalValue}"
142142
$RoleDefinitionId = (Get-MgBetaRoleManagementDirectoryRoleDefinition -Filter "DisplayName eq '$RoleDefinition'").Id
143143
Write-Verbose -Message "Retrieved role definition {$RoleDefinition} with ID {$RoleDefinitionId}"
144144

Modules/Microsoft365DSC/DSCResources/MSFT_EXOManagementRoleAssignment/MSFT_EXOManagementRoleAssignment.psm1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ function Set-TargetResource
387387
Write-Verbose -Message 'Waiting for 20 seconds for new permissions to be effective.'
388388
Start-Sleep 20
389389
Write-Verbose -Message 'Disconnecting from Exchange Online'
390-
Reset-MSCloudLoginConnectionProfileContext
390+
Reset-MSCloudLoginConnectionProfileContext -Workload ExchangeOnline
391391
}
392392
}
393393

0 commit comments

Comments
 (0)