From 88a2407af9216f818bee656455eb72c69e40c0d1 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 4 Jul 2024 13:38:35 -0400 Subject: [PATCH 001/252] Initial --- .../MSFT_AADDeviceRegistrationPolicy.psm1 | 393 ++++++++++++++++++ ...SFT_AADDeviceRegistrationPolicy.schema.mof | 15 + .../readme.md | 6 + .../settings.json | 34 ++ .../AADDeviceRegistrationPolicy/2-Update.ps1 | 28 ++ ...5DSC.AADDeviceRegistrationPolicy.Tests.ps1 | 153 +++++++ 6 files changed, 629 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/MSFT_AADDeviceRegistrationPolicy.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/MSFT_AADDeviceRegistrationPolicy.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADDeviceRegistrationPolicy/2-Update.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADDeviceRegistrationPolicy.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/MSFT_AADDeviceRegistrationPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/MSFT_AADDeviceRegistrationPolicy.psm1 new file mode 100644 index 0000000000..37b59b296c --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/MSFT_AADDeviceRegistrationPolicy.psm1 @@ -0,0 +1,393 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [ValidateSet('Yes')] + [System.String] + $IsSingleInstance, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [ValidateRange(1,500)] + [System.Int32] + $MaxAttributesPerSet = $null, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + try + { + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + + $getValue = Get-MgBetaPolicyDeviceRegistrationPolicy -ErrorAction Stop + + $AzureADAllowedToJoin = 'None' + $AzureADAllowedToJoinUsers = $null + $AzureADAllowedToJoinGroups = $null + if ($getValue.AzureADJoin.AllowedToJoin.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.allDeviceRegistrationMembership') + { + $AzureADAllowedToJoin = 'All' + } + elseif ($getValue.AzureADJoin.AllowedToJoin.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.enumeratedDeviceRegistrationMembership') + { + $AzureADAllowedToJoin = 'Selected' + + foreach ($userId in $getValue.AzureAdJoin.AllowedToJoin.AdditionalProperties.Users) + { + $userInfo = Get-MgUser -UserId $userId + $AzureADAllowedToJoinUsers += $userInfo.UserPrincipalName + } + + foreach ($groupId in $getValue.AzureAdJoin.AllowedToJoin.AdditionalProperties.Groups) + { + $groupInfo = Get-MgGroup -GroupId $groupId + $AzureADAllowedToJoinGroups += $groupInfo.DisplayName + } + } + + $MultiFactorAuthConfiguration = $false + if ($getValue.MultiFactorAuthConfiguration -eq 'required') + { + $MultiFactorAuthConfiguration = $true + } + + $results = @{ + IsSingleInstance = 'Yes' + AzureADAllowedToJoin = $AzureADAllowedToJoin + AzureADAllowedToJoinGroups = $AzureADAllowedToJoinGroups + UserDeviceQuota = $getValue.UserDeviceQuota + MultiFactorAuthConfiguration = $MultiFactorAuthConfiguration + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + Managedidentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + return [System.Collections.Hashtable] $results + } + catch + { + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [ValidateRange(1,500)] + [System.Int32] + $MaxAttributesPerSet = $null, + + [Parameter()] + [System.String] + [ValidateSet('Present')] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + $BoundParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + Write-Verbose -Message "Creating new Attribute Set with Id {$Id}" + New-MgBetaDirectoryAttributeSet @BoundParameters | Out-Null + } + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Updating the Attribute Set with Id {$($currentInstance.Id)}" + $BoundParameters.Add('AttributeSetId', $Id) + $BoundParameters.Remove('Id') | Out-Null + Update-MgBetaDirectoryAttributeSet @BoundParameters | Out-Null + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [ValidateRange(1,500)] + [System.Int32] + $MaxAttributesPerSet = $null, + + [Parameter()] + [System.String] + [ValidateSet('Present')] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + Write-Verbose -Message "Testing configuration of the Attribute Set with Id {$Id}" + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + $params = @{ + IsSingleInstance = 'Yes' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + Managedidentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + + $dscContent = $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + return $dscContent + } + catch + { + if ($_.ErrorDetails.Message -like "*Insufficient privileges*") + { + Write-Host "`r`n $($Global:M365DSCEmojiYellowCircle) Insufficient permissions or license to export Attribute Sets." + } + else + { + Write-Host $Global:M365DSCEmojiRedX + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + } + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/MSFT_AADDeviceRegistrationPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/MSFT_AADDeviceRegistrationPolicy.schema.mof new file mode 100644 index 0000000000..ee1dc25a51 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/MSFT_AADDeviceRegistrationPolicy.schema.mof @@ -0,0 +1,15 @@ +[ClassVersion("1.0.0.0"), FriendlyName("AADAttributeSet")] +class MSFT_AADAttributeSet : OMI_BaseResource +{ + [Key, Description("Identifier for the attribute set that is unique within a tenant. Can be up to 32 characters long and include Unicode characters. Cannot contain spaces or special characters. Cannot be changed later. Case insensitive")] String Id; + [Write, Description("Identifier for the attribute set that is unique within a tenant. Can be up to 32 characters long and include Unicode characters. Cannot contain spaces or special characters. Cannot be changed later. Case insensitive")] String Description; + [Write, Description("Maximum number of custom security attributes that can be defined in this attribute set. Default value is null. If not specified, the administrator can add up to the maximum of 500 active attributes per tenant. Can be changed later.")] UInt32 MaxAttributesPerSet; + [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] string Ensure; + [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Secret of the Azure Active Directory tenant used for authentication."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/readme.md new file mode 100644 index 0000000000..9637edfab0 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/readme.md @@ -0,0 +1,6 @@ + +# AADAttributeSet + +## Description + +Represents a group of related custom security attribute definitions. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/settings.json new file mode 100644 index 0000000000..227706211e --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/settings.json @@ -0,0 +1,34 @@ +{ + "resourceName": "AADAttributeSet", + "description": "Represents a group of related custom security attribute definitions.", + "roles": { + "read": [ + "Attribute Definition Reader" + ], + "update": [ + "Attribute Definition Administrator" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [ + ], + "update": [ + ] + }, + "application": { + "read": [ + { + "name": "CustomSecAttributeDefinition.Read.All" + } + ], + "update": [ + { + "name": "CustomSecAttributeDefinition.ReadWrite.All" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADDeviceRegistrationPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADDeviceRegistrationPolicy/2-Update.ps1 new file mode 100644 index 0000000000..52b8df2775 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADDeviceRegistrationPolicy/2-Update.ps1 @@ -0,0 +1,28 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param + ( + [Parameter(Mandatory = $true)] + [PSCredential] + $credsCredential + ) + + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + AADAttributeSet "AADAttributeSetTest" + { + Credential = $credsCredential; + Description = "Attribute set with 420 attributes"; + Ensure = "Present"; + Id = "TestAttributeSet"; + MaxAttributesPerSet = 300; # Updated Property + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADDeviceRegistrationPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADDeviceRegistrationPolicy.Tests.ps1 new file mode 100644 index 0000000000..39e93e112f --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADDeviceRegistrationPolicy.Tests.ps1 @@ -0,0 +1,153 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource "AADAttributeSet" -GenericStubModule $GenericStubPath +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName Update-MgBetaDirectoryAttributeSet -MockWith { + } + + Mock -CommandName Remove-MgBetaDirectoryAttributeSet -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + Context -Name "The instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + Description = "This is my super context test"; + MaxAttributesPerSet = 420; + Ensure = "Present"; + Id = "c3"; + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDirectoryAttributeSet -MockWith { + return $null + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + } + + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Description = "This is my super context test"; + MaxAttributesPerSet = 420; + Ensure = "Present"; + Id = "c3"; + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDirectoryAttributeSet -MockWith { + return @{ + Description = "This is my super context test"; + MaxAttributesPerSet = 420; + Id = "c3"; + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Description = "This is my super context test"; + MaxAttributesPerSet = 420; + Ensure = "Present"; + Id = "c3"; + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDirectoryAttributeSet -MockWith { + return @{ + Description = "This is my super context test"; + MaxAttributesPerSet = 431; #drift + Ensure = "Present"; + Id = "c3"; + Credential = $Credential; + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Update-MgBetaDirectoryAttributeSet -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDirectoryAttributeSet -MockWith { + return @{ + Description = "This is my super context test"; + MaxAttributesPerSet = 420; + Id = "c3"; + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope From d608e6ea38a2cfbe7ba3db4c4a4c9e9b749f44f8 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 5 Jul 2024 10:14:38 -0400 Subject: [PATCH 002/252] Fixes --- .../MSFT_AADDeviceRegistrationPolicy.psm1 | 286 +++++++++++++++--- ...SFT_AADDeviceRegistrationPolicy.schema.mof | 19 +- .../readme.md | 4 +- .../settings.json | 4 +- 4 files changed, 255 insertions(+), 58 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/MSFT_AADDeviceRegistrationPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/MSFT_AADDeviceRegistrationPolicy.psm1 index 37b59b296c..807616920f 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/MSFT_AADDeviceRegistrationPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/MSFT_AADDeviceRegistrationPolicy.psm1 @@ -10,13 +10,46 @@ function Get-TargetResource $IsSingleInstance, [Parameter()] + [ValidateSet('All', 'Selected', 'None')] [System.String] - $Description, + $AzureADAllowedToJoin, [Parameter()] - [ValidateRange(1,500)] - [System.Int32] - $MaxAttributesPerSet = $null, + [System.String[]] + $AzureADAllowedToJoinUsers, + + [Parameter()] + [System.String[]] + $AzureADAllowedToJoinGroups, + + [Parameter()] + [System.Boolean] + $MultiFactorAuthConfiguration, + + [Parameter()] + [System.Boolean] + $LocalAdminsEnableGlobalAdmins, + + [Parameter()] + [System.Boolean] + $LocalAdminPasswordIsEnabled, + + [Parameter()] + [ValidateSet('All', 'Selected', 'None')] + [System.String] + $AzureAdJoinLocalAdminsRegisteringMode, + + [Parameter()] + [System.String[]] + $AzureAdJoinLocalAdminsRegisteringGroups, + + [Parameter()] + [System.String[]] + $AzureAdJoinLocalAdminsRegisteringUsers, + + [Parameter()] + [System.UInt32] + $UserDeviceQuota, [Parameter()] [System.Management.Automation.PSCredential] @@ -64,13 +97,11 @@ function Get-TargetResource Add-M365DSCTelemetryEvent -Data $data #endregion - $nullResult = $PSBoundParameters - $getValue = Get-MgBetaPolicyDeviceRegistrationPolicy -ErrorAction Stop $AzureADAllowedToJoin = 'None' - $AzureADAllowedToJoinUsers = $null - $AzureADAllowedToJoinGroups = $null + $AzureADAllowedToJoinUsers = @() + $AzureADAllowedToJoinGroups = @() if ($getValue.AzureADJoin.AllowedToJoin.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.allDeviceRegistrationMembership') { $AzureADAllowedToJoin = 'All' @@ -79,38 +110,72 @@ function Get-TargetResource { $AzureADAllowedToJoin = 'Selected' - foreach ($userId in $getValue.AzureAdJoin.AllowedToJoin.AdditionalProperties.Users) + foreach ($userId in $getValue.AzureAdJoin.AllowedToJoin.AdditionalProperties.users) { $userInfo = Get-MgUser -UserId $userId $AzureADAllowedToJoinUsers += $userInfo.UserPrincipalName } - foreach ($groupId in $getValue.AzureAdJoin.AllowedToJoin.AdditionalProperties.Groups) + foreach ($groupId in $getValue.AzureAdJoin.AllowedToJoin.AdditionalProperties.groups) { $groupInfo = Get-MgGroup -GroupId $groupId $AzureADAllowedToJoinGroups += $groupInfo.DisplayName } } + $AzureAdJoinLocalAdminsRegisteringUsers = @() + $AzureAdJoinLocalAdminsRegisteringGroups = @() + $AzureAdJoinLocalAdminsRegisteringMode = 'All' + + if ($getValue.AzureAdJoin.LocalAdmins.RegisteringUsers.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.noDeviceRegistrationMembership') + { + $AzureAdJoinLocalAdminsRegisteringMode = 'None' + } + elseif ($getValue.AzureAdJoin.LocalAdmins.RegisteringUsers.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.enumeratedDeviceRegistrationMembership') + { + $AzureAdJoinLocalAdminsRegisteringMode = 'Selected' + foreach ($userId in $getValue.AzureAdJoin.LocalAdmins.RegisteringUsers.AdditionalProperties.users) + { + $userInfo = Get-MgUser -UserId $userId + $AzureAdJoinLocalAdminsRegisteringUsers += $userInfo.UserPrincipalName + } + + foreach ($groupId in $getValue.AzureAdJoin.LocalAdmins.RegisteringUsers.AdditionalProperties.groups) + { + $groupInfo = Get-MgGroup -GroupId $groupId + $AzureAdJoinLocalAdminsRegisteringGroups += $groupInfo.DisplayName + } + } + $MultiFactorAuthConfiguration = $false if ($getValue.MultiFactorAuthConfiguration -eq 'required') { $MultiFactorAuthConfiguration = $true } - + $LocalAdminsEnableGlobalAdmins = $true + if (-not $getValue.AzureAdJoin.LocalAdmins.EnableGlobalAdmins) + { + $LocalAdminsEnableGlobalAdmins = $false + } $results = @{ - IsSingleInstance = 'Yes' - AzureADAllowedToJoin = $AzureADAllowedToJoin - AzureADAllowedToJoinGroups = $AzureADAllowedToJoinGroups - UserDeviceQuota = $getValue.UserDeviceQuota - MultiFactorAuthConfiguration = $MultiFactorAuthConfiguration - Credential = $Credential - ApplicationId = $ApplicationId - TenantId = $TenantId - ApplicationSecret = $ApplicationSecret - CertificateThumbprint = $CertificateThumbprint - Managedidentity = $ManagedIdentity.IsPresent - AccessTokens = $AccessTokens + IsSingleInstance = 'Yes' + AzureADAllowedToJoin = $AzureADAllowedToJoin + AzureADAllowedToJoinGroups = $AzureADAllowedToJoinGroups + AzureADAllowedToJoinUsers = $AzureADAllowedToJoinUsers + UserDeviceQuota = $getValue.UserDeviceQuota + MultiFactorAuthConfiguration = $MultiFactorAuthConfiguration + LocalAdminsEnableGlobalAdmins = $LocalAdminsEnableGlobalAdmins + LocalAdminPasswordIsEnabled = [Boolean]$getValue.LocalAdminPassword.IsEnabled + AzureAdJoinLocalAdminsRegisteringMode = $AzureAdJoinLocalAdminsRegisteringMode + AzureAdJoinLocalAdminsRegisteringGroups = $AzureAdJoinLocalAdminsRegisteringGroups + AzureAdJoinLocalAdminsRegisteringUsers = $AzureAdJoinLocalAdminsRegisteringUsers + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + Managedidentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens } return [System.Collections.Hashtable] $results @@ -133,22 +198,51 @@ function Set-TargetResource param ( [Parameter(Mandatory = $true)] + [ValidateSet('Yes')] [System.String] - $Id, + $IsSingleInstance, [Parameter()] + [ValidateSet('All', 'Selected', 'None')] [System.String] - $Description, + $AzureADAllowedToJoin, [Parameter()] - [ValidateRange(1,500)] - [System.Int32] - $MaxAttributesPerSet = $null, + [System.String[]] + $AzureADAllowedToJoinUsers, + + [Parameter()] + [System.String[]] + $AzureADAllowedToJoinGroups, [Parameter()] + [System.Boolean] + $MultiFactorAuthConfiguration, + + [Parameter()] + [System.Boolean] + $LocalAdminsEnableGlobalAdmins, + + [Parameter()] + [System.Boolean] + $LocalAdminPasswordIsEnabled, + + [Parameter()] + [ValidateSet('All', 'Selected', 'None')] [System.String] - [ValidateSet('Present')] - $Ensure = 'Present', + $AzureAdJoinLocalAdminsRegisteringMode, + + [Parameter()] + [System.String[]] + $AzureAdJoinLocalAdminsRegisteringGroups, + + [Parameter()] + [System.String[]] + $AzureAdJoinLocalAdminsRegisteringUsers, + + [Parameter()] + [System.UInt32] + $UserDeviceQuota, [Parameter()] [System.Management.Automation.PSCredential] @@ -191,21 +285,84 @@ function Set-TargetResource Add-M365DSCTelemetryEvent -Data $data #endregion - $currentInstance = Get-TargetResource @PSBoundParameters - $BoundParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + $MultiFactorAuthConfigurationValue = "notRequired" + if ($MultiFactorAuthConfiguration) + { + $MultiFactorAuthConfigurationValue = 'required' + } + + $azureADRegistrationAllowedToRegister = "#microsoft.graph.noDeviceRegistrationMembership" + if ($AzureAdJoinLocalAdminsRegisteringMode -eq 'All') + { + $azureADRegistrationAllowedToRegister = "#microsoft.graph.allDeviceRegistrationMembership" + } + elseif ($AzureAdJoinLocalAdminsRegisteringMode -eq 'Selected') + { + $azureADRegistrationAllowedToRegister = "#microsoft.graph.enumeratedDeviceRegistrationMembership" + + $azureADRegistrationAllowedUsers = @() + foreach ($user in $AzureAdJoinLocalAdminsRegisteringUsers) + { + $userInfo = Get-MgUser -UserId $user + $azureADRegistrationAllowedUsers += $userInfo.Id + } + + $azureADRegistrationAllowedGroups = @() + foreach ($group in $AzureAdJoinLocalAdminsRegisteringGroups) + { + $groupInfo = Get-MgGroup -Filter "DisplayName eq '$group'" + $azureADRegistrationAllowedGroups += $groupInfo.Id + } + } - if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + $localAdminAllowedMode = "#microsoft.graph.noDeviceRegistrationMembership" + if ($AzureAdJoinLocalAdminsRegisteringMode -eq 'All') { - Write-Verbose -Message "Creating new Attribute Set with Id {$Id}" - New-MgBetaDirectoryAttributeSet @BoundParameters | Out-Null + $localAdminAllowedMode = "#microsoft.graph.allDeviceRegistrationMembership" } - elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + elseif ($AzureAdJoinLocalAdminsRegisteringMode -eq 'Selected') { - Write-Verbose -Message "Updating the Attribute Set with Id {$($currentInstance.Id)}" - $BoundParameters.Add('AttributeSetId', $Id) - $BoundParameters.Remove('Id') | Out-Null - Update-MgBetaDirectoryAttributeSet @BoundParameters | Out-Null + $localAdminAllowedMode = "#microsoft.graph.enumeratedDeviceRegistrationMembership" + + $localAdminAllowedUsers = @() + foreach ($user in $AzureAdJoinLocalAdminsRegisteringUsers) + { + $userInfo = Get-MgUser -UserId $user + $localAdminAllowedUsers += $userInfo.Id + } + + $localAdminAllowedGroups = @() + foreach ($group in $AzureAdJoinLocalAdminsRegisteringGroups) + { + $groupInfo = Get-MgGroup -Filter "DisplayName eq '$group'" + $localAdminAllowedGroups += $groupInfo.Id + } + } + + $updateParameters = @{ + userDeviceQuota = $UserDeviceQuota + multiFactorAuthConfiguration = $MultiFactorAuthConfigurationValue + azureADJoin = @{ + allowedToJoin = @{ + '@odata.type' = $AzureADAllowedToJoin + users = $AzureADAllowedToJoinUsers + groups = $AzureADAllowedToJoinGroups + } + localAdmins = @{ + enableGlobalAdmins = $LocalAdminsEnableGlobalAdmins + registeringUsers = @{ + '@odata.type' = $localAdminAllowedMode + users = $localAdminAllowedUsers + groups = $localAdminAllowedGroups + } + } + } + localAdminPasswordSettings = @{ + isEnabled = $LocalAdminPasswordIsEnabled + } } + $uri = $Global:MSCloudLoginConnectionProfile.MicrosoftGraph.ResourceUrl + 'beta/policies/deviceRegistrationPolicy' + Invoke-MgGraphRequest -Method PUT -Uri $uri -Body $updateParameters } function Test-TargetResource @@ -215,22 +372,51 @@ function Test-TargetResource param ( [Parameter(Mandatory = $true)] + [ValidateSet('Yes')] [System.String] - $Id, + $IsSingleInstance, [Parameter()] + [ValidateSet('All', 'Selected', 'None')] [System.String] - $Description, + $AzureADAllowedToJoin, + + [Parameter()] + [System.String[]] + $AzureADAllowedToJoinUsers, + + [Parameter()] + [System.String[]] + $AzureADAllowedToJoinGroups, + + [Parameter()] + [System.Boolean] + $MultiFactorAuthConfiguration, + + [Parameter()] + [System.Boolean] + $LocalAdminsEnableGlobalAdmins, [Parameter()] - [ValidateRange(1,500)] - [System.Int32] - $MaxAttributesPerSet = $null, + [System.Boolean] + $LocalAdminPasswordIsEnabled, [Parameter()] + [ValidateSet('All', 'Selected', 'None')] [System.String] - [ValidateSet('Present')] - $Ensure = 'Present', + $AzureAdJoinLocalAdminsRegisteringMode, + + [Parameter()] + [System.String[]] + $AzureAdJoinLocalAdminsRegisteringGroups, + + [Parameter()] + [System.String[]] + $AzureAdJoinLocalAdminsRegisteringUsers, + + [Parameter()] + [System.UInt32] + $UserDeviceQuota, [Parameter()] [System.Management.Automation.PSCredential] @@ -273,7 +459,7 @@ function Test-TargetResource Add-M365DSCTelemetryEvent -Data $data #endregion - Write-Verbose -Message "Testing configuration of the Attribute Set with Id {$Id}" + Write-Verbose -Message "Testing configuration of the Device Registration Policy" $CurrentValues = Get-TargetResource @PSBoundParameters $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() @@ -342,6 +528,10 @@ function Export-TargetResource try { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } $params = @{ IsSingleInstance = 'Yes' Credential = $Credential diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/MSFT_AADDeviceRegistrationPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/MSFT_AADDeviceRegistrationPolicy.schema.mof index ee1dc25a51..944ef367d8 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/MSFT_AADDeviceRegistrationPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/MSFT_AADDeviceRegistrationPolicy.schema.mof @@ -1,10 +1,17 @@ -[ClassVersion("1.0.0.0"), FriendlyName("AADAttributeSet")] -class MSFT_AADAttributeSet : OMI_BaseResource +[ClassVersion("1.0.0.0"), FriendlyName("AADDeviceRegistrationPolicy")] +class MSFT_AADDeviceRegistrationPolicy : OMI_BaseResource { - [Key, Description("Identifier for the attribute set that is unique within a tenant. Can be up to 32 characters long and include Unicode characters. Cannot contain spaces or special characters. Cannot be changed later. Case insensitive")] String Id; - [Write, Description("Identifier for the attribute set that is unique within a tenant. Can be up to 32 characters long and include Unicode characters. Cannot contain spaces or special characters. Cannot be changed later. Case insensitive")] String Description; - [Write, Description("Maximum number of custom security attributes that can be defined in this attribute set. Default value is null. If not specified, the administrator can add up to the maximum of 500 active attributes per tenant. Can be changed later.")] UInt32 MaxAttributesPerSet; - [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] string Ensure; + [Key, Description("Only valid value is 'Yes'."), ValueMap{"Yes"}, Values{"Yes"}] String IsSingleInstance; + [Write, Description("Specifies the maximum number of devices that a user can have within your organization before blocking new device registrations. The default value is set to 50. If this property isn't specified during the policy update operation, it's automatically reset to 0 to indicate that users aren't allowed to join any devices.")] UInt32 UserDeviceQuota; + [Write, Description("Scope that a device registration policy applies to."), ValueMap{"All", "Selected", "None"}, Values{"All", "Selected", "None"}] String AzureADAllowedToJoin; + [Write, Description("List of users that this policy applies to.")] String AzureADAllowedToJoinUsers[]; + [Write, Description("List of groups that this policy applies to.")] String AzureADAllowedToJoinGroups[]; + [Write, Description("Specifies the authentication policy for a user to complete registration using Microsoft Entra join or Microsoft Entra registered within your organization.")] Boolean MultiFactorAuthConfiguration; + [Write, Description("Indicates whether global administrators are local administrators on all Microsoft Entra-joined devices. This setting only applies to future registrations. Default is true.")] Boolean LocalAdminsEnableGlobalAdmins; + [Write, Description("Scope that a device registration policy applies to for local admins."), ValueMap{"All", "Selected", "None"}, Values{"All", "Selected", "None"}] String AzureAdJoinLocalAdminsRegisteringMode; + [Write, Description("List of groups that this policy applies to.")] String AzureAdJoinLocalAdminsRegisteringGroups[]; + [Write, Description("List of users that this policy applies to.")] String AzureAdJoinLocalAdminsRegisteringUsers[]; + [Write, Description("Specifies whether this policy scope is configurable by the admin. The default value is false. An admin can set it to true to enable Local Admin Password Solution (LAPS) within their organzation.")] Boolean LocalAdminPasswordIsEnabled; [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/readme.md index 9637edfab0..740e58881b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/readme.md @@ -1,6 +1,6 @@ -# AADAttributeSet +# AADDeviceRegistrationPolicy ## Description -Represents a group of related custom security attribute definitions. +Represents the policy scope that controls quota restrictions, additional authentication, and authorization policies to register device identities to your organization. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/settings.json index 227706211e..6cf3fe9eed 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/settings.json @@ -20,12 +20,12 @@ "application": { "read": [ { - "name": "CustomSecAttributeDefinition.Read.All" + "name": "Policy.Read.DeviceConfiguration" } ], "update": [ { - "name": "CustomSecAttributeDefinition.ReadWrite.All" + "name": "Policy.ReadWrite.DeviceConfiguration" } ] } From a29baef061a9ffede143ffd8dab3c74c836ec135 Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Thu, 5 Sep 2024 09:58:53 +0530 Subject: [PATCH 003/252] first commit --- .../MSFT_EXOMigrationEnpoint.psm1 | 425 ++++++++++++++++++ .../MSFT_EXOMigrationEnpoint.schema.mof | 13 + .../MSFT_EXOMigrationEnpoint/readme.md | 6 + .../MSFT_EXOMigrationEnpoint/settings.json | 32 ++ .../Resources/ResourceName/1-Create.ps1 | 26 ++ .../Resources/ResourceName/2-Update.ps1 | 26 ++ .../Resources/ResourceName/3-Remove.ps1 | 26 ++ .../Microsoft365DSC.ResourceName.Tests.ps1 | 176 ++++++++ 8 files changed, 730 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/MSFT_EXOMigrationEnpoint.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/MSFT_EXOMigrationEnpoint.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/ResourceName/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/ResourceName/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/ResourceName/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/MSFT_EXOMigrationEnpoint.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/MSFT_EXOMigrationEnpoint.psm1 new file mode 100644 index 0000000000..d81da06c27 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/MSFT_EXOMigrationEnpoint.psm1 @@ -0,0 +1,425 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.Boolean] + $AcceptUntrustedCertificates, + + [Parameter()] + [System.String] + $ApplicationID, + + [Parameter()] + [System.String] + $AppSecretKeyVaultUrl, + + [Parameter()] + [System.String] + $Authentication, + + [Parameter()] + [ValidateSet('Exchange Remote', 'Outlook Anywhere', 'Google Workspace', 'IMAP')] + [System.String] + $EndpointType, + + [Parameter()] + [System.String] + $ExchangeServer, + + [Parameter()] + [System.String] + $MailboxPermission, + + [Parameter()] + [System.String] + $MaxConcurrentIncrementalSyncs, + + [Parameter()] + [System.String] + $MaxConcurrentMigrations, + + [Parameter()] + [System.String] + $NspiServer, + + [Parameter()] + [System.String] + $Port, + + [Parameter()] + [System.String] + $RemoteServer, + + [Parameter()] + [System.String] + $RemoteTenant, + + [Parameter()] + [System.String] + $RpcProxyServer, + + [Parameter()] + [ValidateSet('None', 'Tls', 'Ssl')] + [System.String] + $Security, + + [Parameter()] + [System.String] + $SourceMailboxLegacyDN, + + [Parameter()] + [System.String] + $UseAutoDiscover, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + ##TODO - Add the list of Parameters + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + ##TODO - Replace the workload by the one associated to your resource + New-M365DSCConnection -Workload 'Workload' ` + -InboundParameters $PSBoundParameters | Out-Null + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + try + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + ##TODO - Replace the PrimaryKey in the Filter by the one for the resource + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.PrimaryKey -eq $PrimaryKey} + } + else + { + ##TODO - Replace the cmdlet by the one to retrieve a specific instance. + $instance = Get-cmdlet -PrimaryKey $PrimaryKey -ErrorAction Stop + } + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + ##TODO - Add the list of parameters to be returned + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] + [System.String] + $PrimaryKey, + + ##TODO - Add the list of Parameters + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + ##TODO - Replace by the New cmdlet for the resource + New-Cmdlet @SetParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + ##TODO - Replace by the Update/Set cmdlet for the resource + Set-cmdlet @SetParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + ##TODO - Replace by the Remove cmdlet for the resource + Remove-cmdlet @SetParameters + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] + [System.String] + $PrimaryKey, + + ##TODO - Add the list of Parameters + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + ##TODO - Replace workload + $ConnectionMode = New-M365DSCConnection -Workload 'Workload' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + $Script:ExportMode = $true + ##TODO - Replace Get-Cmdlet by the cmdlet to retrieve all instances + [array] $Script:exportedInstances = Get-Cmdlet -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + $displayedKey = $config.Id + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + ##TODO - Specify the Primary Key + #PrimaryKey = $config.PrimaryKey + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/MSFT_EXOMigrationEnpoint.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/MSFT_EXOMigrationEnpoint.schema.mof new file mode 100644 index 0000000000..6fa43ce435 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/MSFT_EXOMigrationEnpoint.schema.mof @@ -0,0 +1,13 @@ +[ClassVersion("1.0.0.0"), FriendlyName("ResourceName")] +class MSFT_ResourceName : OMI_BaseResource +{ + [Key, Description("")] String PrimaryKey; + [Write, Description("")] String OtherProperties; + + [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; \ No newline at end of file diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/readme.md new file mode 100644 index 0000000000..32e0e7fb27 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/readme.md @@ -0,0 +1,6 @@ + +# ResourceName + +## Description + +##TODO - Provide a short description of what the resource is set to configure. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/settings.json new file mode 100644 index 0000000000..edf14b05e4 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName": "ResourceName", + "description": "Description of what the resource is about.", + "roles": { + "read": [ + "Role" + ], + "update": [ + "Role" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [ + { + "name": "Permission for Monitoring and Export" + } + ], + "update": [ + { + "name": "Permission for deploying" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ResourceName/1-Create.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/ResourceName/1-Create.ps1 @@ -0,0 +1,26 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ResourceName/2-Update.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/ResourceName/2-Update.ps1 @@ -0,0 +1,26 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ResourceName/3-Remove.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/ResourceName/3-Remove.ps1 @@ -0,0 +1,26 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 new file mode 100644 index 0000000000..20857e0393 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 @@ -0,0 +1,176 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -GenericStubModule $GenericStubPath + +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + ##TODO - Mock any Remove/Set/New cmdlets + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + Context -Name "The instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return $null + Mock -CommandName Get-Cmdlet -MockWith { + return $null + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should create a new instance from the Set method' { + ##TODO - Replace the New-Cmdlet by the appropriate one + Should -Invoke -CommandName New-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Absent' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should remove the instance from the Set method' { + ##TODO - Replace the Remove-Cmdlet by the appropriate one + Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return the desired values + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return a drift + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + ##TODO - Replace the Update-Cmdlet by the appropriate one + Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope From d281e09489669fcc07944e22ec1e65012a64deeb Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 19 Sep 2024 18:02:13 -0400 Subject: [PATCH 004/252] Initial --- .../MSFT_ADOPermissionGroupSettings.psm1 | 398 ++++++++++++++++++ ...MSFT_ADOPermissionGroupSettings.schema.mof | 14 + .../MSFT_ADOPermissionGroupSettings/readme.md | 6 + .../settings.json | 32 ++ .../ADOPermissionGroupSettings/2-Update.ps1 | 26 ++ ...65DSC.ADOPermissionGroupSettings.Tests.ps1 | 177 ++++++++ 6 files changed, 653 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/ADOPermissionGroupSettings/2-Update.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOPermissionGroupSettings.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.psm1 new file mode 100644 index 0000000000..d8ff5bdb19 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.psm1 @@ -0,0 +1,398 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] + [System.String] + $PrimaryKey, + + ##TODO - Add the list of Parameters + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'AzureDevOPS' ` + -InboundParameters $PSBoundParameters | Out-Null + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + try + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + if (-not [System.String]::IsNullOrEmpty($Descriptor)) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.descriptor -eq $Descriptor} + } + + if ($null -eq $instance) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.principalName -eq $PrincipalName} + } + } + else + { + $uri = "https://vssps.dev.azure.com/$OrganizationName/_apis/graph/groups?api-version=7.1-preview.1" + $allInstances = (Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri).value + if (-not [System.String]::IsNullOrEmpty($Descriptor)) + { + $instance = $allInstances | Where-Object -FilterScript {$_.descriptor -eq $Descriptor} + } + if ($null -eq $instance) + { + $instance = $allInstances | Where-Object -FilterScript {$_.principalName -eq $PrincipalName} + } + } + if ($null -eq $instance) + { + return $nullResult + } + + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/accesscontrollists/$($instance.originId)?api-version=7.1-preview.1" + $ace = Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri + + $results = @{ + ##TODO - Add the list of parameters to be returned + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] + [System.String] + $PrimaryKey, + + ##TODO - Add the list of Parameters + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + ##TODO - Replace by the New cmdlet for the resource + New-Cmdlet @SetParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + ##TODO - Replace by the Update/Set cmdlet for the resource + Set-cmdlet @SetParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + ##TODO - Replace by the Remove cmdlet for the resource + Remove-cmdlet @SetParameters + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] + [System.String] + $PrimaryKey, + + ##TODO - Add the list of Parameters + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + $ConnectionMode = New-M365DSCConnection -Workload 'AzureDevOPS' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + $Script:ExportMode = $true + $profile = Invoke-M365DSCAzureDevOPSWebRequest -Uri 'https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=5.1' + $accounts = Invoke-M365DSCAzureDevOPSWebRequest -Uri "https://app.vssps.visualstudio.com/_apis/accounts?api-version=7.1-preview.1&memberId=$($profile.id)" + + $i = 1 + $dscContent = '' + if ($accounts.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($account in $accounts) + { + $organization = 'O365DSC-Dev'#$account.Value.accountName + $uri = "https://vssps.dev.azure.com/$organization/_apis/graph/groups?api-version=7.1-preview.1" + [array] $Script:exportedInstances = (Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri).Value + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + $displayedKey = $config.principalName + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + OrganizationName = $Organization + PrincipalName = $config.principalName + Descriptor = $config.descriptor + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.schema.mof new file mode 100644 index 0000000000..be6b06c877 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.schema.mof @@ -0,0 +1,14 @@ +[ClassVersion("1.0.0.0"), FriendlyName("ResourceName")] +class MSFT_ResourceName : OMI_BaseResource +{ + [Key, Description("")] String PrimaryKey; + [Write, Description("")] String OtherProperties; + + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] string Ensure; + [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/readme.md new file mode 100644 index 0000000000..32e0e7fb27 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/readme.md @@ -0,0 +1,6 @@ + +# ResourceName + +## Description + +##TODO - Provide a short description of what the resource is set to configure. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/settings.json new file mode 100644 index 0000000000..edf14b05e4 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName": "ResourceName", + "description": "Description of what the resource is about.", + "roles": { + "read": [ + "Role" + ], + "update": [ + "Role" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [ + { + "name": "Permission for Monitoring and Export" + } + ], + "update": [ + { + "name": "Permission for deploying" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ADOPermissionGroupSettings/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ADOPermissionGroupSettings/2-Update.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/ADOPermissionGroupSettings/2-Update.ps1 @@ -0,0 +1,26 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOPermissionGroupSettings.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOPermissionGroupSettings.Tests.ps1 new file mode 100644 index 0000000000..f3ddc7d594 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOPermissionGroupSettings.Tests.ps1 @@ -0,0 +1,177 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -GenericStubModule $GenericStubPath + +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + ##TODO - Mock any Remove/Set/New cmdlets + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + Context -Name "The instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return $null + Mock -CommandName Get-Cmdlet -MockWith { + return $null + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should create a new instance from the Set method' { + ##TODO - Replace the New-Cmdlet by the appropriate one + Set-TargetResource @testParams + Should -Invoke -CommandName New-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Absent' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should remove the instance from the Set method' { + ##TODO - Replace the Remove-Cmdlet by the appropriate one + Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return the desired values + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return a drift + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + ##TODO - Replace the Update-Cmdlet by the appropriate one + Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope From 6977699c858e8a75885acd9a9ac5e62f6ae7c851 Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Fri, 20 Sep 2024 16:21:48 +0200 Subject: [PATCH 005/252] Add Intune ASR App and Browser Isolation Policy for Windows10 --- CHANGELOG.md | 3 + ...AppAndBrowserIsolationPolicyWindows10.psm1 | 855 ++++++++++++++++++ ...BrowserIsolationPolicyWindows10.schema.mof | 48 + .../readme.md | 6 + .../settings.json | 33 + .../1-Create.ps1 | 51 ++ .../2-Update.ps1 | 51 ++ .../3-Remove.ps1 | 34 + ...dBrowserIsolationPolicyWindows10.Tests.ps1 | 347 +++++++ 9 files changed, 1428 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppAndBrowserIsolationPolicyWindows10/MSFT_IntuneAppAndBrowserIsolationPolicyWindows10.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppAndBrowserIsolationPolicyWindows10/MSFT_IntuneAppAndBrowserIsolationPolicyWindows10.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppAndBrowserIsolationPolicyWindows10/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppAndBrowserIsolationPolicyWindows10/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneAppAndBrowserIsolationPolicyWindows10/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneAppAndBrowserIsolationPolicyWindows10/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneAppAndBrowserIsolationPolicyWindows10/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppAndBrowserIsolationPolicyWindows10.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index ea8a75523f..c89ae2a9f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,9 @@ * IntuneAntivirusPolicyWindows10SettingCatalog * Fixes an issue with invalid parameter definition. FIXES [#5015](https://github.com/microsoft/Microsoft365DSC/issues/5015) +* IntuneAppAndBrowserIsolationPolicyWindows10 + * Initial release. + FIXES [#3028](https://github.com/microsoft/Microsoft365DSC/issues/3028) * IntuneDeviceCompliancePolicyWindows10 * Fixes an issue where the property `ValidOperatingSystemBuildRanges` was not exported properly. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppAndBrowserIsolationPolicyWindows10/MSFT_IntuneAppAndBrowserIsolationPolicyWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppAndBrowserIsolationPolicyWindows10/MSFT_IntuneAppAndBrowserIsolationPolicyWindows10.psm1 new file mode 100644 index 0000000000..01d7114e5a --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppAndBrowserIsolationPolicyWindows10/MSFT_IntuneAppAndBrowserIsolationPolicyWindows10.psm1 @@ -0,0 +1,855 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [ValidateSet('0', '1', '2', '3')] + [System.String] + $AllowWindowsDefenderApplicationGuard, + + [Parameter()] + [ValidateSet('0', '1', '2', '3')] + [System.String] + $ClipboardSettings, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $SaveFilesToHost, + + [Parameter()] + [ValidateSet('install')] + [System.String] + $InstallWindowsDefenderApplicationGuard, + + [Parameter()] + [ValidateSet('1', '2', '3')] + [System.String] + $ClipboardFileType, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $AllowPersistence, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $AllowVirtualGPU, + + [Parameter()] + [ValidateSet('0', '1', '2', '4', '8')] + [System.Int32[]] + $PrintingSettings, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $AllowCameraMicrophoneRedirection, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $AuditApplicationGuard, + + [Parameter()] + [System.String[]] + $CertificateThumbprints, + + [Parameter()] + [System.String[]] + $EnterpriseIPRange, + + [Parameter()] + [System.String[]] + $EnterpriseCloudResources, + + [Parameter()] + [System.String[]] + $EnterpriseNetworkDomainNames, + + [Parameter()] + [System.String[]] + $EnterpriseProxyServers, + + [Parameter()] + [System.String[]] + $EnterpriseInternalProxyServers, + + [Parameter()] + [System.String[]] + $NeutralResources, + + [Parameter()] + [ValidateSet('1', '0')] + [System.String] + $EnterpriseProxyServersAreAuthoritative, + + [Parameter()] + [ValidateSet('1', '0')] + [System.String] + $EnterpriseIPRangesAreAuthoritative, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + #endregion + + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + try + { + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + + $getValue = $null + #region resource generator code + $getValue = Get-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $Id -ErrorAction SilentlyContinue + + if ($null -eq $getValue) + { + Write-Verbose -Message "Could not find an Intune App And Browser Isolation Policy for Windows10 with Id {$Id}" + + if (-not [System.String]::IsNullOrEmpty($DisplayName)) + { + $getValue = Get-MgBetaDeviceManagementConfigurationPolicy ` + -Filter "Name eq '$DisplayName'" ` + -ErrorAction SilentlyContinue + } + } + #endregion + if ($null -eq $getValue) + { + Write-Verbose -Message "Could not find an Intune App And Browser Isolation Policy for Windows10 with Name {$DisplayName}." + return $nullResult + } + $Id = $getValue.Id + Write-Verbose -Message "An Intune App And Browser Isolation Policy for Windows10 with Id {$Id} and Name {$DisplayName} was found" + + # Retrieve policy specific settings + [array]$settings = Get-MgBetaDeviceManagementConfigurationPolicySetting ` + -DeviceManagementConfigurationPolicyId $Id ` + -ExpandProperty 'settingDefinitions' ` + -ErrorAction Stop + + $policySettings = @{} + $policySettings = Export-IntuneSettingCatalogPolicySettings -Settings $settings -ReturnHashtable $policySettings + + $results = @{ + #region resource generator code + Description = $getValue.Description + DisplayName = $getValue.Name + RoleScopeTagIds = $getValue.RoleScopeTagIds + Id = $getValue.Id + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + #endregion + } + $results += $policySettings + + $assignmentsValues = Get-MgBetaDeviceManagementConfigurationPolicyAssignment -DeviceManagementConfigurationPolicyId $Id + $assignmentResult = @() + if ($assignmentsValues.Count -gt 0) + { + $assignmentResult += ConvertFrom-IntunePolicyAssignment -Assignments $assignmentsValues -IncludeDeviceFilter $true + } + $results.Add('Assignments', $assignmentResult) + + return [System.Collections.Hashtable] $results + } + catch + { + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [ValidateSet('0', '1', '2', '3')] + [System.String] + $AllowWindowsDefenderApplicationGuard, + + [Parameter()] + [ValidateSet('0', '1', '2', '3')] + [System.String] + $ClipboardSettings, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $SaveFilesToHost, + + [Parameter()] + [ValidateSet('install')] + [System.String] + $InstallWindowsDefenderApplicationGuard, + + [Parameter()] + [ValidateSet('1', '2', '3')] + [System.String] + $ClipboardFileType, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $AllowPersistence, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $AllowVirtualGPU, + + [Parameter()] + [ValidateSet('0', '1', '2', '4', '8')] + [System.Int32[]] + $PrintingSettings, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $AllowCameraMicrophoneRedirection, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $AuditApplicationGuard, + + [Parameter()] + [System.String[]] + $CertificateThumbprints, + + [Parameter()] + [System.String[]] + $EnterpriseIPRange, + + [Parameter()] + [System.String[]] + $EnterpriseCloudResources, + + [Parameter()] + [System.String[]] + $EnterpriseNetworkDomainNames, + + [Parameter()] + [System.String[]] + $EnterpriseProxyServers, + + [Parameter()] + [System.String[]] + $EnterpriseInternalProxyServers, + + [Parameter()] + [System.String[]] + $NeutralResources, + + [Parameter()] + [ValidateSet('1', '0')] + [System.String] + $EnterpriseProxyServersAreAuthoritative, + + [Parameter()] + [ValidateSet('1', '0')] + [System.String] + $EnterpriseIPRangesAreAuthoritative, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + #endregion + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + + $BoundParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + $templateReferenceId = '9f667e40-8f3c-4f88-80d8-457f16906315_1' + $platforms = 'windows10' + $technologies = 'mdm' + + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + Write-Verbose -Message "Creating an Intune App And Browser Isolation Policy for Windows10 with Name {$DisplayName}" + $BoundParameters.Remove("Assignments") | Out-Null + + $settings = Get-IntuneSettingCatalogPolicySetting ` + -DSCParams ([System.Collections.Hashtable]$BoundParameters) ` + -TemplateId $templateReferenceId + + $createParameters = @{ + Name = $DisplayName + Description = $Description + TemplateReference = @{ templateId = $templateReferenceId } + Platforms = $platforms + Technologies = $technologies + Settings = $settings + } + + #region resource generator code + $policy = New-MgBetaDeviceManagementConfigurationPolicy -BodyParameter $createParameters + + if ($policy.Id) + { + $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + Update-DeviceConfigurationPolicyAssignment ` + -DeviceConfigurationPolicyId $policy.Id ` + -Targets $assignmentsHash ` + -Repository 'deviceManagement/configurationPolicies' + } + #endregion + } + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Updating the Intune App And Browser Isolation Policy for Windows10 with Id {$($currentInstance.Id)}" + $BoundParameters.Remove("Assignments") | Out-Null + + $settings = Get-IntuneSettingCatalogPolicySetting ` + -DSCParams ([System.Collections.Hashtable]$BoundParameters) ` + -TemplateId $templateReferenceId + + Update-IntuneDeviceConfigurationPolicy ` + -DeviceConfigurationPolicyId $currentInstance.Id ` + -Name $DisplayName ` + -Description $Description ` + -TemplateReferenceId $templateReferenceId ` + -Platforms $platforms ` + -Technologies $technologies ` + -Settings $settings + + #region resource generator code + $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + Update-DeviceConfigurationPolicyAssignment ` + -DeviceConfigurationPolicyId $currentInstance.Id ` + -Targets $assignmentsHash ` + -Repository 'deviceManagement/configurationPolicies' + #endregion + } + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Removing the Intune App And Browser Isolation Policy for Windows10 with Id {$($currentInstance.Id)}" + #region resource generator code + Remove-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $currentInstance.Id + #endregion + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [ValidateSet('0', '1', '2', '3')] + [System.String] + $AllowWindowsDefenderApplicationGuard, + + [Parameter()] + [ValidateSet('0', '1', '2', '3')] + [System.String] + $ClipboardSettings, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $SaveFilesToHost, + + [Parameter()] + [ValidateSet('install')] + [System.String] + $InstallWindowsDefenderApplicationGuard, + + [Parameter()] + [ValidateSet('1', '2', '3')] + [System.String] + $ClipboardFileType, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $AllowPersistence, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $AllowVirtualGPU, + + [Parameter()] + [ValidateSet('0', '1', '2', '4', '8')] + [System.Int32[]] + $PrintingSettings, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $AllowCameraMicrophoneRedirection, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $AuditApplicationGuard, + + [Parameter()] + [System.String[]] + $CertificateThumbprints, + + [Parameter()] + [System.String[]] + $EnterpriseIPRange, + + [Parameter()] + [System.String[]] + $EnterpriseCloudResources, + + [Parameter()] + [System.String[]] + $EnterpriseNetworkDomainNames, + + [Parameter()] + [System.String[]] + $EnterpriseProxyServers, + + [Parameter()] + [System.String[]] + $EnterpriseInternalProxyServers, + + [Parameter()] + [System.String[]] + $NeutralResources, + + [Parameter()] + [ValidateSet('1', '0')] + [System.String] + $EnterpriseProxyServersAreAuthoritative, + + [Parameter()] + [ValidateSet('1', '0')] + [System.String] + $EnterpriseIPRangesAreAuthoritative, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + #endregion + + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + Write-Verbose -Message "Testing configuration of the Intune App And Browser Isolation Policy for Windows10 with Id {$Id} and Name {$DisplayName}" + + $CurrentValues = Get-TargetResource @PSBoundParameters + [Hashtable]$ValuesToCheck = @{} + $MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object { + if ($_.Key -notlike '*Variable' -or $_.Key -notin @('Verbose', 'Debug', 'ErrorAction', 'WarningAction', 'InformationAction')) + { + if ($null -ne $CurrentValues[$_.Key] -or $null -ne $PSBoundParameters[$_.Key]) + { + $ValuesToCheck.Add($_.Key, $null) + if (-not $PSBoundParameters.ContainsKey($_.Key)) + { + $PSBoundParameters.Add($_.Key, $null) + } + } + } + } + + if ($CurrentValues.Ensure -ne $Ensure) + { + Write-Verbose -Message "Test-TargetResource returned $false" + return $false + } + $testResult = $true + + #Compare Cim instances + foreach ($key in $PSBoundParameters.Keys) + { + $source = $PSBoundParameters.$key + $target = $CurrentValues.$key + if ($null -ne $source -and $source.GetType().Name -like '*CimInstance*') + { + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + if (-not $testResult) + { + break + } + + $ValuesToCheck.Remove($key) | Out-Null + } + } + + $ValuesToCheck.Remove('Id') | Out-Null + $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + + if ($testResult) + { + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + } + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + #region resource generator code + $policyTemplateID = "9f667e40-8f3c-4f88-80d8-457f16906315_1" + [array]$getValue = Get-MgBetaDeviceManagementConfigurationPolicy ` + -Filter $Filter ` + -All ` + -ErrorAction Stop | Where-Object ` + -FilterScript { + $_.TemplateReference.TemplateId -eq $policyTemplateID + } + #endregion + + $i = 1 + $dscContent = '' + if ($getValue.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $getValue) + { + $displayedKey = $config.Id + if (-not [String]::IsNullOrEmpty($config.displayName)) + { + $displayedKey = $config.displayName + } + elseif (-not [string]::IsNullOrEmpty($config.name)) + { + $displayedKey = $config.name + } + Write-Host " |---[$i/$($getValue.Count)] $displayedKey" -NoNewline + $params = @{ + Id = $config.Id + DisplayName = $config.Name + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + if ($Results.Assignments) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString -ComplexObject $Results.Assignments -CIMInstanceName DeviceManagementConfigurationPolicyAssignments + if ($complexTypeStringResult) + { + $Results.Assignments = $complexTypeStringResult + } + else + { + $Results.Remove('Assignments') | Out-Null + } + } + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + + if ($Results.Assignments) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "Assignments" -IsCIMArray:$true + } + + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppAndBrowserIsolationPolicyWindows10/MSFT_IntuneAppAndBrowserIsolationPolicyWindows10.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppAndBrowserIsolationPolicyWindows10/MSFT_IntuneAppAndBrowserIsolationPolicyWindows10.schema.mof new file mode 100644 index 0000000000..834c947e27 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppAndBrowserIsolationPolicyWindows10/MSFT_IntuneAppAndBrowserIsolationPolicyWindows10.schema.mof @@ -0,0 +1,48 @@ +[ClassVersion("1.0.0.0")] +class MSFT_DeviceManagementConfigurationPolicyAssignments +{ + [Write, Description("The type of the target assignment."), ValueMap{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget","#microsoft.graph.configurationManagerCollectionAssignmentTarget"}, Values{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget","#microsoft.graph.configurationManagerCollectionAssignmentTarget"}] String dataType; + [Write, Description("The type of filter of the target assignment i.e. Exclude or Include. Possible values are:none, include, exclude."), ValueMap{"none","include","exclude"}, Values{"none","include","exclude"}] String deviceAndAppManagementAssignmentFilterType; + [Write, Description("The Id of the filter for the target assignment.")] String deviceAndAppManagementAssignmentFilterId; + [Write, Description("The group Id that is the target of the assignment.")] String groupId; + [Write, Description("The group Display Name that is the target of the assignment.")] String groupDisplayName; + [Write, Description("The collection Id that is the target of the assignment.(ConfigMgr)")] String collectionId; +}; + + +[ClassVersion("1.0.0.0"), FriendlyName("IntuneAppAndBrowserIsolationPolicyWindows10")] +class MSFT_IntuneAppAndBrowserIsolationPolicyWindows10 : OMI_BaseResource +{ + [Write, Description("Policy description")] String Description; + [Key, Description("Policy name")] String DisplayName; + [Write, Description("List of Scope Tags for this Entity instance.")] String RoleScopeTagIds[]; + [Write, Description("The unique identifier for an entity. Read-only.")] String Id; + [Write, Description("Turn on Microsoft Defender Application Guard (0: Disable Microsoft Defender Application Guard, 1: Enable Microsoft Defender Application Guard for Microsoft Edge ONLY, 2: Enable Microsoft Defender Application Guard for isolated Windows environments ONLY, 3: Enable Microsoft Defender Application Guard for Microsoft Edge AND isolated Windows environments)"), ValueMap{"0", "1", "2", "3"}, Values{"0", "1", "2", "3"}] String AllowWindowsDefenderApplicationGuard; + [Write, Description("Clipboard behavior settings (0: Completely turns Off the clipboard functionality for the Application Guard., 1: Turns On clipboard operation from an isolated session to the host., 2: Turns On clipboard operation from the host to an isolated session., 3: Turns On clipboard operation in both the directions.)"), ValueMap{"0", "1", "2", "3"}, Values{"0", "1", "2", "3"}] String ClipboardSettings; + [Write, Description("Allow files to download and save to the host operating system (0: The user cannot download files from Edge in the container to the host file system. When the policy is not configured, it is the same as disabled (0)., 1: Turns on the functionality to allow users to download files from Edge in the container to the host file system.)"), ValueMap{"0", "1"}, Values{"0", "1"}] String SaveFilesToHost; + [Write, Description("Install Windows defender application guard (install: Install)"), ValueMap{"install"}, Values{"install"}] String InstallWindowsDefenderApplicationGuard; + [Write, Description("Clipboard content options (1: Allow text copying., 2: Allow image copying., 3: Allow text and image copying.)"), ValueMap{"1", "2", "3"}, Values{"1", "2", "3"}] String ClipboardFileType; + [Write, Description("Allow data persistence (0: Application Guard discards user-downloaded files and other items (such as, cookies, Favorites, and so on) during machine restart or user log-off., 1: Application Guard saves user-downloaded files and other items (such as, cookies, Favorites, and so on) for use in future Application Guard sessions.)"), ValueMap{"0", "1"}, Values{"0", "1"}] String AllowPersistence; + [Write, Description("Allow hardware-accelerated rendering (0: Cannot access the vGPU and uses the CPU to support rendering graphics. When the policy is not configured, it is the same as disabled (0)., 1: Turns on the functionality to access the vGPU offloading graphics rendering from the CPU. This can create a faster experience when working with graphics intense websites or watching video within the container.)"), ValueMap{"0", "1"}, Values{"0", "1"}] String AllowVirtualGPU; + [Write, Description("Print Settings (0: Disables all print functionality., 1: Enables only XPS printing., 2: Enables only PDF printing., 4: Enables only local printing., 8: Enables only network printing.)"), ValueMap{"0", "1", "2", "4", "8"}, Values{"0", "1", "2", "4", "8"}] SInt32 PrintingSettings[]; + [Write, Description("Allow camera and microphone access (0: Microsoft Defender Application Guard cannot access the device's camera and microphone. When the policy is not configured, it is the same as disabled (0)., 1: Turns on the functionality to allow Microsoft Defender Application Guard to access the device's camera and microphone.)"), ValueMap{"0", "1"}, Values{"0", "1"}] String AllowCameraMicrophoneRedirection; + [Write, Description("Audit Application Guard (0: Audit event logs aren't collected for Application Guard., 1: Application Guard inherits its auditing policies from system and starts to audit security events for Application Guard container.)"), ValueMap{"0", "1"}, Values{"0", "1"}] String AuditApplicationGuard; + [Write, Description("Certificate Thumbprints")] String CertificateThumbprints[]; + [Write, Description("Enterprise IP Range")] String EnterpriseIPRange[]; + [Write, Description("Enterprise Cloud Resources")] String EnterpriseCloudResources[]; + [Write, Description("Enterprise Network Domain Names")] String EnterpriseNetworkDomainNames[]; + [Write, Description("Enterprise Proxy Servers")] String EnterpriseProxyServers[]; + [Write, Description("Enterprise Internal Proxy Servers")] String EnterpriseInternalProxyServers[]; + [Write, Description("Neutral Resources")] String NeutralResources[]; + [Write, Description("Enterprise Proxy Servers Are Authoritative (1: Enable, 0: Disable)"), ValueMap{"1", "0"}, Values{"1", "0"}] String EnterpriseProxyServersAreAuthoritative; + [Write, Description("Enterprise IP Ranges Are Authoritative (1: Enable, 0: Disable)"), ValueMap{"1", "0"}, Values{"1", "0"}] String EnterpriseIPRangesAreAuthoritative; + [Write, Description("Represents the assignment to the Intune policy."), EmbeddedInstance("MSFT_DeviceManagementConfigurationPolicyAssignments")] String Assignments[]; + [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; + [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Secret of the Azure Active Directory tenant used for authentication."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppAndBrowserIsolationPolicyWindows10/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppAndBrowserIsolationPolicyWindows10/readme.md new file mode 100644 index 0000000000..311864ce6b --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppAndBrowserIsolationPolicyWindows10/readme.md @@ -0,0 +1,6 @@ + +# IntuneAppAndBrowserIsolationPolicyWindows10 + +## Description + +Intune App And Browser Isolation Policy for Windows10 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppAndBrowserIsolationPolicyWindows10/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppAndBrowserIsolationPolicyWindows10/settings.json new file mode 100644 index 0000000000..fe0c097e79 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppAndBrowserIsolationPolicyWindows10/settings.json @@ -0,0 +1,33 @@ +{ + "resourceName": "IntuneAppAndBrowserIsolationPolicyWindows10", + "description": "This resource configures an Intune App And Browser Isolation Policy for Windows10.", + "permissions": { + "graph": { + "application": { + "read": [ + { + "name": "DeviceManagementConfiguration.Read.All" + } + ], + "update": [ + { + "name": "DeviceManagementConfiguration.ReadWrite.All" + } + ] + }, + "delegated": { + "read": [ + { + "name": "DeviceManagementConfiguration.Read.All" + } + ], + "update": [ + { + "name": "DeviceManagementConfiguration.ReadWrite.All" + } + ] + } + } +} + +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppAndBrowserIsolationPolicyWindows10/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppAndBrowserIsolationPolicyWindows10/1-Create.ps1 new file mode 100644 index 0000000000..b985c55712 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppAndBrowserIsolationPolicyWindows10/1-Create.ps1 @@ -0,0 +1,51 @@ +<# +This example creates a new Device Remediation. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneAppAndBrowserIsolationPolicyWindows10 'ConfigureAppAndBrowserIsolationPolicyWindows10' + { + Assignments = @( + MSFT_DeviceManagementConfigurationPolicyAssignments{ + deviceAndAppManagementAssignmentFilterType = 'none' + dataType = '#microsoft.graph.groupAssignmentTarget' + groupId = '11111111-1111-1111-1111-111111111111' + } + ); + AllowCameraMicrophoneRedirection = "1"; + AllowPersistence = "0"; + AllowVirtualGPU = "0"; + AllowWindowsDefenderApplicationGuard = "1"; + ClipboardFileType = "1"; + ClipboardSettings = "0"; + Description = 'Description' + DisplayName = "App and Browser Isolation"; + Ensure = "Present"; + Id = '00000000-0000-0000-0000-000000000000' + InstallWindowsDefenderApplicationGuard = "install"; + SaveFilesToHost = "0"; + RoleScopeTagIds = @("0"); + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppAndBrowserIsolationPolicyWindows10/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppAndBrowserIsolationPolicyWindows10/2-Update.ps1 new file mode 100644 index 0000000000..8f3133d7cf --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppAndBrowserIsolationPolicyWindows10/2-Update.ps1 @@ -0,0 +1,51 @@ +<# +This example updates a new Device Remediation. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneAppAndBrowserIsolationPolicyWindows10 'ConfigureAppAndBrowserIsolationPolicyWindows10' + { + Assignments = @( + MSFT_DeviceManagementConfigurationPolicyAssignments{ + deviceAndAppManagementAssignmentFilterType = 'none' + dataType = '#microsoft.graph.groupAssignmentTarget' + groupId = '11111111-1111-1111-1111-111111111111' + } + ); + AllowCameraMicrophoneRedirection = "0"; # Updated property + AllowPersistence = "0"; + AllowVirtualGPU = "0"; + AllowWindowsDefenderApplicationGuard = "1"; + ClipboardFileType = "1"; + ClipboardSettings = "0"; + Description = 'Description' + DisplayName = "App and Browser Isolation"; + Ensure = "Present"; + Id = '00000000-0000-0000-0000-000000000000' + InstallWindowsDefenderApplicationGuard = "install"; + SaveFilesToHost = "0"; + RoleScopeTagIds = @("0"); + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppAndBrowserIsolationPolicyWindows10/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppAndBrowserIsolationPolicyWindows10/3-Remove.ps1 new file mode 100644 index 0000000000..a6a52ed29b --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppAndBrowserIsolationPolicyWindows10/3-Remove.ps1 @@ -0,0 +1,34 @@ +<# +This example removes a Device Remediation. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneAppAndBrowserIsolationPolicyWindows10 'ConfigureAppAndBrowserIsolationPolicyWindows10' + { + Id = '00000000-0000-0000-0000-000000000000' + DisplayName = 'App and Browser Isolation' + Ensure = 'Absent' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppAndBrowserIsolationPolicyWindows10.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppAndBrowserIsolationPolicyWindows10.Tests.ps1 new file mode 100644 index 0000000000..c72f26f30e --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppAndBrowserIsolationPolicyWindows10.Tests.ps1 @@ -0,0 +1,347 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource "IntuneAppAndBrowserIsolationPolicyWindows10" -GenericStubModule $GenericStubPath +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName Get-PSSession -MockWith { + } + + Mock -CommandName Remove-PSSession -MockWith { + } + + Mock -CommandName Update-MgBetaDeviceManagementConfigurationPolicy -MockWith { + } + + Mock -CommandName New-MgBetaDeviceManagementConfigurationPolicy -MockWith { + } + + Mock -CommandName Remove-MgBetaDeviceManagementConfigurationPolicy -MockWith { + } + + Mock -CommandName Update-IntuneDeviceConfigurationPolicy -MockWith { + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicy -MockWith { + return @{ + Id = '12345-12345-12345-12345-12345' + Description = 'My Test' + Name = 'Test' + RoleScopeTagIds = @("FakeStringValue") + TemplateReference = @{ + TemplateId = '9f667e40-8f3c-4f88-80d8-457f16906315_1' + } + } + } + + Mock -CommandName Get-IntuneSettingCatalogPolicySetting -MockWith { + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicySetting -MockWith { + return @( + @{ + Id = '0' + SettingDefinitions = @( + @{ + Id = 'device_vendor_msft_windowsdefenderapplicationguard_installwindowsdefenderapplicationguard' + Name = 'InstallWindowsDefenderApplicationGuard' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + } + }, + @{ + Id = 'device_vendor_msft_windowsdefenderapplicationguard_settings_allowwindowsdefenderapplicationguard' + Name = 'AllowWindowsDefenderApplicationGuard' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + } + }, + @{ + Id = 'device_vendor_msft_windowsdefenderapplicationguard_settings_allowpersistence' + Name = 'AllowPersistence' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + } + }, + @{ + Id = 'device_vendor_msft_windowsdefenderapplicationguard_settings_allowvirtualgpu' + Name = 'AllowVirtualGPU' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + } + }, + @{ + Id = 'device_vendor_msft_windowsdefenderapplicationguard_settings_allowcameramicrophoneredirection' + Name = 'AllowCameraMicrophoneRedirection' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + } + } + ) + Settinginstance = @{ + SettingDefinitionId = 'device_vendor_msft_windowsdefenderapplicationguard_settings_allowwindowsdefenderapplicationguard' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = '1f2529c7-4b06-4ae6-bebc-210f7135676f' + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + choiceSettingValue = @{ + children = @( + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + settingDefinitionId = 'device_vendor_msft_windowsdefenderapplicationguard_settings_allowpersistence' + choiceSettingValue = @{ + children = @() + value = 'device_vendor_msft_windowsdefenderapplicationguard_settings_allowpersistence_0' + } + }, + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + settingDefinitionId = 'device_vendor_msft_windowsdefenderapplicationguard_settings_allowvirtualgpu' + choiceSettingValue = @{ + children = @() + value = 'device_vendor_msft_windowsdefenderapplicationguard_settings_allowvirtualgpu_0' + } + }, + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + settingDefinitionId = 'device_vendor_msft_windowsdefenderapplicationguard_settings_allowcameramicrophoneredirection' + choiceSettingValue = @{ + children = @() + value = 'device_vendor_msft_windowsdefenderapplicationguard_settings_allowcameramicrophoneredirection_1' + } + }, + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + settingDefinitionId = 'device_vendor_msft_windowsdefenderapplicationguard_installwindowsdefenderapplicationguard' + choiceSettingValue = @{ + children = @() + value = 'device_vendor_msft_windowsdefenderapplicationguard_installwindowsdefenderapplicationguard_install' + } + } + ) + value = 'device_vendor_msft_windowsdefenderapplicationguard_settings_allowwindowsdefenderapplicationguard_1' + } + } + } + } + ) + } + + Mock -CommandName Update-DeviceConfigurationPolicyAssignment -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicyAssignment -MockWith { + return @(@{ + Id = '12345-12345-12345-12345-12345' + Source = 'direct' + SourceId = '12345-12345-12345-12345-12345' + Target = @{ + DeviceAndAppManagementAssignmentFilterId = '12345-12345-12345-12345-12345' + DeviceAndAppManagementAssignmentFilterType = 'none' + AdditionalProperties = @( + @{ + '@odata.type' = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + } + ) + } + }) + } + + } + # Test contexts + Context -Name "The IntuneAppAndBrowserIsolationPolicyWindows10 should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + deviceAndAppManagementAssignmentFilterType = 'none' + } -ClientOnly) + ) + AllowCameraMicrophoneRedirection = "1"; + AllowPersistence = "0"; + AllowVirtualGPU = "0"; + AllowWindowsDefenderApplicationGuard = "1"; + InstallWindowsDefenderApplicationGuard = "install"; + Description = "My Test" + Id = "12345-12345-12345-12345-12345" + DisplayName = "Test" + RoleScopeTagIds = @("FakeStringValue") + Ensure = "Present" + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicy -MockWith { + return $null + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + It 'Should Create the group from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-MgBetaDeviceManagementConfigurationPolicy -Exactly 1 + } + } + + Context -Name "The IntuneAppAndBrowserIsolationPolicyWindows10 exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + deviceAndAppManagementAssignmentFilterType = 'none' + } -ClientOnly) + ) + AllowCameraMicrophoneRedirection = "1"; + AllowPersistence = "0"; + AllowVirtualGPU = "0"; + AllowWindowsDefenderApplicationGuard = "1"; + InstallWindowsDefenderApplicationGuard = "install"; + Description = "My Test" + Id = "12345-12345-12345-12345-12345" + DisplayName = "Test" + RoleScopeTagIds = @("FakeStringValue") + Ensure = 'Absent' + Credential = $Credential; + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should Remove the group from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-MgBetaDeviceManagementConfigurationPolicy -Exactly 1 + } + } + Context -Name "The IntuneAppAndBrowserIsolationPolicyWindows10 Exists and Values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + deviceAndAppManagementAssignmentFilterType = 'none' + } -ClientOnly) + ) + AllowCameraMicrophoneRedirection = "1"; + AllowPersistence = "0"; + AllowVirtualGPU = "0"; + AllowWindowsDefenderApplicationGuard = "1"; + InstallWindowsDefenderApplicationGuard = "install"; + Description = "My Test" + Id = "12345-12345-12345-12345-12345" + DisplayName = "Test" + RoleScopeTagIds = @("FakeStringValue") + Ensure = 'Present' + Credential = $Credential; + } + } + + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The IntuneAppAndBrowserIsolationPolicyWindows10 exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + deviceAndAppManagementAssignmentFilterType = 'none' + } -ClientOnly) + ) + AllowCameraMicrophoneRedirection = "0"; # Updated property + AllowPersistence = "0"; + AllowVirtualGPU = "0"; + AllowWindowsDefenderApplicationGuard = "1"; + InstallWindowsDefenderApplicationGuard = "install"; + Description = "My Test" + Id = "12345-12345-12345-12345-12345" + DisplayName = "Test" + RoleScopeTagIds = @("FakeStringValue") + Ensure = 'Present' + Credential = $Credential; + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Update-IntuneDeviceConfigurationPolicy -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope From da0d198f19022ed25f32a0f34fcecfad97c01cd6 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Mon, 23 Sep 2024 17:36:24 -0700 Subject: [PATCH 006/252] Microsoft365 DSC for Intune MobileApps MacOS Lob Apps. --- CHANGELOG.md | 2 + .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 580 ++++++++++++++++++ ...SFT_IntuneMobileAppsMacOSLobApp.schema.mof | 32 + .../readme.md | 6 + .../settings.json | 32 + .../IntuneMobileAppsMacOSLobApp/1-Create.ps1 | 27 + .../IntuneMobileAppsMacOSLobApp/2-Update.ps1 | 27 + .../IntuneMobileAppsMacOSLobApp/3-Remove.ps1 | 27 + ...5DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 | 177 ++++++ 9 files changed, 910 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index b25d25321c..39a87df4d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ # UNRELEASED +* IntuneMobileAppsMacOSLobApp + * Initial release * AADPasswordRuleSettings * Initial release * ADOOrganizationOwner diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 new file mode 100644 index 0000000000..a9728b35cb --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 @@ -0,0 +1,580 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + #region resource parameters + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [PSObject[]] + $Assignments, + + [Parameter()] + [PSObject[]] + $Categories, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $Developer, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $InformationUrl, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsFeatured, + + [Parameter()] + [PSObject] + $LargeIcon, + + [Parameter()] + [System.String] + $Notes, + + [Parameter()] + [System.String] + $Owner, + + [Parameter()] + [System.String] + $PrivacyInformationUrl, + + [Parameter()] + [System.String] + $Publisher, + + [Parameter()] + [PSObject] + $PublishingState, + + [Parameter()] + [PSObject[]] + $Relationships, + + #endregion + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters | Out-Null + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + try + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Id -eq $Id} + } + else + { + $instance = Get-IntuneMobileAppsMacOSLobApp -MobileAppId $Id -ErrorAction Stop + } + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + Id = $instance.Id + ResponseHeadersVariable = $instance.ResponseHeadersVariable + AdditionalProperties = $instance.AdditionalProperties + Assignments = $instance.Assignments + Categories = $instance.Categories + Description = $instance.Description + Developer = $instance.Developer + DisplayName = $instance.DisplayName + InformationUrl = $instance.InformationUrl + IsFeatured = $instance.IsFeatured + LargeIcon = $instance.LargeIcon + Notes = $instance.Notes + Owner = $instance.Owner + PrivacyInformationUrl = $instance.PrivacyInformationUrl + Publisher = $instance.Publisher + PublishingState = $instance.PublishingState + + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + #region resource generator code + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [PSObject[]] + $Assignments, + + [Parameter()] + [PSObject[]] + $Categories, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $Developer, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $InformationUrl, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsFeatured, + + [Parameter()] + [PSObject] + $LargeIcon, + + [Parameter()] + [System.String] + $Notes, + + [Parameter()] + [System.String] + $Owner, + + [Parameter()] + [System.String] + $PrivacyInformationUrl, + + [Parameter()] + [System.String] + $Publisher, + + [Parameter()] + [PSObject] + $PublishingState, + + [Parameter()] + [PSObject[]] + $Relationships, + + #endregion resource generator code + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + New-IntuneMobileAppsMacOSLobApp @SetParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Update-IntuneMobileAppsMacOSLobApp @SetParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Remove-IntuneMobileAppsMacOSLobApp @SetParameters + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + #region resource generator code + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [PSObject[]] + $Assignments, + + [Parameter()] + [PSObject[]] + $Categories, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $Developer, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $InformationUrl, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsFeatured, + + [Parameter()] + [PSObject] + $LargeIcon, + + [Parameter()] + [System.String] + $Notes, + + [Parameter()] + [System.String] + $Owner, + + [Parameter()] + [System.String] + $PrivacyInformationUrl, + + [Parameter()] + [System.String] + $Publisher, + + [Parameter()] + [PSObject] + $PublishingState, + + [Parameter()] + [PSObject[]] + $Relationships, + + #endregion resource generator code + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-IntuneMobileAppsMacOSLobApp -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + $displayedKey = $config.Id + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + PrimaryKey = $config.Id + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof new file mode 100644 index 0000000000..324ed5cc8d --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof @@ -0,0 +1,32 @@ +[ClassVersion("1.0.0"), FriendlyName("IntuneMobileAppsMacOSLobApp")] +class MSFT_IntuneMobileAppsMacOSLobApp : OMI_BaseResource +{ + [Key, Description("The unique identifier for an entity. Read-only. Inherited from mobileApp object.")] String Id; + + [Write, Description("Optional Response Headers Variable.")] String ResponseHeadersVariable; + [Write, Description("Additional Parameters.")] Hashtable AdditionalProperties; #TODOK + + [Write, Description("The description of the app. Inherited from mobileApp.")] String Description; + [Write, Description("Name of the device health script publisher")] String Developer; + [Write, Description("The admin provided or imported title of the app. Inherited from mobileApp.")] String DisplayName; + [Write, Description("Name of the device health script publisher")] String InformationUrl; + [Write, Description("The value indicating whether the app is marked as featured by the admin. Inherited from mobileApp.")] String IsFeatured; + [Write, Description("The large icon to be displayed in the app details and used for upload of the icon. Inherited from mobileApp.")] String LargeIcon; #TODOK + [Write, Description("Notes for the app. Inherited from mobileApp.")] String Notes; + [Write, Description("The owner of the app. Inherited from mobileApp.")] String Owner; + [Write, Description("The privacy statement Url. Inherited from mobileApp.")] String PrivacyInformationUrl; + [Write, Description("The publisher of the app. Inherited from mobileApp.")] String Publisher; + [Write, Description("The publishing state for the app. The app cannot be assigned unless the app is published. Inherited from mobileApp. Possible values are: notPublished, processing, published.")] MobileAppPublishingState PublishingState; #TODOK + + [Write, Description("The list of group assignments for this mobile app. To construct, see NOTES section for ASSIGNMENTS properties and create a hash table.")] String Assignments[]; #TODOK + [Write, Description("The list of categories for this app. To construct, see NOTES section for CATEGORIES properties and create a hash table.")] String Categories[]; #TODOK + + [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; + [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Secret of the Azure Active Directory tenant used for authentication."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/readme.md new file mode 100644 index 0000000000..821600b758 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/readme.md @@ -0,0 +1,6 @@ + +# IntuneMobileAppsMacOSLobApp + +## Description + +This resource configures an Intune mobile app of MacOSLobApp type for MacOS devices. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/settings.json new file mode 100644 index 0000000000..3244e12531 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName": "IntuneMobileAppsMacOSLobApp", + "description": "This resource configures an Intune mobile app of MacOSLobApp type for MacOS devices.", + "permissions": { + "graph": { + "delegated": { + "read": [ + { + "name": "DeviceManagementApps.Read.All" + } + ], + "update": [ + { + "name": "DeviceManagementApps.ReadWrite.All" + } + ] + }, + "application": { + "read": [ + { + "name": "DeviceManagementApps.Read.All" + } + ], + "update": [ + { + "name": "DeviceManagementApps.ReadWrite.All" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 new file mode 100644 index 0000000000..63cb0782d5 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 @@ -0,0 +1,27 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 new file mode 100644 index 0000000000..63cb0782d5 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 @@ -0,0 +1,27 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/3-Remove.ps1 new file mode 100644 index 0000000000..63cb0782d5 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/3-Remove.ps1 @@ -0,0 +1,27 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 new file mode 100644 index 0000000000..f3ddc7d594 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 @@ -0,0 +1,177 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -GenericStubModule $GenericStubPath + +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + ##TODO - Mock any Remove/Set/New cmdlets + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + Context -Name "The instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return $null + Mock -CommandName Get-Cmdlet -MockWith { + return $null + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should create a new instance from the Set method' { + ##TODO - Replace the New-Cmdlet by the appropriate one + Set-TargetResource @testParams + Should -Invoke -CommandName New-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Absent' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should remove the instance from the Set method' { + ##TODO - Replace the Remove-Cmdlet by the appropriate one + Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return the desired values + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return a drift + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + ##TODO - Replace the Update-Cmdlet by the appropriate one + Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope From 6ab848fc8326513db8490d859fd4f8ae39bcfb71 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Tue, 24 Sep 2024 23:02:10 -0700 Subject: [PATCH 007/252] Addressed the comments on iteration 1. --- .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 44 +++++++------------ ...SFT_IntuneMobileAppsMacOSLobApp.schema.mof | 40 +++++++++++++---- 2 files changed, 46 insertions(+), 38 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 index a9728b35cb..103709a5e5 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 @@ -13,14 +13,6 @@ function Get-TargetResource [PSObject] $BodyParameter, - [Parameter()] - [System.String] - $ResponseHeadersVariable, - - [Parameter()] - [System.Collections.Hashtable] - $AdditionalProperties, - [Parameter()] [PSObject[]] $Assignments, @@ -134,13 +126,23 @@ function Get-TargetResource } else { - $instance = Get-IntuneMobileAppsMacOSLobApp -MobileAppId $Id -ErrorAction Stop + $instance = Get-MgDeviceAppManagementMobileApp -MobileAppId $Id -ErrorAction Stop } + if ($null -eq $instance) { + Write-Verbose -Message "No Mobile app with Id {$Id} was found. Search with DisplayName." + $policy = Get-MgBetaDeviceAppManagementiOSManagedAppProtection -Filter "displayName eq '$DisplayName'" -ErrorAction SilentlyContinue + } + + if ($null -eq $policy) + { + Write-Verbose -Message "No Mobile app with {$DisplayName} was found." return $nullResult } + Write-Verbose -Message "Found Mobile app with {$DisplayName}." + $results = @{ Id = $instance.Id ResponseHeadersVariable = $instance.ResponseHeadersVariable @@ -197,14 +199,6 @@ function Set-TargetResource [PSObject] $BodyParameter, - [Parameter()] - [System.String] - $ResponseHeadersVariable, - - [Parameter()] - [System.Collections.Hashtable] - $AdditionalProperties, - [Parameter()] [PSObject[]] $Assignments, @@ -312,17 +306,17 @@ function Set-TargetResource # CREATE if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { - New-IntuneMobileAppsMacOSLobApp @SetParameters + New-MgDeviceAppManagementMobileApp @SetParameters } # UPDATE elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { - Update-IntuneMobileAppsMacOSLobApp @SetParameters + Update-MgDeviceAppManagementMobileApp @SetParameters } # REMOVE elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { - Remove-IntuneMobileAppsMacOSLobApp @SetParameters + Remove-MgDeviceAppManagementMobileApp @SetParameters } } @@ -341,14 +335,6 @@ function Test-TargetResource [PSObject] $BodyParameter, - [Parameter()] - [System.String] - $ResponseHeadersVariable, - - [Parameter()] - [System.Collections.Hashtable] - $AdditionalProperties, - [Parameter()] [PSObject[]] $Assignments, @@ -518,7 +504,7 @@ function Export-TargetResource try { $Script:ExportMode = $true - [array] $Script:exportedInstances = Get-IntuneMobileAppsMacOSLobApp -ErrorAction Stop + [array] $Script:exportedInstances = Get-MgDeviceAppManagementMobileApp -ErrorAction Stop $i = 1 $dscContent = '' diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof index 324ed5cc8d..92ea3fb3e1 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof @@ -1,25 +1,47 @@ +[ClassVersion("1.0.0.0")] +class MSFT_DeviceManagementMobileAppAssignments +{ + #TODOK: No other mof's have mentioned Key Id for the Assignment class! + + [Write, Description("The type of the target assignment."), ValueMap{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget","#microsoft.graph.configurationManagerCollectionAssignmentTarget"}, Values{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget","#microsoft.graph.configurationManagerCollectionAssignmentTarget"}] String dataType; + [Write, Description("The type of filter of the target assignment i.e. Exclude or Include. Possible values are:none, include, exclude."), ValueMap{"none","include","exclude"}, Values{"none","include","exclude"}] String deviceAndAppManagementAssignmentFilterType; + [Write, Description("The Id of the filter for the target assignment.")] String deviceAndAppManagementAssignmentFilterId; + [Write, Description("The group Id that is the target of the assignment.")] String groupId; + [Write, Description("The group Display Name that is the target of the assignment.")] String groupDisplayName; + [Write, Description("The collection Id that is the target of the assignment.(ConfigMgr)")] String collectionId; +}; + +class MSFT_DeviceManagementMobileAppCategory +{ + [Key, Description("The unique identifier for an entity. Read-only.")] String Id; + [Write, Description("The name of the app category.")] String DisplayName; +}; + +class MSFT_DeviceManagementLargeIcon +{ + [Write, Description("Indicates the content mime type.")] String Type; + [Write, Description("The byte array that contains the actual content.")] String Value[]; +}; + [ClassVersion("1.0.0"), FriendlyName("IntuneMobileAppsMacOSLobApp")] class MSFT_IntuneMobileAppsMacOSLobApp : OMI_BaseResource { [Key, Description("The unique identifier for an entity. Read-only. Inherited from mobileApp object.")] String Id; - [Write, Description("Optional Response Headers Variable.")] String ResponseHeadersVariable; - [Write, Description("Additional Parameters.")] Hashtable AdditionalProperties; #TODOK - [Write, Description("The description of the app. Inherited from mobileApp.")] String Description; - [Write, Description("Name of the device health script publisher")] String Developer; + [Write, Description("The dewveloper of the app. Inherited from mobileApp.")] String Developer; [Write, Description("The admin provided or imported title of the app. Inherited from mobileApp.")] String DisplayName; - [Write, Description("Name of the device health script publisher")] String InformationUrl; + [Write, Description("The InformationUrl of the app. Inherited from mobileApp.")] String InformationUrl; [Write, Description("The value indicating whether the app is marked as featured by the admin. Inherited from mobileApp.")] String IsFeatured; - [Write, Description("The large icon to be displayed in the app details and used for upload of the icon. Inherited from mobileApp.")] String LargeIcon; #TODOK [Write, Description("Notes for the app. Inherited from mobileApp.")] String Notes; [Write, Description("The owner of the app. Inherited from mobileApp.")] String Owner; [Write, Description("The privacy statement Url. Inherited from mobileApp.")] String PrivacyInformationUrl; [Write, Description("The publisher of the app. Inherited from mobileApp.")] String Publisher; - [Write, Description("The publishing state for the app. The app cannot be assigned unless the app is published. Inherited from mobileApp. Possible values are: notPublished, processing, published.")] MobileAppPublishingState PublishingState; #TODOK + [Write, Description("The publishing state for the app. The app cannot be assigned unless the app is published. Inherited from mobileApp. Possible values are: notPublished, processing, published.")] String PublishingState; - [Write, Description("The list of group assignments for this mobile app. To construct, see NOTES section for ASSIGNMENTS properties and create a hash table.")] String Assignments[]; #TODOK - [Write, Description("The list of categories for this app. To construct, see NOTES section for CATEGORIES properties and create a hash table.")] String Categories[]; #TODOK + [Write, Description("The list of group assignments for this mobile app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppAssignments")] String Assignments[]; + [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppCategory")] String Categories[]; + [Write, Description("The large icon to be displayed in the app details and used for upload of the icon. Inherited from mobileApp.")] String LargeIcon; #TODOK: Byte[] is just a String [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; From 72bee7503f5cfa7dbc48cf67fde05dbd28e4f156 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Tue, 24 Sep 2024 23:03:17 -0700 Subject: [PATCH 008/252] Update Microsoft365.psm1 TODOK to ask. --- Tests/Unit/Stubs/Microsoft365.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 08a1346300..c85ed85c34 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -18670,7 +18670,7 @@ function New-MgBetaDeviceManagementAssignmentFilter $HttpPipelineAppend ) } -function New-MgBetaDeviceManagementConfigurationPolicy +function New-MgBetaDeviceManagementConfigurationPolicy #TODOK: What is the use of this file? Why almost all Intune cmdlets are already here? { [CmdletBinding()] param( From 46b0c73561190c3668107af21d188059c354928e Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Tue, 1 Oct 2024 15:54:02 +0530 Subject: [PATCH 009/252] Adding support for updating 1 key credential --- .../MSFT_AADApplication/MSFT_AADApplication.psm1 | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index 636e27a4db..c88da22921 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -933,7 +933,16 @@ function Set-TargetResource if($needToUpdateKeyCredentials -and $KeyCredentials) { - Write-Warning -Message "KeyCredentials is a readonly property and cannot be configured." + Write-Verbose -Message "Updating for Azure AD Application {$($currentAADApp.DisplayName)} with KeyCredentials:`r`n$($KeyCredentials| Out-String)" + + if((currentAADApp.KeyCredentials.Length -eq 0 -and $KeyCredentials.Length -eq 1) -or (currentAADApp.KeyCredentials.Length -eq 1 -and $KeyCredentials.Length -eq 0)) + { + Update-MgApplication -ApplicationId $currentAADApp.Id -KeyCredentials $KeyCredentials | Out-Null + } + else + { + Write-Warning -Message "KeyCredentials is a readonly property and cannot be configured." + } } } From b76d84d1ed5d8bb59a9ee3e688ed610ed8eba974 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Tue, 1 Oct 2024 23:46:13 -0700 Subject: [PATCH 010/252] Added examples and UTs passing locally. --- .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 171 ++++++--------- ...SFT_IntuneMobileAppsMacOSLobApp.schema.mof | 35 +-- .../settings.json | 2 +- .../IntuneMobileAppsMacOSLobApp/1-Create.ps1 | 16 +- .../IntuneMobileAppsMacOSLobApp/2-Update.ps1 | 16 +- .../IntuneMobileAppsMacOSLobApp/3-Remove.ps1 | 16 +- ...5DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 | 178 ++++++++++----- Tests/Unit/Stubs/Microsoft365.psm1 | 204 ++++++++++++++++++ 8 files changed, 452 insertions(+), 186 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 index 103709a5e5..f3cbe068a8 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 @@ -4,22 +4,15 @@ function Get-TargetResource [OutputType([System.Collections.Hashtable])] param ( - #region resource parameters + #region Intune resource parameters + [Parameter()] [System.String] $Id, - [Parameter()] - [PSObject] - $BodyParameter, - - [Parameter()] - [PSObject[]] - $Assignments, - - [Parameter()] - [PSObject[]] - $Categories, + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, [Parameter()] [System.String] @@ -29,22 +22,14 @@ function Get-TargetResource [System.String] $Developer, - [Parameter()] - [System.String] - $DisplayName, - [Parameter()] [System.String] $InformationUrl, [Parameter()] - [System.Management.Automation.SwitchParameter] + [System.Boolean] $IsFeatured, - [Parameter()] - [PSObject] - $LargeIcon, - [Parameter()] [System.String] $Notes, @@ -62,13 +47,10 @@ function Get-TargetResource $Publisher, [Parameter()] - [PSObject] + [System.String] + [ValidateSet('notPublished', 'processing','published')] $PublishingState, - [Parameter()] - [PSObject[]] - $Relationships, - #endregion [Parameter()] @@ -92,6 +74,10 @@ function Get-TargetResource [System.String] $CertificateThumbprint, + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + [Parameter()] [Switch] $ManagedIdentity, @@ -126,16 +112,16 @@ function Get-TargetResource } else { - $instance = Get-MgDeviceAppManagementMobileApp -MobileAppId $Id -ErrorAction Stop + $instance = Get-MgBetaDeviceAppManagementMobileApp -MobileAppId $Id -Filter "microsoft.graph.managedApp/appAvailability eq null" -ErrorAction Stop } if ($null -eq $instance) { Write-Verbose -Message "No Mobile app with Id {$Id} was found. Search with DisplayName." - $policy = Get-MgBetaDeviceAppManagementiOSManagedAppProtection -Filter "displayName eq '$DisplayName'" -ErrorAction SilentlyContinue + $instance = Get-MgBetaDeviceAppManagementMobileApp -Filter "displayName eq '$DisplayName'" -ErrorAction SilentlyContinue } - if ($null -eq $policy) + if ($null -eq $instance) { Write-Verbose -Message "No Mobile app with {$DisplayName} was found." return $nullResult @@ -145,27 +131,25 @@ function Get-TargetResource $results = @{ Id = $instance.Id - ResponseHeadersVariable = $instance.ResponseHeadersVariable - AdditionalProperties = $instance.AdditionalProperties - Assignments = $instance.Assignments - Categories = $instance.Categories + #Assignments = $instance.Assignments + #Categories = $instance.Categories Description = $instance.Description Developer = $instance.Developer DisplayName = $instance.DisplayName InformationUrl = $instance.InformationUrl IsFeatured = $instance.IsFeatured - LargeIcon = $instance.LargeIcon + #LargeIcon = $instance.LargeIcon Notes = $instance.Notes Owner = $instance.Owner PrivacyInformationUrl = $instance.PrivacyInformationUrl Publisher = $instance.Publisher PublishingState = $instance.PublishingState - Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ApplicationSecret = $ApplicationSecret ManagedIdentity = $ManagedIdentity.IsPresent AccessTokens = $AccessTokens } @@ -190,22 +174,15 @@ function Set-TargetResource [CmdletBinding()] param ( - #region resource generator code - [Parameter(Mandatory = $true)] - [System.String] - $Id, + #region Intune resource parameters [Parameter()] - [PSObject] - $BodyParameter, - - [Parameter()] - [PSObject[]] - $Assignments, + [System.String] + $Id, - [Parameter()] - [PSObject[]] - $Categories, + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, [Parameter()] [System.String] @@ -215,22 +192,14 @@ function Set-TargetResource [System.String] $Developer, - [Parameter()] - [System.String] - $DisplayName, - [Parameter()] [System.String] $InformationUrl, [Parameter()] - [System.Management.Automation.SwitchParameter] + [System.Boolean] $IsFeatured, - [Parameter()] - [PSObject] - $LargeIcon, - [Parameter()] [System.String] $Notes, @@ -248,14 +217,11 @@ function Set-TargetResource $Publisher, [Parameter()] - [PSObject] + [System.String] + [ValidateSet('notPublished', 'processing','published')] $PublishingState, - [Parameter()] - [PSObject[]] - $Relationships, - - #endregion resource generator code + #endregion [Parameter()] [ValidateSet('Present', 'Absent')] @@ -278,6 +244,10 @@ function Set-TargetResource [System.String] $CertificateThumbprint, + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + [Parameter()] [Switch] $ManagedIdentity, @@ -300,23 +270,25 @@ function Set-TargetResource #endregion $currentInstance = Get-TargetResource @PSBoundParameters - $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + $setParameters.remove('Id') | Out-Null + $setParameters.remove('Ensure') | Out-Null + # CREATE if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { - New-MgDeviceAppManagementMobileApp @SetParameters + New-MgBetaDeviceAppManagementMobileApp @SetParameters } # UPDATE elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { - Update-MgDeviceAppManagementMobileApp @SetParameters + Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id @SetParameters } # REMOVE elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { - Remove-MgDeviceAppManagementMobileApp @SetParameters + Remove-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id -Confirm:$false } } @@ -326,22 +298,15 @@ function Test-TargetResource [OutputType([System.Boolean])] param ( - #region resource generator code - [Parameter(Mandatory = $true)] - [System.String] - $Id, - - [Parameter()] - [PSObject] - $BodyParameter, + #region resource parameters [Parameter()] - [PSObject[]] - $Assignments, + [System.String] + $Id, - [Parameter()] - [PSObject[]] - $Categories, + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, [Parameter()] [System.String] @@ -351,22 +316,14 @@ function Test-TargetResource [System.String] $Developer, - [Parameter()] - [System.String] - $DisplayName, - [Parameter()] [System.String] $InformationUrl, [Parameter()] - [System.Management.Automation.SwitchParameter] + [System.Boolean] $IsFeatured, - [Parameter()] - [PSObject] - $LargeIcon, - [Parameter()] [System.String] $Notes, @@ -384,14 +341,11 @@ function Test-TargetResource $Publisher, [Parameter()] - [PSObject] + [System.String] + [ValidateSet('notPublished', 'processing','published')] $PublishingState, - [Parameter()] - [PSObject[]] - $Relationships, - - #endregion resource generator code + #endregion [Parameter()] [ValidateSet('Present', 'Absent')] @@ -414,6 +368,10 @@ function Test-TargetResource [System.String] $CertificateThumbprint, + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + [Parameter()] [Switch] $ManagedIdentity, @@ -469,14 +427,14 @@ function Export-TargetResource [System.String] $TenantId, - [Parameter()] - [System.Management.Automation.PSCredential] - $ApplicationSecret, - [Parameter()] [System.String] $CertificateThumbprint, + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + [Parameter()] [Switch] $ManagedIdentity, @@ -504,7 +462,7 @@ function Export-TargetResource try { $Script:ExportMode = $true - [array] $Script:exportedInstances = Get-MgDeviceAppManagementMobileApp -ErrorAction Stop + [array] $Script:exportedInstances = Get-MgBetaDeviceAppManagementMobileApp -Filter "microsoft.graph.managedApp/appAvailability eq null" -ErrorAction Stop $i = 1 $dscContent = '' @@ -521,12 +479,23 @@ function Export-TargetResource $displayedKey = $config.Id Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline $params = @{ - PrimaryKey = $config.Id + Id = $config.Id + Description = $config.Description + Developer = $config.Developer + DisplayName = $config.DisplayName + InformationUrl = $config.InformationUrl + IsFeatured = $config.IsFeatured + Notes = $config.Notes + Owner = $config.Owner + PrivacyInformationUrl = $config.PrivacyInformationUrl + Publisher = $config.Publisher + PublishingState = $config.PublishingState Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ApplicationSecret = $ApplicationSecret ManagedIdentity = $ManagedIdentity.IsPresent AccessTokens = $AccessTokens } diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof index 92ea3fb3e1..3a55c7d2ca 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof @@ -1,47 +1,18 @@ -[ClassVersion("1.0.0.0")] -class MSFT_DeviceManagementMobileAppAssignments -{ - #TODOK: No other mof's have mentioned Key Id for the Assignment class! - - [Write, Description("The type of the target assignment."), ValueMap{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget","#microsoft.graph.configurationManagerCollectionAssignmentTarget"}, Values{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget","#microsoft.graph.configurationManagerCollectionAssignmentTarget"}] String dataType; - [Write, Description("The type of filter of the target assignment i.e. Exclude or Include. Possible values are:none, include, exclude."), ValueMap{"none","include","exclude"}, Values{"none","include","exclude"}] String deviceAndAppManagementAssignmentFilterType; - [Write, Description("The Id of the filter for the target assignment.")] String deviceAndAppManagementAssignmentFilterId; - [Write, Description("The group Id that is the target of the assignment.")] String groupId; - [Write, Description("The group Display Name that is the target of the assignment.")] String groupDisplayName; - [Write, Description("The collection Id that is the target of the assignment.(ConfigMgr)")] String collectionId; -}; - -class MSFT_DeviceManagementMobileAppCategory -{ - [Key, Description("The unique identifier for an entity. Read-only.")] String Id; - [Write, Description("The name of the app category.")] String DisplayName; -}; - -class MSFT_DeviceManagementLargeIcon -{ - [Write, Description("Indicates the content mime type.")] String Type; - [Write, Description("The byte array that contains the actual content.")] String Value[]; -}; - [ClassVersion("1.0.0"), FriendlyName("IntuneMobileAppsMacOSLobApp")] class MSFT_IntuneMobileAppsMacOSLobApp : OMI_BaseResource { - [Key, Description("The unique identifier for an entity. Read-only. Inherited from mobileApp object.")] String Id; + [Key, Description("The admin provided or imported title of the app. Inherited from mobileApp.")] String DisplayName; + [Write, Description("The unique identifier for an entity. Read-only. Inherited from mobileApp object.")] String Id; [Write, Description("The description of the app. Inherited from mobileApp.")] String Description; [Write, Description("The dewveloper of the app. Inherited from mobileApp.")] String Developer; - [Write, Description("The admin provided or imported title of the app. Inherited from mobileApp.")] String DisplayName; [Write, Description("The InformationUrl of the app. Inherited from mobileApp.")] String InformationUrl; [Write, Description("The value indicating whether the app is marked as featured by the admin. Inherited from mobileApp.")] String IsFeatured; [Write, Description("Notes for the app. Inherited from mobileApp.")] String Notes; [Write, Description("The owner of the app. Inherited from mobileApp.")] String Owner; [Write, Description("The privacy statement Url. Inherited from mobileApp.")] String PrivacyInformationUrl; [Write, Description("The publisher of the app. Inherited from mobileApp.")] String Publisher; - [Write, Description("The publishing state for the app. The app cannot be assigned unless the app is published. Inherited from mobileApp. Possible values are: notPublished, processing, published.")] String PublishingState; - - [Write, Description("The list of group assignments for this mobile app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppAssignments")] String Assignments[]; - [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppCategory")] String Categories[]; - [Write, Description("The large icon to be displayed in the app details and used for upload of the icon. Inherited from mobileApp.")] String LargeIcon; #TODOK: Byte[] is just a String + [Write, Description("The publishing state for the app. The app cannot be assigned unless the app is published. Inherited from mobileApp."), ValueMap{"notPublished", "processing","published"}, Values{"notPublished", "processing", "published"}] String PublishingState; [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/settings.json index 3244e12531..3e70ad560b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/settings.json @@ -1,6 +1,6 @@ { "resourceName": "IntuneMobileAppsMacOSLobApp", - "description": "This resource configures an Intune mobile app of MacOSLobApp type for MacOS devices.", + "description": "This resource configures an Intune mobile app.", "permissions": { "graph": { "delegated": { diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 index 63cb0782d5..097a2846b4 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 @@ -22,6 +22,20 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + IntuneMobileAppsMacOSLobApp "IntuneMobileAppsMacOSLobApp-TeamsForBusinessInstaller" + { + Id = "8d027f94-0682-431e-97c1-827d1879fa79"; + Description = "TeamsForBusinessInstaller"; + Developer = "Contoso"; + DisplayName = "TeamsForBusinessInstaller"; + Ensure = "Present"; + InformationUrl = ""; + IsFeatured = $False; + Notes = ""; + Owner = ""; + PrivacyInformationUrl = ""; + Publisher = "Contoso"; + PublishingState = "published"; + } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 index 63cb0782d5..85ec982890 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 @@ -22,6 +22,20 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + IntuneMobileAppsMacOSLobApp "IntuneMobileAppsMacOSLobApp-TeamsForBusinessInstaller" + { + Id = "8d027f94-0682-431e-97c1-827d1879fa79"; + Description = "TeamsForBusinessInstaller"; + Developer = "Contoso drift"; #drift + DisplayName = "TeamsForBusinessInstaller"; + Ensure = "Present"; + InformationUrl = ""; + IsFeatured = $False; + Notes = ""; + Owner = ""; + PrivacyInformationUrl = ""; + Publisher = "Contoso"; + PublishingState = "published"; + } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/3-Remove.ps1 index 63cb0782d5..33cc9276b4 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/3-Remove.ps1 @@ -22,6 +22,20 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + IntuneMobileAppsMacOSLobApp "IntuneMobileAppsMacOSLobApp-TeamsForBusinessInstaller" + { + Id = "8d027f94-0682-431e-97c1-827d1879fa79"; + Description = "TeamsForBusinessInstaller"; + Developer = "Contoso"; + DisplayName = "TeamsForBusinessInstaller"; + Ensure = "Absent"; + InformationUrl = ""; + IsFeatured = $False; + Notes = ""; + Owner = ""; + PrivacyInformationUrl = ""; + Publisher = "Contoso"; + PublishingState = "published"; + } } } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 index f3ddc7d594..809bbe30d6 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 @@ -35,123 +35,194 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { return "Credentials" } - ##TODO - Mock any Remove/Set/New cmdlets + Mock -CommandName New-MgBetaDeviceAppManagementMobileApp -MockWith { + } + Mock -CommandName Update-MgBetaDeviceAppManagementMobileApp -MockWith { + } + Mock -CommandName Remove-MgBetaDeviceAppManagementMobileApp -MockWith { + } # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { } + $Script:exportedInstances =$null $Script:ExportMode = $false } + # Test contexts - Context -Name "The instance should exist but it DOES NOT" -Fixture { + Context -Name "1. The instance should exist but it DOES NOT" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; + Id = "8d027f94-0682-431e-97c1-827d1879fa79" + Description = "TeamsForBusinessInstaller" + Developer = "Contoso" + DisplayName = "TeamsForBusinessInstaller" + InformationUrl = "" + IsFeatured = $False + Notes = "" + Owner = "" + PrivacyInformationUrl = "" + Publisher = "Contoso" + PublishingState = "published" + Ensure = 'Present' + Credential = $Credential } - ##TODO - Mock the Get-Cmdlet to return $null - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { return $null } } - It 'Should return Values from the Get method' { + It '1.1 Should return Values from the Get method' { (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' } - It 'Should return false from the Test method' { + It '1.2 Should return false from the Test method' { Test-TargetResource @testParams | Should -Be $false } - It 'Should create a new instance from the Set method' { - ##TODO - Replace the New-Cmdlet by the appropriate one + It '1.3 Should create a new instance from the Set method' { Set-TargetResource @testParams - Should -Invoke -CommandName New-Cmdlet -Exactly 1 + Should -Invoke -CommandName New-MgBetaDeviceAppManagementMobileApp -Exactly 1 } } - Context -Name "The instance exists but it SHOULD NOT" -Fixture { + Context -Name "2. The instance exists but it SHOULD NOT" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Absent' - Credential = $Credential; + Id = "8d027f94-0682-431e-97c1-827d1879fa79" + Description = "TeamsForBusinessInstaller" + Developer = "Contoso" + DisplayName = "TeamsForBusinessInstaller" + InformationUrl = "" + IsFeatured = $False + Notes = "" + Owner = "" + PrivacyInformationUrl = "" + Publisher = "Contoso" + PublishingState = "published" + Ensure = 'Absent' + Credential = $Credential } - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { return @{ - + Id = "8d027f94-0682-431e-97c1-827d1879fa79" + Description = "TeamsForBusinessInstaller" + Developer = "Contoso" + DisplayName = "TeamsForBusinessInstaller" + InformationUrl = "" + IsFeatured = $False + Notes = "" + Owner = "" + PrivacyInformationUrl = "" + Publisher = "Contoso" + PublishingState = "published" } } } - It 'Should return Values from the Get method' { + It '2.1 Should return Values from the Get method' { (Get-TargetResource @testParams).Ensure | Should -Be 'Present' } - It 'Should return false from the Test method' { + It '2.2 Should return false from the Test method' { Test-TargetResource @testParams | Should -Be $false } - It 'Should remove the instance from the Set method' { - ##TODO - Replace the Remove-Cmdlet by the appropriate one - Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + It '2.3 Should remove the instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-MgBetaDeviceAppManagementMobileApp -Exactly 1 } } - Context -Name "The instance exists and values are already in the desired state" -Fixture { + Context -Name "3. The instance exists and values are already in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; + Id = "8d027f94-0682-431e-97c1-827d1879fa79" + Description = "TeamsForBusinessInstaller" + Developer = "Contoso" + DisplayName = "TeamsForBusinessInstaller" + InformationUrl = "" + IsFeatured = $False + Notes = "" + Owner = "" + PrivacyInformationUrl = "" + Publisher = "Contoso" + PublishingState = "published" + Ensure = 'Present' + Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return the desired values - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { return @{ - + Id = "8d027f94-0682-431e-97c1-827d1879fa79" + Description = "TeamsForBusinessInstaller" + Developer = "Contoso" + DisplayName = "TeamsForBusinessInstaller" + InformationUrl = "" + IsFeatured = $False + Notes = "" + Owner = "" + PrivacyInformationUrl = "" + Publisher = "Contoso" + PublishingState = "published" } } } - It 'Should return true from the Test method' { + It '3.0 Should return true from the Test method' { Test-TargetResource @testParams | Should -Be $true } } - Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + Context -Name "4. The instance exists and values are NOT in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; + Id = "8d027f94-0682-431e-97c1-827d1879fa79" + Description = "TeamsForBusinessInstaller" + Developer = "Contoso" + DisplayName = "TeamsForBusinessInstaller" + InformationUrl = "" + IsFeatured = $False + Notes = "" + Owner = "" + PrivacyInformationUrl = "" + Publisher = "Contoso" + PublishingState = "published" + Ensure = 'Present' + Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return a drift - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { return @{ - + Id = "8d027f94-0682-431e-97c1-827d1879fa79" + Description = "TeamsForBusinessInstaller" + Developer = "Contoso" + DisplayName = "TeamsForBusinessInstaller drift" + InformationUrl = "" + IsFeatured = $False + Notes = "" + Owner = "" + PrivacyInformationUrl = "" + Publisher = "Contoso" + PublishingState = "published" } } } - It 'Should return Values from the Get method' { + It '4.1 Should return Values from the Get method' { (Get-TargetResource @testParams).Ensure | Should -Be 'Present' } - It 'Should return false from the Test method' { + It '4.2 Should return false from the Test method' { Test-TargetResource @testParams | Should -Be $false } - It 'Should call the Set method' { + It '4.3 Should call the Set method' { Set-TargetResource @testParams - ##TODO - Replace the Update-Cmdlet by the appropriate one - Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + Should -Invoke -CommandName Update-MgBetaDeviceAppManagementMobileApp -Exactly 1 } } - Context -Name 'ReverseDSC Tests' -Fixture { + Context -Name '5. ReverseDSC Tests' -Fixture { BeforeAll { $Global:CurrentModeIsExport = $true $Global:PartialExportFileName = "$(New-Guid).partial.ps1" @@ -159,14 +230,23 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { return @{ - + Id = "8d027f94-0682-431e-97c1-827d1879fa79" + Description = "TeamsForBusinessInstaller" + Developer = "Contoso" + DisplayName = "TeamsForBusinessInstaller drift" + InformationUrl = "" + IsFeatured = $False + Notes = "" + Owner = "" + PrivacyInformationUrl = "" + Publisher = "Contoso" + PublishingState = "published" } } } - It 'Should Reverse Engineer resource from the Export method' { + It '5.0 Should Reverse Engineer resource from the Export method' { $result = Export-TargetResource @testParams $result | Should -Not -BeNullOrEmpty } diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index c85ed85c34..a9239e58c1 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -17892,6 +17892,210 @@ function Get-MgBetaDeviceManagementGroupPolicyConfigurationAssignment $HttpPipelineAppend ) } + +function New-MgBetaDeviceAppManagementMobileApp { + [CmdletBinding()] + param ( + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $Developer, + + [Parameter()] + [System.String] + $InformationUrl, + + [Parameter()] + [System.Boolean] + $IsFeatured, + + [Parameter()] + [System.String] + $Notes, + + [Parameter()] + [System.String] + $Owner, + + [Parameter()] + [System.String] + $PrivacyInformationUrl, + + [Parameter()] + [System.String] + $Publisher, + + [Parameter()] + [System.String] + [ValidateSet('notPublished', 'processing','published')] + $PublishingState + ) +} + +function Get-MgBetaDeviceAppManagementMobileApp { + [CmdletBinding()] + param ( + [Parameter()] + [System.String] + $MobileAppId, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $Developer, + + [Parameter()] + [System.String] + $InformationUrl, + + [Parameter()] + [System.Boolean] + $IsFeatured, + + [Parameter()] + [System.String] + $Notes, + + [Parameter()] + [System.String] + $Owner, + + [Parameter()] + [System.String] + $PrivacyInformationUrl, + + [Parameter()] + [System.String] + $Publisher, + + [Parameter()] + [System.String] + [ValidateSet('notPublished', 'processing','published')] + $PublishingState + ) +} +function Update-MgBetaDeviceAppManagementMobileApp { + [CmdletBinding()] + param ( + [Parameter()] + [System.String] + $MobileAppId, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $Developer, + + [Parameter()] + [System.String] + $InformationUrl, + + [Parameter()] + [System.Boolean] + $IsFeatured, + + [Parameter()] + [System.String] + $Notes, + + [Parameter()] + [System.String] + $Owner, + + [Parameter()] + [System.String] + $PrivacyInformationUrl, + + [Parameter()] + [System.String] + $Publisher, + + [Parameter()] + [System.String] + [ValidateSet('notPublished', 'processing','published')] + $PublishingState + ) +} + +function Remove-MgBetaDeviceAppManagementMobileApp { + [CmdletBinding()] + param ( + [Parameter()] + [System.String] + $MobileAppId, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $Developer, + + [Parameter()] + [System.String] + $InformationUrl, + + [Parameter()] + [System.Boolean] + $IsFeatured, + + [Parameter()] + [System.String] + $Notes, + + [Parameter()] + [System.String] + $Owner, + + [Parameter()] + [System.String] + $PrivacyInformationUrl, + + [Parameter()] + [System.String] + $Publisher, + + [Parameter()] + [System.String] + [ValidateSet('notPublished', 'processing','published')] + $PublishingState, + + [Parameter()] + [System.Boolean] + $Confirm + ) +} + function Get-MgBetaDeviceManagementGroupPolicyConfigurationDefinitionValue { [CmdletBinding()] From b3097f52b2aae370fc735f70b4cb4a66b4b20fd8 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Wed, 2 Oct 2024 00:40:22 -0700 Subject: [PATCH 011/252] minor changes in the stub. --- .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 6 +- Tests/Unit/Stubs/Microsoft365.psm1 | 87 +++---------------- 2 files changed, 16 insertions(+), 77 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 index f3cbe068a8..86bf19dc2b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 @@ -27,7 +27,7 @@ function Get-TargetResource $InformationUrl, [Parameter()] - [System.Boolean] + [System.String] $IsFeatured, [Parameter()] @@ -197,7 +197,7 @@ function Set-TargetResource $InformationUrl, [Parameter()] - [System.Boolean] + [System.String] $IsFeatured, [Parameter()] @@ -321,7 +321,7 @@ function Test-TargetResource $InformationUrl, [Parameter()] - [System.Boolean] + [System.String] $IsFeatured, [Parameter()] diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index a9239e58c1..84278053bf 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -17917,7 +17917,7 @@ function New-MgBetaDeviceAppManagementMobileApp { $InformationUrl, [Parameter()] - [System.Boolean] + [System.String] $IsFeatured, [Parameter()] @@ -17967,7 +17967,7 @@ function Get-MgBetaDeviceAppManagementMobileApp { $InformationUrl, [Parameter()] - [System.Boolean] + [System.String] $IsFeatured, [Parameter()] @@ -18016,7 +18016,7 @@ function Update-MgBetaDeviceAppManagementMobileApp { $InformationUrl, [Parameter()] - [System.Boolean] + [System.String] $IsFeatured, [Parameter()] @@ -18066,7 +18066,7 @@ function Remove-MgBetaDeviceAppManagementMobileApp { $InformationUrl, [Parameter()] - [System.Boolean] + [System.String] $IsFeatured, [Parameter()] @@ -18874,7 +18874,7 @@ function New-MgBetaDeviceManagementAssignmentFilter $HttpPipelineAppend ) } -function New-MgBetaDeviceManagementConfigurationPolicy #TODOK: What is the use of this file? Why almost all Intune cmdlets are already here? +function New-MgBetaDeviceManagementConfigurationPolicy { [CmdletBinding()] param( @@ -83113,7 +83113,7 @@ function Update-MgBetaDeviceAppManagementPolicySetAssignment #endregion #region MgBetaDeviceAppManagementMobileApp -function Get-MgBetaDeviceAppManagementMobileApp +function Get-MgBetaDeviceAppManagementMobileApp # TODOK { [CmdletBinding()] param @@ -83200,7 +83200,7 @@ function Get-MgBetaDeviceAppManagementMobileApp ) } -function New-MgBetaDeviceAppManagementMobileApp +function New-MgBetaDeviceAppManagementMobileApp # TODOK { [CmdletBinding()] param @@ -83258,7 +83258,8 @@ function New-MgBetaDeviceAppManagementMobileApp $IsAssigned, [Parameter()] - [System.Management.Automation.SwitchParameter] + #[System.Management.Automation.SwitchParameter] + [System.String] $IsFeatured, [Parameter()] @@ -83339,58 +83340,7 @@ function New-MgBetaDeviceAppManagementMobileApp ) } -function Remove-MgBetaDeviceAppManagementMobileApp -{ - [CmdletBinding()] - param - ( - [Parameter()] - [System.String] - $MobileAppId, - - [Parameter()] - [PSObject] - $InputObject, - - [Parameter()] - [System.String] - $ResponseHeadersVariable, - - [Parameter()] - [System.Management.Automation.SwitchParameter] - $Break, - - [Parameter()] - [System.Collections.IDictionary] - $Headers, - - [Parameter()] - [PSObject[]] - $HttpPipelineAppend, - - [Parameter()] - [PSObject[]] - $HttpPipelinePrepend, - - [Parameter()] - [System.Management.Automation.SwitchParameter] - $PassThru, - - [Parameter()] - [System.Uri] - $Proxy, - - [Parameter()] - [System.Management.Automation.PSCredential] - $ProxyCredential, - - [Parameter()] - [System.Management.Automation.SwitchParameter] - $ProxyUseDefaultCredentials - ) -} - -function Set-MgBetaDeviceAppManagementMobileApp +function Remove-MgBetaDeviceAppManagementMobileApp # TODOK { [CmdletBinding()] param @@ -83403,22 +83353,10 @@ function Set-MgBetaDeviceAppManagementMobileApp [PSObject] $InputObject, - [Parameter()] - [PSObject] - $BodyParameter, - [Parameter()] [System.String] $ResponseHeadersVariable, - [Parameter()] - [System.Collections.Hashtable] - $AdditionalProperties, - - [Parameter()] - [PSObject[]] - $MobileAppAssignments, - [Parameter()] [System.Management.Automation.SwitchParameter] $Break, @@ -83453,7 +83391,7 @@ function Set-MgBetaDeviceAppManagementMobileApp ) } -function Update-MgBetaDeviceAppManagementMobileApp +function Update-MgBetaDeviceAppManagementMobileApp # TODOK { [CmdletBinding()] param @@ -83519,7 +83457,8 @@ function Update-MgBetaDeviceAppManagementMobileApp $IsAssigned, [Parameter()] - [System.Management.Automation.SwitchParameter] + #[System.Management.Automation.SwitchParameter] + [System.String] $IsFeatured, [Parameter()] From 387d8945e6f73a3bce12ac1395d6ad627009b899 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Wed, 2 Oct 2024 11:34:41 -0700 Subject: [PATCH 012/252] updated the mof file to add complex types. --- .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 6 +- ...SFT_IntuneMobileAppsMacOSLobApp.schema.mof | 58 +++++++++++++++++- Tests/Unit/Stubs/Microsoft365.psm1 | 59 ++++--------------- 3 files changed, 70 insertions(+), 53 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 index 86bf19dc2b..f3cbe068a8 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 @@ -27,7 +27,7 @@ function Get-TargetResource $InformationUrl, [Parameter()] - [System.String] + [System.Boolean] $IsFeatured, [Parameter()] @@ -197,7 +197,7 @@ function Set-TargetResource $InformationUrl, [Parameter()] - [System.String] + [System.Boolean] $IsFeatured, [Parameter()] @@ -321,7 +321,7 @@ function Test-TargetResource $InformationUrl, [Parameter()] - [System.String] + [System.Boolean] $IsFeatured, [Parameter()] diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof index 3a55c7d2ca..b250cb9101 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof @@ -13,8 +13,15 @@ class MSFT_IntuneMobileAppsMacOSLobApp : OMI_BaseResource [Write, Description("The privacy statement Url. Inherited from mobileApp.")] String PrivacyInformationUrl; [Write, Description("The publisher of the app. Inherited from mobileApp.")] String Publisher; [Write, Description("The publishing state for the app. The app cannot be assigned unless the app is published. Inherited from mobileApp."), ValueMap{"notPublished", "processing","published"}, Values{"notPublished", "processing", "published"}] String PublishingState; + [Write, Description("List of Scope Tag IDs for the device health script")] String RoleScopeTagIds[]; - [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; + [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppCategory")] String Categories[]; + [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppAssignment")] String Assignments[]; + [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppRelationship")] String Relationships[]; + [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppAssignmentSettings")] String Settings[]; + [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMimeContent")] String LargeIcon; + + [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; @@ -23,3 +30,52 @@ class MSFT_IntuneMobileAppsMacOSLobApp : OMI_BaseResource [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; [Write, Description("Access token used for authentication.")] String AccessTokens[]; }; + +class MSFT_DeviceManagementMobileAppCategory +{ + [Key, Description("The name of the app category.")] String DisplayName; + [Write, Description("The unique identifier for an entity. Read-only.")] String Id; +}; + +class MSFT_DeviceManagementMimeContent +{ + [Write, Description("Indicates the type of content mime.")] String Type; + [Write, Description("The byte array that contains the actual content.")] String Value[]; +}; + +class MSFT_DeviceManagementMobileAppAssignment +{ + [Write, Description("Possible values for the install intent chosen by the admin."), + ValueMap{"Available", "Required","Uninstall", "AvailableWithoutEnrollment"}, + Values{"Available", "Required","Uninstall", "AvailableWithoutEnrollment"}] + String Intent; + + [Write, Description("The group Id that is the target of the assignment.")] String groupId; + [Write, Description("The group Display Name that is the target of the assignment.")] String groupDisplayName; + [Write, Description("The type of the target assignment."), + ValueMap{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget"}, + Values{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget"}] + String odataType; #TODOK: It could be 'target' property also + + [Write, Description("The Id of the filter for the target assignment.")] String deviceAndAppManagementAssignmentFilterId; + [Write, Description("The type of filter of the target assignment i.e. Exclude or Include. Possible values are:none, include, exclude."), + ValueMap{"none","include","exclude"}, + Values{"none","include","exclude"}] + String deviceAndAppManagementAssignmentFilterType; +}; + +class MSFT_DeviceManagementMobileAppAssingmentSetting +{ + [Write, Description("The mobile app assignment setting type.")] String type; + [Write, Description("he mobile app assignment setting value.")] String value; +}; + +class MSFT_DeviceManagementMobileAppRelationship +{ + [Write, Description("The unique identifier for an entity. Read-only.")] String Id; + [Write, Description("The target mobile app's app id.")] String TargetId; + [Write, Description(" Indicates whether the target of a relationship is the parent or the child in the relationship."), + ValueMap{"Child", "Parent", "UnknownFutureValue"}, + Values{"Child", "Parent", "UnknownFutureValue"}] + String TargetType; +}; diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 84278053bf..6fd3c370c9 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -17917,7 +17917,7 @@ function New-MgBetaDeviceAppManagementMobileApp { $InformationUrl, [Parameter()] - [System.String] + [System.Boolean] $IsFeatured, [Parameter()] @@ -17967,7 +17967,7 @@ function Get-MgBetaDeviceAppManagementMobileApp { $InformationUrl, [Parameter()] - [System.String] + [System.Boolean] $IsFeatured, [Parameter()] @@ -18016,7 +18016,7 @@ function Update-MgBetaDeviceAppManagementMobileApp { $InformationUrl, [Parameter()] - [System.String] + [System.Boolean] $IsFeatured, [Parameter()] @@ -18049,47 +18049,6 @@ function Remove-MgBetaDeviceAppManagementMobileApp { [System.String] $MobileAppId, - [Parameter()] - [System.String] - $DisplayName, - - [Parameter()] - [System.String] - $Description, - - [Parameter()] - [System.String] - $Developer, - - [Parameter()] - [System.String] - $InformationUrl, - - [Parameter()] - [System.String] - $IsFeatured, - - [Parameter()] - [System.String] - $Notes, - - [Parameter()] - [System.String] - $Owner, - - [Parameter()] - [System.String] - $PrivacyInformationUrl, - - [Parameter()] - [System.String] - $Publisher, - - [Parameter()] - [System.String] - [ValidateSet('notPublished', 'processing','published')] - $PublishingState, - [Parameter()] [System.Boolean] $Confirm @@ -83258,8 +83217,7 @@ function New-MgBetaDeviceAppManagementMobileApp # TODOK $IsAssigned, [Parameter()] - #[System.Management.Automation.SwitchParameter] - [System.String] + [System.Management.Automation.SwitchParameter] $IsFeatured, [Parameter()] @@ -83387,7 +83345,11 @@ function Remove-MgBetaDeviceAppManagementMobileApp # TODOK [Parameter()] [System.Management.Automation.SwitchParameter] - $ProxyUseDefaultCredentials + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Boolean] + $Confirm ) } @@ -83457,8 +83419,7 @@ function Update-MgBetaDeviceAppManagementMobileApp # TODOK $IsAssigned, [Parameter()] - #[System.Management.Automation.SwitchParameter] - [System.String] + [System.Management.Automation.SwitchParameter] $IsFeatured, [Parameter()] From f0101e6914fb9fcaf6248aa4c05a53aa23c5f9b8 Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Thu, 3 Oct 2024 12:25:55 +0530 Subject: [PATCH 013/252] added the logic, examples and tests --- .../MSFT_EXOMigrationEndpoint.psm1} | 256 +++++++++++++--- .../MSFT_EXOMigrationEndpoint.schema.mof | 30 ++ .../MSFT_EXOMigrationEndpoint/readme.md | 6 + .../MSFT_EXOMigrationEndpoint/settings.json | 34 +++ .../MSFT_EXOMigrationEnpoint.schema.mof | 13 - .../MSFT_EXOMigrationEnpoint/readme.md | 6 - .../MSFT_EXOMigrationEnpoint/settings.json | 32 -- .../1-Create.ps1 | 0 .../EXOMigrationEndpoint/2-Update.ps1 | 42 +++ .../EXOMigrationEndpoint/3-Remove.ps1 | 40 +++ .../Resources/ResourceName/2-Update.ps1 | 26 -- .../Resources/ResourceName/3-Remove.ps1 | 26 -- ...osoft365DSC.EXOMigrationEndpoint.Tests.ps1 | 253 ++++++++++++++++ .../Microsoft365DSC.ResourceName.Tests.ps1 | 176 ----------- Tests/Unit/Stubs/Microsoft365.psm1 | 276 ++++++++++++++++++ 15 files changed, 898 insertions(+), 318 deletions(-) rename Modules/Microsoft365DSC/DSCResources/{MSFT_EXOMigrationEnpoint/MSFT_EXOMigrationEnpoint.psm1 => MSFT_EXOMigrationEndpoint/MSFT_EXOMigrationEndpoint.psm1} (58%) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEndpoint/MSFT_EXOMigrationEndpoint.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEndpoint/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEndpoint/settings.json delete mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/MSFT_EXOMigrationEnpoint.schema.mof delete mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/readme.md delete mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/settings.json rename Modules/Microsoft365DSC/Examples/Resources/{ResourceName => EXOMigrationEndpoint}/1-Create.ps1 (100%) create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/3-Remove.ps1 delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/ResourceName/2-Update.ps1 delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/ResourceName/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMigrationEndpoint.Tests.ps1 delete mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/MSFT_EXOMigrationEnpoint.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEndpoint/MSFT_EXOMigrationEndpoint.psm1 similarity index 58% rename from Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/MSFT_EXOMigrationEnpoint.psm1 rename to Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEndpoint/MSFT_EXOMigrationEndpoint.psm1 index d81da06c27..2898ab3ac5 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/MSFT_EXOMigrationEnpoint.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEndpoint/MSFT_EXOMigrationEndpoint.psm1 @@ -4,7 +4,6 @@ function Get-TargetResource [OutputType([System.Collections.Hashtable])] param ( - ##TODO - Replace the PrimaryKey [Parameter(Mandatory = $true)] [System.String] $Identity, @@ -15,7 +14,7 @@ function Get-TargetResource [Parameter()] [System.String] - $ApplicationID, + $AppID, [Parameter()] [System.String] @@ -84,8 +83,6 @@ function Get-TargetResource [System.String] $Ensure = 'Present', - ##TODO - Add the list of Parameters - [Parameter()] [System.Management.Automation.PSCredential] $Credential, @@ -111,8 +108,7 @@ function Get-TargetResource $AccessTokens ) - ##TODO - Replace the workload by the one associated to your resource - New-M365DSCConnection -Workload 'Workload' ` + New-M365DSCConnection -Workload 'ExchangeOnline' ` -InboundParameters $PSBoundParameters | Out-Null #Ensure the proper dependencies are installed in the current environment. @@ -133,29 +129,45 @@ function Get-TargetResource { if ($null -ne $Script:exportedInstances -and $Script:ExportMode) { - ##TODO - Replace the PrimaryKey in the Filter by the one for the resource - $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.PrimaryKey -eq $PrimaryKey} + $migrationEndpoint = $Script:exportedInstances | Where-Object -FilterScript {$_.Identity -eq $Identity} } else { - ##TODO - Replace the cmdlet by the one to retrieve a specific instance. - $instance = Get-cmdlet -PrimaryKey $PrimaryKey -ErrorAction Stop + $migrationEndpoint = Get-MigrationEndpoint -Identity $Identity -ErrorAction Stop } - if ($null -eq $instance) + if ($null -eq $migrationEndpoint) { return $nullResult } $results = @{ - ##TODO - Add the list of parameters to be returned - Ensure = 'Present' - Credential = $Credential - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - ManagedIdentity = $ManagedIdentity.IsPresent - AccessTokens = $AccessTokens + Identity = $Identity + AcceptUntrustedCertificates = $migrationEndpoint.AcceptUntrustedCertificates + AppID = $migrationEndpoint.AppID + AppSecretKeyVaultUrl = $migrationEndpoint.AppSecretKeyVaultUrl + Authentication = $migrationEndpoint.Authentication + EndpointType = $migrationEndpoint.EndpointType + ExchangeServer = $migrationEndpoint.ExchangeServer + MailboxPermission = $migrationEndpoint.MailboxPermission + MaxConcurrentIncrementalSyncs = $migrationEndpoint.MaxConcurrentIncrementalSyncs + MaxConcurrentMigrations = $migrationEndpoint.MaxConcurrentMigrations + NspiServer = $migrationEndpoint.NspiServer + Port = $migrationEndpoint.Port + RemoteServer = $migrationEndpoint.RemoteServer + RemoteTenant = $migrationEndpoint.RemoteTenant + RpcProxyServer = $migrationEndpoint.RpcProxyServer + Security = $migrationEndpoint.Security + SourceMailboxLegacyDN = $migrationEndpoint.SourceMailboxLegacyDN + UseAutoDiscover = $migrationEndpoint.UseAutoDiscover + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens } + return [System.Collections.Hashtable] $results } catch @@ -175,12 +187,84 @@ function Set-TargetResource [CmdletBinding()] param ( - ##TODO - Replace the PrimaryKey [Parameter(Mandatory = $true)] [System.String] - $PrimaryKey, + $Identity, + + [Parameter()] + [System.Boolean] + $AcceptUntrustedCertificates, + + [Parameter()] + [System.String] + $AppID, + + [Parameter()] + [System.String] + $AppSecretKeyVaultUrl, + + [Parameter()] + [System.String] + $Authentication, + + [Parameter()] + [ValidateSet('Exchange Remote', 'Outlook Anywhere', 'Google Workspace', 'IMAP')] + [System.String] + $EndpointType, + + [Parameter()] + [System.String] + $ExchangeServer, + + [Parameter()] + [System.String] + $MailboxPermission, + + [Parameter()] + [System.String] + $MaxConcurrentIncrementalSyncs, + + [Parameter()] + [System.String] + $MaxConcurrentMigrations, + + [Parameter()] + [System.String] + $NspiServer, + + [Parameter()] + [System.String] + $Port, + + [Parameter()] + [System.String] + $RemoteServer, + + [Parameter()] + [System.String] + $RemoteTenant, - ##TODO - Add the list of Parameters + [Parameter()] + [System.String] + $RpcProxyServer, + + [Parameter()] + [ValidateSet('None', 'Tls', 'Ssl')] + [System.String] + $Security, + + [Parameter()] + [System.String] + $SourceMailboxLegacyDN, + + [Parameter()] + [System.String] + $UseAutoDiscover, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', [Parameter()] [System.Management.Automation.PSCredential] @@ -221,25 +305,50 @@ function Set-TargetResource $currentInstance = Get-TargetResource @PSBoundParameters - $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + $setParams = [System.Collections.Hashtable]($PSBoundParameters) + $setParams = Remove-M365DSCAuthenticationParameter -BoundParameters $setParams + $setParams.Remove('RemoteTenant') + $setParams.Remove('EndpointType') + $setParams.Remove('UseAutoDiscover') + $setParams.Add('Confirm', $false) + + $newParams = [System.Collections.Hashtable]($PSBoundParameters) + $newParams = Remove-M365DSCAuthenticationParameter -BoundParameters $newParams + $newParams.Remove('EndpointType') + $newParams.Remove('Identity') + $newParams.Add('Name', $Identity) + $newParams.Add('Confirm', [Switch]$false) + + if ($EndpointType -eq "IMAP") + { + # Removing mailbox permission parameter as this is valid only for outlook anywhere migration + $setParams.Remove('MailboxPermission') + $newParams.Remove('MailboxPermission') + + # adding skip verification switch to skip verifying + # that the remote server is reachable when creating a migration endpoint. + $setParams.Add('SkipVerification', [Switch]$true) + $newParams.Add('SkipVerification', [Switch]$true) + + $newParams.Add('IMAP', [Switch]$true) + } + + # add the logic for other endpoint types ('Exchange Remote', 'Outlook Anywhere', 'Google Workspace') # CREATE if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { - ##TODO - Replace by the New cmdlet for the resource - New-Cmdlet @SetParameters + New-MigrationEndpoint @newParams } # UPDATE elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { - ##TODO - Replace by the Update/Set cmdlet for the resource - Set-cmdlet @SetParameters + Set-MigrationEndpoint @setParams } # REMOVE elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { - ##TODO - Replace by the Remove cmdlet for the resource - Remove-cmdlet @SetParameters + Remove-MigrationEndpoint -Identity $Identity } } @@ -249,12 +358,84 @@ function Test-TargetResource [OutputType([System.Boolean])] param ( - ##TODO - Replace the PrimaryKey [Parameter(Mandatory = $true)] [System.String] - $PrimaryKey, + $Identity, + + [Parameter()] + [System.Boolean] + $AcceptUntrustedCertificates, + + [Parameter()] + [System.String] + $AppID, + + [Parameter()] + [System.String] + $AppSecretKeyVaultUrl, + + [Parameter()] + [System.String] + $Authentication, - ##TODO - Add the list of Parameters + [Parameter()] + [ValidateSet('Exchange Remote', 'Outlook Anywhere', 'Google Workspace', 'IMAP')] + [System.String] + $EndpointType, + + [Parameter()] + [System.String] + $ExchangeServer, + + [Parameter()] + [System.String] + $MailboxPermission, + + [Parameter()] + [System.String] + $MaxConcurrentIncrementalSyncs, + + [Parameter()] + [System.String] + $MaxConcurrentMigrations, + + [Parameter()] + [System.String] + $NspiServer, + + [Parameter()] + [System.String] + $Port, + + [Parameter()] + [System.String] + $RemoteServer, + + [Parameter()] + [System.String] + $RemoteTenant, + + [Parameter()] + [System.String] + $RpcProxyServer, + + [Parameter()] + [ValidateSet('None', 'Tls', 'Ssl')] + [System.String] + $Security, + + [Parameter()] + [System.String] + $SourceMailboxLegacyDN, + + [Parameter()] + [System.String] + $UseAutoDiscover, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', [Parameter()] [System.Management.Automation.PSCredential] @@ -344,8 +525,7 @@ function Export-TargetResource $AccessTokens ) - ##TODO - Replace workload - $ConnectionMode = New-M365DSCConnection -Workload 'Workload' ` + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` -InboundParameters $PSBoundParameters #Ensure the proper dependencies are installed in the current environment. @@ -363,8 +543,7 @@ function Export-TargetResource try { $Script:ExportMode = $true - ##TODO - Replace Get-Cmdlet by the cmdlet to retrieve all instances - [array] $Script:exportedInstances = Get-Cmdlet -ErrorAction Stop + [array] $Script:exportedInstances = Get-MigrationEndpoint -ErrorAction Stop $i = 1 $dscContent = '' @@ -378,11 +557,10 @@ function Export-TargetResource } foreach ($config in $Script:exportedInstances) { - $displayedKey = $config.Id + $displayedKey = $config.Identity Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline $params = @{ - ##TODO - Specify the Primary Key - #PrimaryKey = $config.PrimaryKey + Identity = $config.Identity Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEndpoint/MSFT_EXOMigrationEndpoint.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEndpoint/MSFT_EXOMigrationEndpoint.schema.mof new file mode 100644 index 0000000000..8848a16f25 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEndpoint/MSFT_EXOMigrationEndpoint.schema.mof @@ -0,0 +1,30 @@ +[ClassVersion("1.0.0.0"), FriendlyName("EXOMigrationEndpoint")] +class MSFT_EXOMigrationEndpoint : OMI_BaseResource +{ + [Key, Description("Identity of the migration endpoint.")] String Identity; + [Write, Description("Specifies whether to accept untrusted certificates.")] Boolean AcceptUntrustedCertificates; + [Write, Description("The Application ID used for authentication.")] String AppID; + [Write, Description("The URL of the Key Vault that stores the application secret.")] String AppSecretKeyVaultUrl; + [Write, Description("The authentication method for the migration endpoint.")] String Authentication; + [Write, Description("The type of migration endpoint."), ValueMap{"Exchange Remote", "Outlook Anywhere", "Google Workspace", "IMAP"}, Values{"Exchange Remote", "Outlook Anywhere", "Google Workspace", "IMAP"}] String EndpointType; + [Write, Description("The Exchange Server address for the migration endpoint.")] String ExchangeServer; + [Write, Description("The mailbox permission for the migration endpoint.")] String MailboxPermission; + [Write, Description("The maximum number of concurrent incremental syncs.")] String MaxConcurrentIncrementalSyncs; + [Write, Description("The maximum number of concurrent migrations.")] String MaxConcurrentMigrations; + [Write, Description("The NSPI server for the migration endpoint.")] String NspiServer; + [Write, Description("The port number for the migration endpoint.")] String Port; + [Write, Description("The remote server for the migration endpoint.")] String RemoteServer; + [Write, Description("The remote tenant for the migration endpoint.")] String RemoteTenant; + [Write, Description("The RPC proxy server for the migration endpoint.")] String RpcProxyServer; + [Write, Description("The security level for the migration endpoint."), ValueMap{"None", "Tls", "Ssl"}, Values{"None", "Tls", "Ssl"}] String Security; + [Write, Description("The legacy distinguished name of the source mailbox.")] String SourceMailboxLegacyDN; + [Write, Description("Specifies whether to use AutoDiscover.")] Boolean UseAutoDiscover; + + [Write, Description("Specifies if the migration endpoint should exist or not."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; + [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEndpoint/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEndpoint/readme.md new file mode 100644 index 0000000000..a5d359017c --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEndpoint/readme.md @@ -0,0 +1,6 @@ + +# EXOMigrationEndpoint + +## Description + +Use this resource to create and monitor migration endpoints in exchange. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEndpoint/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEndpoint/settings.json new file mode 100644 index 0000000000..d223f925cd --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEndpoint/settings.json @@ -0,0 +1,34 @@ +{ + "resourceName": "EXOMigrationEndpoint", + "description": "Use this resource to create and monitor migration endpoint in exchange", + "roles": { + "read": [ + "Global Reader" + ], + "update": [ + "Exchange Administrator" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + }, + "exchange": { + "requiredroles": [ + "Recipient Policies", + "View-Only Recipients", + "Mail Recipient Creation", + "View-Only Configuration", + "Mail Recipients" + ], + "requiredrolegroups": "Organization Management" + } + } +} diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/MSFT_EXOMigrationEnpoint.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/MSFT_EXOMigrationEnpoint.schema.mof deleted file mode 100644 index 6fa43ce435..0000000000 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/MSFT_EXOMigrationEnpoint.schema.mof +++ /dev/null @@ -1,13 +0,0 @@ -[ClassVersion("1.0.0.0"), FriendlyName("ResourceName")] -class MSFT_ResourceName : OMI_BaseResource -{ - [Key, Description("")] String PrimaryKey; - [Write, Description("")] String OtherProperties; - - [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; - [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; - [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; - [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; - [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; - [Write, Description("Access token used for authentication.")] String AccessTokens[]; -}; \ No newline at end of file diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/readme.md deleted file mode 100644 index 32e0e7fb27..0000000000 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/readme.md +++ /dev/null @@ -1,6 +0,0 @@ - -# ResourceName - -## Description - -##TODO - Provide a short description of what the resource is set to configure. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/settings.json deleted file mode 100644 index edf14b05e4..0000000000 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEnpoint/settings.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "resourceName": "ResourceName", - "description": "Description of what the resource is about.", - "roles": { - "read": [ - "Role" - ], - "update": [ - "Role" - ] - }, - "permissions": { - "graph": { - "delegated": { - "read": [], - "update": [] - }, - "application": { - "read": [ - { - "name": "Permission for Monitoring and Export" - } - ], - "update": [ - { - "name": "Permission for deploying" - } - ] - } - } - } -} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/1-Create.ps1 similarity index 100% rename from Modules/Microsoft365DSC/Examples/Resources/ResourceName/1-Create.ps1 rename to Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/1-Create.ps1 diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/2-Update.ps1 new file mode 100644 index 0000000000..4ec28ef8fc --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/2-Update.ps1 @@ -0,0 +1,42 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOMigrationEndpoint "EXOMigrationEndpoint-testIMAP" + { + AcceptUntrustedCertificates = $True; + Authentication = "Basic"; + Credential = $Credscredential; + EndpointType = "IMAP"; + Ensure = "Present"; + Identity = "testIMAP"; + MailboxPermission = "Admin"; + MaxConcurrentIncrementalSyncs = "10"; + MaxConcurrentMigrations = "20"; + Port = 993; + RemoteServer = "gmail.com"; + # value for security updated from Tls to None + Security = "None"; + } + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/3-Remove.ps1 new file mode 100644 index 0000000000..9ac7745bec --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/3-Remove.ps1 @@ -0,0 +1,40 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOMigrationEndpoint "EXOMigrationEndpoint-testIMAP" + { + AcceptUntrustedCertificates = $True; + Authentication = "Basic"; + Credential = $Credscredential; + EndpointType = "IMAP"; + Ensure = "Absent"; + Identity = "testIMAP"; + MailboxPermission = "Admin"; + MaxConcurrentIncrementalSyncs = "10"; + MaxConcurrentMigrations = "20"; + Port = 993; + RemoteServer = "gmail.com"; + Security = "None"; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ResourceName/2-Update.ps1 deleted file mode 100644 index b516274848..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/2-Update.ps1 +++ /dev/null @@ -1,26 +0,0 @@ -<# -This example is used to test new resources and showcase the usage of new resources being worked on. -It is not meant to use as a production baseline. -#> - -Configuration Example -{ - param( - [Parameter()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint - ) - Import-DscResource -ModuleName Microsoft365DSC - node localhost - { - - } -} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ResourceName/3-Remove.ps1 deleted file mode 100644 index b516274848..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/3-Remove.ps1 +++ /dev/null @@ -1,26 +0,0 @@ -<# -This example is used to test new resources and showcase the usage of new resources being worked on. -It is not meant to use as a production baseline. -#> - -Configuration Example -{ - param( - [Parameter()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint - ) - Import-DscResource -ModuleName Microsoft365DSC - node localhost - { - - } -} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMigrationEndpoint.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMigrationEndpoint.Tests.ps1 new file mode 100644 index 0000000000..1afff8ab03 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMigrationEndpoint.Tests.ps1 @@ -0,0 +1,253 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -GenericStubModule $GenericStubPath + +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + Mock -CommandName Get-MigrationEndpoint -MockWith { + } + + Mock -CommandName Set-MigrationEndpoint -MockWith { + } + + Mock -CommandName New-MigrationEndpoint -MockWith { + } + + Mock -CommandName Remove-MigrationEndpoint -MockWith { + } + + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + Context -Name "The instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + AcceptUntrustedCertificates = $True; + Authentication = "Basic"; + EndpointType = "IMAP"; + Identity = "testIMAP"; + MailboxPermission = "Admin"; + MaxConcurrentIncrementalSyncs = "10"; + MaxConcurrentMigrations = "20"; + Port = 993; + RemoteServer = "gmail.com"; + Security = "Tls"; + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-MigrationEndpoint -MockWith { + return $null + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should create a new instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-MigrationEndpoint -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + AcceptUntrustedCertificates = $True; + Authentication = "Basic"; + EndpointType = "IMAP"; + Identity = "testIMAP"; + MailboxPermission = "Admin"; + MaxConcurrentIncrementalSyncs = "10"; + MaxConcurrentMigrations = "20"; + Port = 993; + RemoteServer = "gmail.com"; + Security = "Tls"; + Ensure = 'Absent' + Credential = $Credential; + } + + Mock -CommandName Get-MigrationEndpoint -MockWith { + return @{ + AcceptUntrustedCertificates = $True; + Authentication = "Basic"; + EndpointType = "IMAP"; + Identity = "testIMAP"; + MailboxPermission = "Admin"; + MaxConcurrentIncrementalSyncs = "10"; + MaxConcurrentMigrations = "20"; + Port = 993; + RemoteServer = "gmail.com"; + Security = "Tls"; + } + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should remove the instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-MigrationEndpoint -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + AcceptUntrustedCertificates = $True; + Authentication = "Basic"; + EndpointType = "IMAP"; + Identity = "testIMAP"; + MailboxPermission = "Admin"; + MaxConcurrentIncrementalSyncs = "10"; + MaxConcurrentMigrations = "20"; + Port = 993; + RemoteServer = "gmail.com"; + Security = "Tls"; + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-MigrationEndpoint -MockWith { + return @{ + AcceptUntrustedCertificates = $True; + Authentication = "Basic"; + EndpointType = "IMAP"; + Identity = "testIMAP"; + MailboxPermission = "Admin"; + MaxConcurrentIncrementalSyncs = "10"; + MaxConcurrentMigrations = "20"; + Port = 993; + RemoteServer = "gmail.com"; + Security = "Tls"; + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + AcceptUntrustedCertificates = $True; + Authentication = "Basic"; + EndpointType = "IMAP"; + Identity = "testIMAP"; + MailboxPermission = "Admin"; + MaxConcurrentIncrementalSyncs = "10"; + MaxConcurrentMigrations = "20"; + Port = 993; + RemoteServer = "gmail.com"; + Security = "Tls"; + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-MigrationEndpoint -MockWith { + return @{ + AcceptUntrustedCertificates = $True; + Authentication = "Basic"; + EndpointType = "IMAP"; + Identity = "testIMAP"; + MailboxPermission = "Admin"; + MaxConcurrentIncrementalSyncs = "10"; + MaxConcurrentMigrations = "20"; + Port = 993; + RemoteServer = "gmail.com"; + Security = "None"; + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Set-MigrationEndpoint -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + Mock -CommandName Get-MigrationEndpoint -MockWith { + return @{ + AcceptUntrustedCertificates = $True; + Authentication = "Basic"; + EndpointType = "IMAP"; + Identity = "testIMAP"; + MailboxPermission = "Admin"; + MaxConcurrentIncrementalSyncs = "10"; + MaxConcurrentMigrations = "20"; + Port = 993; + RemoteServer = "gmail.com"; + Security = "Tls"; + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 deleted file mode 100644 index 20857e0393..0000000000 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 +++ /dev/null @@ -1,176 +0,0 @@ -[CmdletBinding()] -param( -) -$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` - -ChildPath '..\..\Unit' ` - -Resolve -$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` - -ChildPath '\Stubs\Microsoft365.psm1' ` - -Resolve) -$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` - -ChildPath '\Stubs\Generic.psm1' ` - -Resolve) -Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` - -ChildPath '\UnitTestHelper.psm1' ` - -Resolve) - -$CurrentScriptPath = $PSCommandPath.Split('\') -$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] -$ResourceName = $CurrentScriptName.Split('.')[1] -$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` - -DscResource $ResourceName -GenericStubModule $GenericStubPath - -Describe -Name $Global:DscHelper.DescribeHeader -Fixture { - InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { - Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope - BeforeAll { - - $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force - $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) - - Mock -CommandName Confirm-M365DSCDependencies -MockWith { - } - - Mock -CommandName New-M365DSCConnection -MockWith { - return "Credentials" - } - - ##TODO - Mock any Remove/Set/New cmdlets - - # Mock Write-Host to hide output during the tests - Mock -CommandName Write-Host -MockWith { - } - $Script:exportedInstances =$null - $Script:ExportMode = $false - } - # Test contexts - Context -Name "The instance should exist but it DOES NOT" -Fixture { - BeforeAll { - $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; - } - - ##TODO - Mock the Get-Cmdlet to return $null - Mock -CommandName Get-Cmdlet -MockWith { - return $null - } - } - It 'Should return Values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' - } - It 'Should return false from the Test method' { - Test-TargetResource @testParams | Should -Be $false - } - - It 'Should create a new instance from the Set method' { - ##TODO - Replace the New-Cmdlet by the appropriate one - Should -Invoke -CommandName New-Cmdlet -Exactly 1 - } - } - - Context -Name "The instance exists but it SHOULD NOT" -Fixture { - BeforeAll { - $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Absent' - Credential = $Credential; - } - - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { - return @{ - - } - } - } - It 'Should return Values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Present' - } - It 'Should return false from the Test method' { - Test-TargetResource @testParams | Should -Be $false - } - - It 'Should remove the instance from the Set method' { - ##TODO - Replace the Remove-Cmdlet by the appropriate one - Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 - } - } - - Context -Name "The instance exists and values are already in the desired state" -Fixture { - BeforeAll { - $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; - } - - ##TODO - Mock the Get-Cmdlet to return the desired values - Mock -CommandName Get-Cmdlet -MockWith { - return @{ - - } - } - } - - It 'Should return true from the Test method' { - Test-TargetResource @testParams | Should -Be $true - } - } - - Context -Name "The instance exists and values are NOT in the desired state" -Fixture { - BeforeAll { - $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; - } - - ##TODO - Mock the Get-Cmdlet to return a drift - Mock -CommandName Get-Cmdlet -MockWith { - return @{ - - } - } - } - - It 'Should return Values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Present' - } - - It 'Should return false from the Test method' { - Test-TargetResource @testParams | Should -Be $false - } - - It 'Should call the Set method' { - Set-TargetResource @testParams - ##TODO - Replace the Update-Cmdlet by the appropriate one - Should -Invoke -CommandName Update-Cmdlet -Exactly 1 - } - } - - Context -Name 'ReverseDSC Tests' -Fixture { - BeforeAll { - $Global:CurrentModeIsExport = $true - $Global:PartialExportFileName = "$(New-Guid).partial.ps1" - $testParams = @{ - Credential = $Credential; - } - - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { - return @{ - - } - } - } - It 'Should Reverse Engineer resource from the Export method' { - $result = Export-TargetResource @testParams - $result | Should -Not -BeNullOrEmpty - } - } - } -} - -Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index d8d8db6694..a60f853733 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -1405,6 +1405,282 @@ function Remove-MgBetaRoleManagementEntitlementManagementRoleAssignment ) } +function Get-MigrationEndpoint +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $DiagnosticInfo, + + [Parameter()] + [System.Object] + $Type, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Object] + $Partition + ) +} + +function Set-MigrationEndpoint +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Boolean] + $AcceptUntrustedCertificates, + + [Parameter()] + [System.Object] + $MaxConcurrentMigrations, + + [Parameter()] + [System.Byte[]] + $ServiceAccountKeyFileData, + + [Parameter()] + [System.Object] + $TestMailbox, + + [Parameter()] + [System.String] + $ExchangeServer, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $SkipVerification, + + [Parameter()] + [System.Object] + $Authentication, + + [Parameter()] + [System.String] + $AppSecretKeyVaultUrl, + + [Parameter()] + [System.Object] + $Port, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.Object] + $RemoteServer, + + [Parameter()] + [System.Object] + $Partition, + + [Parameter()] + [System.Object] + $MailboxPermission, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.String] + $SourceMailboxLegacyDN, + + [Parameter()] + [System.String] + $NspiServer, + + [Parameter()] + [System.Object] + $RPCProxyServer, + + [Parameter()] + [System.String] + $PublicFolderDatabaseServerLegacyDN, + + [Parameter()] + [System.Object] + $Security, + + [Parameter()] + [System.Object] + $MaxConcurrentIncrementalSyncs, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credentials + ) +} + +function New-MigrationEndpoint +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $AcceptUntrustedCertificates, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ExchangeRemoteMove, + + [Parameter()] + [System.Object] + $MaxConcurrentMigrations, + + [Parameter()] + [System.Byte[]] + $ServiceAccountKeyFileData, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PublicFolder, + + [Parameter()] + [System.Object] + $TestMailbox, + + [Parameter()] + [System.String] + $ExchangeServer, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $SkipVerification, + + [Parameter()] + [System.Object] + $Authentication, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ExchangeOutlookAnywhere, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Gmail, + + [Parameter()] + [System.String] + $AppSecretKeyVaultUrl, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Compliance, + + [Parameter()] + [System.Int32] + $Port, + + [Parameter()] + [System.Security.SecureString] + $OAuthCode, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.Object] + $RemoteServer, + + [Parameter()] + [System.Object] + $Partition, + + [Parameter()] + [System.Object] + $MailboxPermission, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.String] + $SourceMailboxLegacyDN, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IMAP, + + [Parameter()] + [System.String] + $RemoteTenant, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PublicFolderToUnifiedGroup, + + [Parameter()] + [System.String] + $NspiServer, + + [Parameter()] + [System.String] + $RedirectUri, + + [Parameter()] + [System.Object] + $RPCProxyServer, + + [Parameter()] + [System.Object] + $EmailAddress, + + [Parameter()] + [System.Object] + $Security, + + [Parameter()] + [System.Object] + $MaxConcurrentIncrementalSyncs, + + [Parameter()] + [System.String] + $PublicFolderDatabaseServerLegacyDN, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credentials, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Autodiscover + ) +} + +function Remove-MigrationEndpoint +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Object] + $Partition + ) +} + function Set-ManagementRoleEntry { [CmdletBinding()] From 2f4f0bb760e3ea1f58fc5d0277df08db66eb0888 Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Thu, 3 Oct 2024 12:28:36 +0530 Subject: [PATCH 014/252] updated changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2196377267..95054c78ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change log for Microsoft365DSC +# Unreleased + +* EXOMigrationEndpoint + * Initial Release + # 1.24.1002.1 * AADAdministrativeUnit From dc9142beb4df6d3c0aa83ce9b371a65379ecae22 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Thu, 3 Oct 2024 00:14:15 -0700 Subject: [PATCH 015/252] Adding some code related to Category complex type handling. --- .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 242 +++++++++++++++++- ...SFT_IntuneMobileAppsMacOSLobApp.schema.mof | 45 ++-- .../Modules/M365DSCDRGUtil.psm1 | 173 +++++++++++++ ...5DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 | 26 +- Tests/Unit/Stubs/Microsoft365.psm1 | 30 ++- 5 files changed, 473 insertions(+), 43 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 index f3cbe068a8..4c83dc7f80 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 @@ -51,6 +51,14 @@ function Get-TargetResource [ValidateSet('notPublished', 'processing','published')] $PublishingState, + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Categories, + #endregion [Parameter()] @@ -112,13 +120,20 @@ function Get-TargetResource } else { - $instance = Get-MgBetaDeviceAppManagementMobileApp -MobileAppId $Id -Filter "microsoft.graph.managedApp/appAvailability eq null" -ErrorAction Stop + $instance = Get-MgBetaDeviceAppManagementMobileApp ` + -MobileAppId $Id ` + -Filter "microsoft.graph.managedApp/appAvailability eq null" ` + -ExpandProperty "categories,assignments" ` + -ErrorAction Stop } if ($null -eq $instance) { Write-Verbose -Message "No Mobile app with Id {$Id} was found. Search with DisplayName." - $instance = Get-MgBetaDeviceAppManagementMobileApp -Filter "displayName eq '$DisplayName'" -ErrorAction SilentlyContinue + $instance = Get-MgBetaDeviceAppManagementMobileApp ` + -Filter "displayName eq '$DisplayName'" ` + -ExpandProperty "categories,assignments" ` + -ErrorAction SilentlyContinue } if ($null -eq $instance) @@ -131,19 +146,19 @@ function Get-TargetResource $results = @{ Id = $instance.Id - #Assignments = $instance.Assignments - #Categories = $instance.Categories Description = $instance.Description Developer = $instance.Developer DisplayName = $instance.DisplayName InformationUrl = $instance.InformationUrl IsFeatured = $instance.IsFeatured - #LargeIcon = $instance.LargeIcon Notes = $instance.Notes Owner = $instance.Owner PrivacyInformationUrl = $instance.PrivacyInformationUrl Publisher = $instance.Publisher PublishingState = $instance.PublishingState + RoleScopeTagIds = $instance.RoleScopeTagIds + Categories = $instance.Categories + Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId @@ -154,6 +169,17 @@ function Get-TargetResource AccessTokens = $AccessTokens } + #TODOK + # $resultAssignments = @() + # $appAssignments = Get-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $configPolicy.Id + # if ($appAssignments.count -gt 0) + # { + # $resultAssignments += ConvertFrom-IntuneMobileAppAssignment ` + # -IncludeDeviceFilter:$true ` + # -Assignments ($appAssignments) + # } + # $returnHashtable.Add('Assignments', $resultAssignments) + return [System.Collections.Hashtable] $results } catch @@ -221,6 +247,14 @@ function Set-TargetResource [ValidateSet('notPublished', 'processing','published')] $PublishingState, + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Categories, + #endregion [Parameter()] @@ -278,12 +312,45 @@ function Set-TargetResource # CREATE if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { + if($null -ne $Categories) + { + [System.Object[]]$categoriesValue = ConvertTo-M365DSCIntuneAppCategories -Categories $Categories + $setParameters.Add('Categories', $categoriesValue) + } + + #$app = New-MgBetaDeviceAppManagementMobileApp @SetParameters + New-MgBetaDeviceAppManagementMobileApp @SetParameters + + #TODOK + # $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + # if ($app.id) + # { + # Update-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $app.id ` + # -Targets $assignmentsHash ` + # -Repository 'deviceAppManagement/mobileAppAssignments' + # } + } # UPDATE elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { + if($null -ne $Categories) + { + [System.Object[]]$categoriesValue = ConvertTo-M365DSCIntuneAppCategories -Categories $Categories + $setParameters.Add('Categories', $categoriesValue) + } + Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id @SetParameters + + #TODOK + # $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + # if ($app.id) + # { + # Update-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $app.id ` + # -Targets $assignmentsHash ` + # -Repository 'deviceAppManagement/mobileAppAssignments' + # } } # REMOVE elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') @@ -345,6 +412,14 @@ function Test-TargetResource [ValidateSet('notPublished', 'processing','published')] $PublishingState, + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Categories, + #endregion [Parameter()] @@ -462,7 +537,10 @@ function Export-TargetResource try { $Script:ExportMode = $true - [array] $Script:exportedInstances = Get-MgBetaDeviceAppManagementMobileApp -Filter "microsoft.graph.managedApp/appAvailability eq null" -ErrorAction Stop + [array] $Script:exportedInstances = Get-MgBetaDeviceAppManagementMobileApp ` + -Filter "microsoft.graph.managedApp/appAvailability eq null" ` + -ExpandProperty "categories,assignments" ` + -ErrorAction Stop $i = 1 $dscContent = '' @@ -490,6 +568,11 @@ function Export-TargetResource PrivacyInformationUrl = $config.PrivacyInformationUrl Publisher = $config.Publisher PublishingState = $config.PublishingState + RoleScopeTagIds = $config.RoleScopeTagIds + Categories = $config.Categories + # LargeIcon = $config.LargeIcon + # ChildApps = $config.ChildApps + Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId @@ -500,7 +583,25 @@ function Export-TargetResource AccessTokens = $AccessTokens } + $Params.remove('Md5HashChunkSize') | Out-Null $Results = Get-TargetResource @Params + + #region complex types + + + if (-not (Test-M365DSCAuthenticationParameter -BoundParameters $Results)) + { + Write-Verbose "An error occured in Get-TargetResource, the app {$($params.displayName)} will not be processed." + throw "An error occured in Get-TargetResource, the app {$($params.displayName)} will not be processed. Refer to the event viewer logs for more information." + } + + if ($Results.Categories.Count -gt 0) + { + $Results.Categories = Get-M365DSCIntuneAppCategoriesAsString -Categories $Results.Categories + } + + #endregion complex types + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` -Results $Results @@ -509,6 +610,16 @@ function Export-TargetResource -ModulePath $PSScriptRoot ` -Results $Results ` -Credential $Credential + + #region complex types + + if ($null -ne $Results.Categories) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Categories' + } + + #endregion complex types + $dscContent += $currentDSCBlock Save-M365DSCPartialExport -Content $currentDSCBlock ` -FileName $Global:PartialExportFileName @@ -532,4 +643,123 @@ function Export-TargetResource } } +#region Helper functions + +function ConvertTo-M365DSCIntuneAppAssignmentSettings +{ + [OutputType([System.Object[]])] + param( + [Parameter(Mandatory = $true)] + [System.Collections.ArrayList] + $Settings + ) + + $result = @() + foreach ($setting in $Settings) + { + $currentSetting = @{ + name = $setting.name + value = $setting.value + } + $result += $currentSetting + } + + return $result +} + +function Get-M365DSCIntuneAppAssignmentSettingsAsString +{ + [CmdletBinding()] + [OutputType([System.String])] + param( + [Parameter(Mandatory = $true)] + [System.Object[]] + $Settings + ) + + $StringContent = '@(' + $space = ' ' + $indent = ' ' + + $i = 1 + foreach ($setting in $Settings) + { + if ($Settings.Count -gt 1) + { + $StringContent += "`r`n" + $StringContent += "$space" + } + + $StringContent += "MSFT_DeviceManagementMobileAppAssignmentSettings { `r`n" + $StringContent += "$($space)$($indent)name = '" + $setting.name + "'`r`n" + $StringContent += "$($space)$($indent)value = '" + $setting.value + "'`r`n" + $StringContent += "$space}" + + $i++ + } + + $StringContent += ')' + return $StringContent +} + +function ConvertTo-M365DSCIntuneAppCategories +{ + [OutputType([System.Object[]])] + param( + [Parameter(Mandatory = $true)] + [System.Collections.ArrayList] + $Categories + ) + + $result = @() + foreach ($category in $Categories) + { + $currentCategory = @{ + name = $category.id + value = $category.displayName + } + + $result += $currentCategory + } + + return $result +} + +function Get-M365DSCIntuneAppCategoriesAsString +{ + [CmdletBinding()] + [OutputType([System.String])] + param( + [Parameter(Mandatory = $true)] + [System.Object[]] + $Categories + ) + + $StringContent = '@(' + $space = ' ' + $indent = ' ' + + $i = 1 + foreach ($category in $Categories) + { + if ($Categories.Count -gt 1) + { + $StringContent += "`r`n" + $StringContent += "$space" + } + + $StringContent += "MSFT_DeviceManagementMobileAppCategory { `r`n" + $StringContent += "$($space)$($indent)id = '" + $category.id + "'`r`n" + $StringContent += "$($space)$($indent)displyName = '" + $category.displayName + "'`r`n" + $StringContent += "$space}" + + $i++ + } + + $StringContent += ')' + return $StringContent +} + +#endregion Helper functions + Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof index b250cb9101..72e087fbee 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof @@ -15,11 +15,17 @@ class MSFT_IntuneMobileAppsMacOSLobApp : OMI_BaseResource [Write, Description("The publishing state for the app. The app cannot be assigned unless the app is published. Inherited from mobileApp."), ValueMap{"notPublished", "processing","published"}, Values{"notPublished", "processing", "published"}] String PublishingState; [Write, Description("List of Scope Tag IDs for the device health script")] String RoleScopeTagIds[]; - [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppCategory")] String Categories[]; - [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppAssignment")] String Assignments[]; - [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppRelationship")] String Relationships[]; - [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppAssignmentSettings")] String Settings[]; - [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMimeContent")] String LargeIcon; + [Write, Description("The bundleId of the app.")] String FileName; + [Write, Description("The bundleId of the app.")] Int32 Md5HashChunkSize; + [Write, Description("The build number of the app.")] String Md5Hash[]; + [Write, Description("The version number of the app.")] String InstallAsManaged; + [Write, Description("The version number of the app.")] String IgnoreVersionDetection; + [Write, Description("The bundleId of the app.")] String BundleId; + [Write, Description("The build number of the app.")] String BuildNumber; + [Write, Description("The version number of the app.")] String VersionNumber; + + [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppCategory")] String Categories[]; + [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; @@ -33,14 +39,8 @@ class MSFT_IntuneMobileAppsMacOSLobApp : OMI_BaseResource class MSFT_DeviceManagementMobileAppCategory { - [Key, Description("The name of the app category.")] String DisplayName; - [Write, Description("The unique identifier for an entity. Read-only.")] String Id; -}; - -class MSFT_DeviceManagementMimeContent -{ - [Write, Description("Indicates the type of content mime.")] String Type; - [Write, Description("The byte array that contains the actual content.")] String Value[]; + [Key, Description("The name of the app category.")] String displayName; + [Write, Description("The unique identifier for an entity. Read-only.")] String id; }; class MSFT_DeviceManagementMobileAppAssignment @@ -49,13 +49,14 @@ class MSFT_DeviceManagementMobileAppAssignment ValueMap{"Available", "Required","Uninstall", "AvailableWithoutEnrollment"}, Values{"Available", "Required","Uninstall", "AvailableWithoutEnrollment"}] String Intent; + [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppAssignmentSettings")] String Settings[]; [Write, Description("The group Id that is the target of the assignment.")] String groupId; [Write, Description("The group Display Name that is the target of the assignment.")] String groupDisplayName; [Write, Description("The type of the target assignment."), ValueMap{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget"}, Values{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget"}] - String odataType; #TODOK: It could be 'target' property also + String odataType; [Write, Description("The Id of the filter for the target assignment.")] String deviceAndAppManagementAssignmentFilterId; [Write, Description("The type of filter of the target assignment i.e. Exclude or Include. Possible values are:none, include, exclude."), @@ -63,19 +64,3 @@ class MSFT_DeviceManagementMobileAppAssignment Values{"none","include","exclude"}] String deviceAndAppManagementAssignmentFilterType; }; - -class MSFT_DeviceManagementMobileAppAssingmentSetting -{ - [Write, Description("The mobile app assignment setting type.")] String type; - [Write, Description("he mobile app assignment setting value.")] String value; -}; - -class MSFT_DeviceManagementMobileAppRelationship -{ - [Write, Description("The unique identifier for an entity. Read-only.")] String Id; - [Write, Description("The target mobile app's app id.")] String TargetId; - [Write, Description(" Indicates whether the target of a relationship is the parent or the child in the relationship."), - ValueMap{"Child", "Parent", "UnknownFutureValue"}, - Values{"Child", "Parent", "UnknownFutureValue"}] - String TargetType; -}; diff --git a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 index 6bf838c5d6..bef790b91f 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 @@ -1252,6 +1252,179 @@ function ConvertTo-IntunePolicyAssignment return ,$assignmentResult } +function ConvertFrom-IntuneMobileAppAssignment +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable[]])] + param ( + [Parameter(Mandatory = $true)] + [Array] + $Assignments, + [Parameter()] + [System.Boolean] + $IncludeDeviceFilter = $true + ) + + $assignmentResult = @() + foreach ($assignment in $Assignments) + { + $hashAssignment = @{} + if ($null -ne $assignment.Target.'@odata.type') + { + $dataType = $assignment.Target.'@odata.type' + } + else + { + $dataType = $assignment.Target.AdditionalProperties.'@odata.type' + } + + if ($null -ne $assignment.Target.groupId) + { + $groupId = $assignment.Target.groupId + } + else + { + $groupId = $assignment.Target.AdditionalProperties.groupId + } + + # if ($null -ne $assignment.Target.collectionId) TODOK: remove this if not needed + # { + # $collectionId = $assignment.Target.collectionId + # } + # else + # { + # $collectionId = $assignment.Target.AdditionalProperties.collectionId + # } + + $hashAssignment.Add('dataType',$dataType) + if (-not [string]::IsNullOrEmpty($groupId)) + { + $hashAssignment.Add('groupId', $groupId) + + $group = Get-MgGroup -GroupId ($groupId) -ErrorAction SilentlyContinue + if ($null -ne $group) + { + $groupDisplayName = $group.DisplayName + } + } + + # if (-not [string]::IsNullOrEmpty($collectionId)) + # { + # $hashAssignment.Add('collectionId', $collectionId) + # } + + if ($dataType -eq '#microsoft.graph.allLicensedUsersAssignmentTarget') + { + $groupDisplayName = 'All users' + } + if ($dataType -eq '#microsoft.graph.allDevicesAssignmentTarget') + { + $groupDisplayName = 'All devices' + } + if ($null -ne $groupDisplayName) + { + $hashAssignment.Add('groupDisplayName', $groupDisplayName) + } + if ($IncludeDeviceFilter) + { + if ($null -ne $assignment.Target.DeviceAndAppManagementAssignmentFilterType) + { + $hashAssignment.Add('deviceAndAppManagementAssignmentFilterType', $assignment.Target.DeviceAndAppManagementAssignmentFilterType.ToString()) + } + if ($null -ne $assignment.Target.DeviceAndAppManagementAssignmentFilterId) + { + $hashAssignment.Add('deviceAndAppManagementAssignmentFilterId', $assignment.Target.DeviceAndAppManagementAssignmentFilterId) + } + } + + $assignmentResult += $hashAssignment + } + + return ,$assignmentResult +} + +function ConvertTo-IntunePolicyAssignment +{ + [CmdletBinding()] + [OutputType([Hashtable[]])] + param ( + [Parameter(Mandatory = $true)] + [AllowNull()] + $Assignments, + [Parameter()] + [System.Boolean] + $IncludeDeviceFilter = $true + ) + + if ($null -eq $Assignments) + { + return ,@() + } + + $assignmentResult = @() + foreach ($assignment in $Assignments) + { + $target = @{"@odata.type" = $assignment.dataType} + if ($IncludeDeviceFilter) + { + if ($null -ne $assignment.DeviceAndAppManagementAssignmentFilterType) + { + $target.Add('deviceAndAppManagementAssignmentFilterType', $assignment.DeviceAndAppManagementAssignmentFilterType) + $target.Add('deviceAndAppManagementAssignmentFilterId', $assignment.DeviceAndAppManagementAssignmentFilterId) + } + } + if ($assignment.dataType -like '*CollectionAssignmentTarget') + { + $target.add('collectionId', $assignment.collectionId) + } + elseif ($assignment.dataType -like '*GroupAssignmentTarget') + { + $group = Get-MgGroup -GroupId ($assignment.groupId) -ErrorAction SilentlyContinue + if ($null -eq $group) + { + if ($assignment.groupDisplayName) + { + $group = Get-MgGroup -Filter "DisplayName eq '$($assignment.groupDisplayName)'" -ErrorAction SilentlyContinue + if ($null -eq $group) + { + $message = "Skipping assignment for the group with DisplayName {$($assignment.groupDisplayName)} as it could not be found in the directory.`r`n" + $message += "Please update your DSC resource extract with the correct groupId or groupDisplayName." + Write-Verbose -Message $message + $target = $null + } + if ($group -and $group.Count -gt 1) + { + $message = "Skipping assignment for the group with DisplayName {$($assignment.groupDisplayName)} as it is not unique in the directory.`r`n" + $message += "Please update your DSC resource extract with the correct groupId or a unique group DisplayName." + Write-Verbose -Message $message + $group = $null + $target = $null + } + } + else + { + $message = "Skipping assignment for the group with Id {$($assignment.groupId)} as it could not be found in the directory.`r`n" + $message += "Please update your DSC resource extract with the correct groupId or a unique group DisplayName." + Write-Verbose -Message $message + $target = $null + } + } + #Skipping assignment if group not found from either groupId or groupDisplayName + if ($null -ne $group) + { + $target.Add('groupId', $group.Id) + } + } + + if ($target) + { + $assignmentResult += @{target = $target} + } + } + + return ,$assignmentResult +} + function Compare-M365DSCIntunePolicyAssignment { [CmdletBinding()] diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 index 809bbe30d6..74faabfe86 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 @@ -65,6 +65,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { PrivacyInformationUrl = "" Publisher = "Contoso" PublishingState = "published" + RoleScopeTagIds = @() + Category = "Productivity" Ensure = 'Present' Credential = $Credential } @@ -73,13 +75,13 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { return $null } } + It '1.1 Should return Values from the Get method' { (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' } It '1.2 Should return false from the Test method' { Test-TargetResource @testParams | Should -Be $false } - It '1.3 Should create a new instance from the Set method' { Set-TargetResource @testParams Should -Invoke -CommandName New-MgBetaDeviceAppManagementMobileApp -Exactly 1 @@ -100,6 +102,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { PrivacyInformationUrl = "" Publisher = "Contoso" PublishingState = "published" + RoleScopeTagIds = @() + Category = "Productivity" Ensure = 'Absent' Credential = $Credential } @@ -117,16 +121,18 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { PrivacyInformationUrl = "" Publisher = "Contoso" PublishingState = "published" + RoleScopeTagIds = @() + Category = "Productivity" } } } + It '2.1 Should return Values from the Get method' { (Get-TargetResource @testParams).Ensure | Should -Be 'Present' } It '2.2 Should return false from the Test method' { Test-TargetResource @testParams | Should -Be $false } - It '2.3 Should remove the instance from the Set method' { Set-TargetResource @testParams Should -Invoke -CommandName Remove-MgBetaDeviceAppManagementMobileApp -Exactly 1 @@ -147,6 +153,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { PrivacyInformationUrl = "" Publisher = "Contoso" PublishingState = "published" + RoleScopeTagIds = @() + Category = "Productivity" Ensure = 'Present' Credential = $Credential; } @@ -164,6 +172,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { PrivacyInformationUrl = "" Publisher = "Contoso" PublishingState = "published" + RoleScopeTagIds = @() + Category = "Productivity" } } } @@ -187,6 +197,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { PrivacyInformationUrl = "" Publisher = "Contoso" PublishingState = "published" + RoleScopeTagIds = @() + Category = "Productivity" Ensure = 'Present' Credential = $Credential; } @@ -204,6 +216,11 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { PrivacyInformationUrl = "" Publisher = "Contoso" PublishingState = "published" + RoleScopeTagIds = @() + Categories = @(MSFT_DeviceManagementMobileAppCategory { + id = '1bff2652-03ec-4a48-941c-152e93736515' + displyName = 'Kajal 3' + }); } } } @@ -211,11 +228,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It '4.1 Should return Values from the Get method' { (Get-TargetResource @testParams).Ensure | Should -Be 'Present' } - It '4.2 Should return false from the Test method' { Test-TargetResource @testParams | Should -Be $false } - It '4.3 Should call the Set method' { Set-TargetResource @testParams Should -Invoke -CommandName Update-MgBetaDeviceAppManagementMobileApp -Exactly 1 @@ -243,9 +258,12 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { PrivacyInformationUrl = "" Publisher = "Contoso" PublishingState = "published" + RoleScopeTagIds = @() + Category = "Productivity" } } } + It '5.0 Should Reverse Engineer resource from the Export method' { $result = Export-TargetResource @testParams $result | Should -Not -BeNullOrEmpty diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 6fd3c370c9..0142b0e7b5 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -17939,7 +17939,15 @@ function New-MgBetaDeviceAppManagementMobileApp { [Parameter()] [System.String] [ValidateSet('notPublished', 'processing','published')] - $PublishingState + $PublishingState, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Categories, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds ) } @@ -17989,7 +17997,15 @@ function Get-MgBetaDeviceAppManagementMobileApp { [Parameter()] [System.String] [ValidateSet('notPublished', 'processing','published')] - $PublishingState + $PublishingState, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Categories, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds ) } function Update-MgBetaDeviceAppManagementMobileApp { @@ -18038,7 +18054,15 @@ function Update-MgBetaDeviceAppManagementMobileApp { [Parameter()] [System.String] [ValidateSet('notPublished', 'processing','published')] - $PublishingState + $PublishingState, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Categories, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds ) } From 434f7eaf32f1588804876cdf6f0440cdd5b853b7 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Thu, 3 Oct 2024 00:35:31 -0700 Subject: [PATCH 016/252] Added category and assignments (intent and settigns TBA) . --- .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 87 +++++++++++-------- ...SFT_IntuneMobileAppsMacOSLobApp.schema.mof | 2 +- 2 files changed, 54 insertions(+), 35 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 index 4c83dc7f80..a3341f06b3 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 @@ -59,6 +59,10 @@ function Get-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $Categories, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + #endregion [Parameter()] @@ -169,16 +173,19 @@ function Get-TargetResource AccessTokens = $AccessTokens } - #TODOK - # $resultAssignments = @() - # $appAssignments = Get-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $configPolicy.Id - # if ($appAssignments.count -gt 0) - # { - # $resultAssignments += ConvertFrom-IntuneMobileAppAssignment ` - # -IncludeDeviceFilter:$true ` - # -Assignments ($appAssignments) - # } - # $returnHashtable.Add('Assignments', $resultAssignments) + $resultAssignments = @() + $appAssignments = Get-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $instance.Id + if ($null -ne $appAssignments -and $appAssignments.count -gt 0) + { + $resultAssignments += ConvertFrom-IntuneMobileAppAssignment ` + -IncludeDeviceFilter:$true ` + -Assignments ($appAssignments) + + $results.Add('Assignments', $resultAssignments) + } + else { + $results.Add('Assignments', $null) + } return [System.Collections.Hashtable] $results } @@ -255,6 +262,11 @@ function Set-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $Categories, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + + #endregion [Parameter()] @@ -318,19 +330,15 @@ function Set-TargetResource $setParameters.Add('Categories', $categoriesValue) } - #$app = New-MgBetaDeviceAppManagementMobileApp @SetParameters - - New-MgBetaDeviceAppManagementMobileApp @SetParameters - - #TODOK - # $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments - # if ($app.id) - # { - # Update-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $app.id ` - # -Targets $assignmentsHash ` - # -Repository 'deviceAppManagement/mobileAppAssignments' - # } + $app = New-MgBetaDeviceAppManagementMobileApp @SetParameters + $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + if ($app.id) + { + Update-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $app.id ` + -Targets $assignmentsHash ` + -Repository 'deviceAppManagement/mobileAppAssignments' + } } # UPDATE elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') @@ -343,14 +351,13 @@ function Set-TargetResource Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id @SetParameters - #TODOK - # $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments - # if ($app.id) - # { - # Update-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $app.id ` - # -Targets $assignmentsHash ` - # -Repository 'deviceAppManagement/mobileAppAssignments' - # } + $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + if ($app.id) + { + Update-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $app.id ` + -Targets $assignmentsHash ` + -Repository 'deviceAppManagement/mobileAppAssignments' + } } # REMOVE elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') @@ -420,6 +427,11 @@ function Test-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $Categories, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + + #endregion [Parameter()] @@ -569,7 +581,6 @@ function Export-TargetResource Publisher = $config.Publisher PublishingState = $config.PublishingState RoleScopeTagIds = $config.RoleScopeTagIds - Categories = $config.Categories # LargeIcon = $config.LargeIcon # ChildApps = $config.ChildApps @@ -583,12 +594,10 @@ function Export-TargetResource AccessTokens = $AccessTokens } - $Params.remove('Md5HashChunkSize') | Out-Null - $Results = Get-TargetResource @Params + $Results = Get-TargetResource @params #region complex types - if (-not (Test-M365DSCAuthenticationParameter -BoundParameters $Results)) { Write-Verbose "An error occured in Get-TargetResource, the app {$($params.displayName)} will not be processed." @@ -618,6 +627,16 @@ function Export-TargetResource $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Categories' } + if ($Results.Assignments) + { + $isCIMArray = $false + if ($Results.Assignments.getType().Fullname -like '*[[\]]') + { + $isCIMArray = $true + } + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Assignments' -IsCIMArray:$isCIMArray + } + #endregion complex types $dscContent += $currentDSCBlock diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof index 72e087fbee..4de4b42b16 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof @@ -25,7 +25,7 @@ class MSFT_IntuneMobileAppsMacOSLobApp : OMI_BaseResource [Write, Description("The version number of the app.")] String VersionNumber; [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppCategory")] String Categories[]; - + [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppAssignment")] String Assignments[]; [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; From 3e4ee2e7b236bfcadb425bb04c3ee936d57f2ba5 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Thu, 3 Oct 2024 03:26:17 -0700 Subject: [PATCH 017/252] m365 config file compiled with assignment. --- .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 50 +++-- ...SFT_IntuneMobileAppsMacOSLobApp.schema.mof | 41 +++-- .../Modules/M365DSCDRGUtil.psm1 | 44 ++--- ...5DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 | 173 ++++++++++++++++-- 4 files changed, 243 insertions(+), 65 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 index a3341f06b3..0f67f9b590 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 @@ -159,9 +159,8 @@ function Get-TargetResource Owner = $instance.Owner PrivacyInformationUrl = $instance.PrivacyInformationUrl Publisher = $instance.Publisher - PublishingState = $instance.PublishingState + PublishingState = $instance.PublishingState.ToString() RoleScopeTagIds = $instance.RoleScopeTagIds - Categories = $instance.Categories Ensure = 'Present' Credential = $Credential @@ -173,6 +172,14 @@ function Get-TargetResource AccessTokens = $AccessTokens } + if($null -ne $instance.Categories) + { + $results.Add('Categories', $instance.Categories) + } + else { + $results.Add('Categories', "") + } + $resultAssignments = @() $appAssignments = Get-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $instance.Id if ($null -ne $appAssignments -and $appAssignments.count -gt 0) @@ -183,9 +190,6 @@ function Get-TargetResource $results.Add('Assignments', $resultAssignments) } - else { - $results.Add('Assignments', $null) - } return [System.Collections.Hashtable] $results } @@ -579,7 +583,7 @@ function Export-TargetResource Owner = $config.Owner PrivacyInformationUrl = $config.PrivacyInformationUrl Publisher = $config.Publisher - PublishingState = $config.PublishingState + PublishingState = $config.PublishingState.ToString() RoleScopeTagIds = $config.RoleScopeTagIds # LargeIcon = $config.LargeIcon # ChildApps = $config.ChildApps @@ -596,19 +600,37 @@ function Export-TargetResource $Results = Get-TargetResource @params - #region complex types - if (-not (Test-M365DSCAuthenticationParameter -BoundParameters $Results)) { Write-Verbose "An error occured in Get-TargetResource, the app {$($params.displayName)} will not be processed." throw "An error occured in Get-TargetResource, the app {$($params.displayName)} will not be processed. Refer to the event viewer logs for more information." } - if ($Results.Categories.Count -gt 0) + #region complex types + + if($null -eq $Results.Categories -or $Results.Categories.Count -eq 0) + { + $Results.Categories = $null + } + else { $Results.Categories = Get-M365DSCIntuneAppCategoriesAsString -Categories $Results.Categories } + if ($Results.Assignments) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString -ComplexObject ([Array]$Results.Assignments) -CIMInstanceName DeviceManagementMobileAppAssignment + + if ($complexTypeStringResult) + { + $Results.Assignments = $complexTypeStringResult + } + else + { + $Results.Remove('Assignments') | Out-Null + } + } + #endregion complex types $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` @@ -677,8 +699,8 @@ function ConvertTo-M365DSCIntuneAppAssignmentSettings foreach ($setting in $Settings) { $currentSetting = @{ - name = $setting.name - value = $setting.value + name = $setting.odataType + value = $setting.uninstallOnDeviceRemoval } $result += $currentSetting } @@ -710,8 +732,8 @@ function Get-M365DSCIntuneAppAssignmentSettingsAsString } $StringContent += "MSFT_DeviceManagementMobileAppAssignmentSettings { `r`n" - $StringContent += "$($space)$($indent)name = '" + $setting.name + "'`r`n" - $StringContent += "$($space)$($indent)value = '" + $setting.value + "'`r`n" + $StringContent += "$($space)$($indent)odataType = '" + $setting.odataType + "'`r`n" + $StringContent += "$($space)$($indent)uninstallOnDeviceRemoval = '" + $setting.uninstallOnDeviceRemoval + "'`r`n" $StringContent += "$space}" $i++ @@ -769,7 +791,7 @@ function Get-M365DSCIntuneAppCategoriesAsString $StringContent += "MSFT_DeviceManagementMobileAppCategory { `r`n" $StringContent += "$($space)$($indent)id = '" + $category.id + "'`r`n" - $StringContent += "$($space)$($indent)displyName = '" + $category.displayName + "'`r`n" + $StringContent += "$($space)$($indent)displayName = '" + $category.displayName + "'`r`n" $StringContent += "$space}" $i++ diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof index 4de4b42b16..112015fc7e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof @@ -13,21 +13,12 @@ class MSFT_IntuneMobileAppsMacOSLobApp : OMI_BaseResource [Write, Description("The privacy statement Url. Inherited from mobileApp.")] String PrivacyInformationUrl; [Write, Description("The publisher of the app. Inherited from mobileApp.")] String Publisher; [Write, Description("The publishing state for the app. The app cannot be assigned unless the app is published. Inherited from mobileApp."), ValueMap{"notPublished", "processing","published"}, Values{"notPublished", "processing", "published"}] String PublishingState; - [Write, Description("List of Scope Tag IDs for the device health script")] String RoleScopeTagIds[]; - - [Write, Description("The bundleId of the app.")] String FileName; - [Write, Description("The bundleId of the app.")] Int32 Md5HashChunkSize; - [Write, Description("The build number of the app.")] String Md5Hash[]; - [Write, Description("The version number of the app.")] String InstallAsManaged; - [Write, Description("The version number of the app.")] String IgnoreVersionDetection; - [Write, Description("The bundleId of the app.")] String BundleId; - [Write, Description("The build number of the app.")] String BuildNumber; - [Write, Description("The version number of the app.")] String VersionNumber; + [Write, Description("List of Scope Tag IDs for mobile app.")] String RoleScopeTagIds[]; [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppCategory")] String Categories[]; - [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppAssignment")] String Assignments[]; + [Write, Description("The list of assignments for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppAssignment")] String Assignments[]; - [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; + [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] String Ensure; [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; @@ -46,10 +37,11 @@ class MSFT_DeviceManagementMobileAppCategory class MSFT_DeviceManagementMobileAppAssignment { [Write, Description("Possible values for the install intent chosen by the admin."), - ValueMap{"Available", "Required","Uninstall", "AvailableWithoutEnrollment"}, - Values{"Available", "Required","Uninstall", "AvailableWithoutEnrollment"}] - String Intent; - [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppAssignmentSettings")] String Settings[]; + ValueMap{"available", "required", "uninstall", "availableWithoutEnrollment"}, + Values{"available", "required", "uninstall", "availableWithoutEnrollment"}] + String intent; + + [Write, Description("The source of this assignment.")] String source; [Write, Description("The group Id that is the target of the assignment.")] String groupId; [Write, Description("The group Display Name that is the target of the assignment.")] String groupDisplayName; @@ -59,8 +51,19 @@ class MSFT_DeviceManagementMobileAppAssignment String odataType; [Write, Description("The Id of the filter for the target assignment.")] String deviceAndAppManagementAssignmentFilterId; - [Write, Description("The type of filter of the target assignment i.e. Exclude or Include. Possible values are:none, include, exclude."), - ValueMap{"none","include","exclude"}, - Values{"none","include","exclude"}] + [Write, Description("The type of filter of the target assignment i.e. Exclude or Include. Possible values are: none, include, exclude."), + ValueMap{"none", "include", "exclude"}, + Values{"none", "include", "exclude"}] String deviceAndAppManagementAssignmentFilterType; + + [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppAssignmentSetting")] String settings[]; +}; + +class MSFT_DeviceManagementMobileAppAssingmentSetting +{ + [Write, Description("The mobile app assignment setting type."), + ValueMap{"microsoft.graph.macOsLobAppAssignmentSettings"}, + Values{"microsoft.graph.macOsLobAppAssignmentSettings"}] + String odataType; + [Write, Description("The mobile app assignment setting name.")] String uninstallOnDeviceRemoval; }; diff --git a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 index bef790b91f..d9066bf136 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 @@ -1287,16 +1287,7 @@ function ConvertFrom-IntuneMobileAppAssignment $groupId = $assignment.Target.AdditionalProperties.groupId } - # if ($null -ne $assignment.Target.collectionId) TODOK: remove this if not needed - # { - # $collectionId = $assignment.Target.collectionId - # } - # else - # { - # $collectionId = $assignment.Target.AdditionalProperties.collectionId - # } - - $hashAssignment.Add('dataType',$dataType) + $hashAssignment.Add('odataType', $dataType) if (-not [string]::IsNullOrEmpty($groupId)) { $hashAssignment.Add('groupId', $groupId) @@ -1308,11 +1299,6 @@ function ConvertFrom-IntuneMobileAppAssignment } } - # if (-not [string]::IsNullOrEmpty($collectionId)) - # { - # $hashAssignment.Add('collectionId', $collectionId) - # } - if ($dataType -eq '#microsoft.graph.allLicensedUsersAssignmentTarget') { $groupDisplayName = 'All users' @@ -1325,6 +1311,21 @@ function ConvertFrom-IntuneMobileAppAssignment { $hashAssignment.Add('groupDisplayName', $groupDisplayName) } + + $hashAssignment.Add('intent', $assignment.intent.ToString()) + $hashAssignment.Add('source', $assignment.source.ToString()) + + # $concatenatedSettings = $assignment.settings.ToString() -join ',' + # $hashAssignment.Add('settings', $concatenatedSettings) + + # $hashSettings = @{} + # foreach ($setting in $assignment.Settings) + # { + # $hashSettings.Add('odatatype', $setting.odataType) + # $hashSettings.Add('uninstallOnDeviceRemoval', $setting.uninstallOnDeviceRemoval) + # } + # $hashAssignment.Add('settings', $hashSettings) + if ($IncludeDeviceFilter) { if ($null -ne $assignment.Target.DeviceAndAppManagementAssignmentFilterType) @@ -1343,7 +1344,7 @@ function ConvertFrom-IntuneMobileAppAssignment return ,$assignmentResult } -function ConvertTo-IntunePolicyAssignment +function ConvertTo-IntuneMobileAppAssignment { [CmdletBinding()] [OutputType([Hashtable[]])] @@ -1373,11 +1374,12 @@ function ConvertTo-IntunePolicyAssignment $target.Add('deviceAndAppManagementAssignmentFilterId', $assignment.DeviceAndAppManagementAssignmentFilterId) } } - if ($assignment.dataType -like '*CollectionAssignmentTarget') - { - $target.add('collectionId', $assignment.collectionId) - } - elseif ($assignment.dataType -like '*GroupAssignmentTarget') + + $assignmentResult += $assignment.intent; + $assignmentResult += $assignment.source; + $assignmentResult += $assignment.settings; + + if ($assignment.dataType -like '*GroupAssignmentTarget') { $group = Get-MgGroup -GroupId ($assignment.groupId) -ErrorAction SilentlyContinue if ($null -eq $group) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 index 74faabfe86..9d40bd7a8d 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 @@ -66,7 +66,27 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Publisher = "Contoso" PublishingState = "published" RoleScopeTagIds = @() - Category = "Productivity" + Categories = @( + MSFT_DeviceManagementMobileAppCategory { + id = '1bff2652-03ec-4a48-941c-152e93736515' + displayName = 'Kajal 3' + }) + Assignments = @( + MSFT_DeviceManagementMobileAppAssignment{ + groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' + source = direct + intent = required + odataType = '#microsoft.graph.groupAssignmentTarget' + deviceAndAppManagementAssignmentFilterType = 'none' + } + MSFT_DeviceManagementMobileAppAssignment{ + groupDisplayName = 'All devices' + source = direct + intent = required + odataType = '#microsoft.graph.allDevicesAssignmentTarget' + deviceAndAppManagementAssignmentFilterType = 'none' + }) + Ensure = 'Present' Credential = $Credential } @@ -103,7 +123,26 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Publisher = "Contoso" PublishingState = "published" RoleScopeTagIds = @() - Category = "Productivity" + Categories = @( + MSFT_DeviceManagementMobileAppCategory { + id = '1bff2652-03ec-4a48-941c-152e93736515' + displayName = 'Kajal 3' + }) + Assignments = @( + MSFT_DeviceManagementMobileAppAssignment{ + groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' + source = direct + intent = required + odataType = '#microsoft.graph.groupAssignmentTarget' + deviceAndAppManagementAssignmentFilterType = 'none' + } + MSFT_DeviceManagementMobileAppAssignment{ + groupDisplayName = 'All devices' + source = direct + intent = required + odataType = '#microsoft.graph.allDevicesAssignmentTarget' + deviceAndAppManagementAssignmentFilterType = 'none' + }) Ensure = 'Absent' Credential = $Credential } @@ -122,7 +161,26 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Publisher = "Contoso" PublishingState = "published" RoleScopeTagIds = @() - Category = "Productivity" + Categories = @( + MSFT_DeviceManagementMobileAppCategory { + id = '1bff2652-03ec-4a48-941c-152e93736515' + displayName = 'Kajal 3' + }) + Assignments = @( + MSFT_DeviceManagementMobileAppAssignment{ + groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' + source = direct + intent = required + odataType = '#microsoft.graph.groupAssignmentTarget' + deviceAndAppManagementAssignmentFilterType = 'none' + } + MSFT_DeviceManagementMobileAppAssignment{ + groupDisplayName = 'All devices' + source = direct + intent = required + odataType = '#microsoft.graph.allDevicesAssignmentTarget' + deviceAndAppManagementAssignmentFilterType = 'none' + }) } } } @@ -154,7 +212,27 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Publisher = "Contoso" PublishingState = "published" RoleScopeTagIds = @() - Category = "Productivity" + Categories = @( + MSFT_DeviceManagementMobileAppCategory { + id = '1bff2652-03ec-4a48-941c-152e93736515' + displayName = 'Kajal 3' + }) + Assignments = @( + MSFT_DeviceManagementMobileAppAssignment{ + groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' + source = direct + intent = required + odataType = '#microsoft.graph.groupAssignmentTarget' + deviceAndAppManagementAssignmentFilterType = 'none' + } + MSFT_DeviceManagementMobileAppAssignment{ + groupDisplayName = 'All devices' + source = direct + intent = required + odataType = '#microsoft.graph.allDevicesAssignmentTarget' + deviceAndAppManagementAssignmentFilterType = 'none' + }) + Ensure = 'Present' Credential = $Credential; } @@ -173,7 +251,26 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Publisher = "Contoso" PublishingState = "published" RoleScopeTagIds = @() - Category = "Productivity" + Categories = @( + MSFT_DeviceManagementMobileAppCategory { + id = '1bff2652-03ec-4a48-941c-152e93736515' + displayName = 'Kajal 3' + }) + Assignments = @( + MSFT_DeviceManagementMobileAppAssignment{ + groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' + source = direct + intent = required + odataType = '#microsoft.graph.groupAssignmentTarget' + deviceAndAppManagementAssignmentFilterType = 'none' + } + MSFT_DeviceManagementMobileAppAssignment{ + groupDisplayName = 'All devices' + source = direct + intent = required + odataType = '#microsoft.graph.allDevicesAssignmentTarget' + deviceAndAppManagementAssignmentFilterType = 'none' + }) } } } @@ -198,7 +295,26 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Publisher = "Contoso" PublishingState = "published" RoleScopeTagIds = @() - Category = "Productivity" + Categories = @( + MSFT_DeviceManagementMobileAppCategory { + id = '1bff2652-03ec-4a48-941c-152e93736515' + displayName = 'Kajal 3' + }) + Assignments = @( + MSFT_DeviceManagementMobileAppAssignment{ + groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' + source = direct + intent = required + odataType = '#microsoft.graph.groupAssignmentTarget' + deviceAndAppManagementAssignmentFilterType = 'none' + } + MSFT_DeviceManagementMobileAppAssignment{ + groupDisplayName = 'All devices' + source = direct + intent = required + odataType = '#microsoft.graph.allDevicesAssignmentTarget' + deviceAndAppManagementAssignmentFilterType = 'none' + }) Ensure = 'Present' Credential = $Credential; } @@ -217,10 +333,26 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Publisher = "Contoso" PublishingState = "published" RoleScopeTagIds = @() - Categories = @(MSFT_DeviceManagementMobileAppCategory { - id = '1bff2652-03ec-4a48-941c-152e93736515' - displyName = 'Kajal 3' - }); + Categories = @( + MSFT_DeviceManagementMobileAppCategory { + id = '1bff2652-03ec-4a48-941c-152e93736515' + displayName = 'Kajal 3' + }) + Assignments = @( + MSFT_DeviceManagementMobileAppAssignment{ + groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' + source = direct + intent = required + odataType = '#microsoft.graph.groupAssignmentTarget' + deviceAndAppManagementAssignmentFilterType = 'none' + } + MSFT_DeviceManagementMobileAppAssignment{ + groupDisplayName = 'All devices' + source = direct + intent = required + odataType = '#microsoft.graph.allDevicesAssignmentTarget' + deviceAndAppManagementAssignmentFilterType = 'none' + }) } } } @@ -259,7 +391,26 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Publisher = "Contoso" PublishingState = "published" RoleScopeTagIds = @() - Category = "Productivity" + Categories = @( + MSFT_DeviceManagementMobileAppCategory { + id = '1bff2652-03ec-4a48-941c-152e93736515' + displayName = 'Kajal 3' + }) + Assignments = @( + MSFT_DeviceManagementMobileAppAssignment{ + groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' + source = direct + intent = required + odataType = '#microsoft.graph.groupAssignmentTarget' + deviceAndAppManagementAssignmentFilterType = 'none' + } + MSFT_DeviceManagementMobileAppAssignment{ + groupDisplayName = 'All devices' + source = direct + intent = required + odataType = '#microsoft.graph.allDevicesAssignmentTarget' + deviceAndAppManagementAssignmentFilterType = 'none' + }) } } } From ebdbb6a0207966d232ddde21a6c5869c83ab4820 Mon Sep 17 00:00:00 2001 From: "Ritik Mittal (from Dev Box)" Date: Thu, 3 Oct 2024 16:40:12 +0530 Subject: [PATCH 018/252] Added AADAuthenticationRequirements resource for Per-User MFA Requirements monitoring --- CHANGELOG.md | 2 + .../MSFT_AADAuthenticationRequirement.psm1 | 381 ++++++++++++++++++ ...FT_AADAuthenticationRequirement.schema.mof | 14 + .../readme.md | 6 + .../settings.json | 20 + .../AADAuthenticationRequirement/2-Update.ps1 | 34 ++ ...DSC.AADAuthenticationRequirement.Tests.ps1 | 160 ++++++++ 7 files changed, 617 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/MSFT_AADAuthenticationRequirement.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/MSFT_AADAuthenticationRequirement.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADAuthenticationRequirement/2-Update.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAuthenticationRequirement.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 2196377267..ed8f6aa7ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ * Added ReportSuspiciousActivitySettings * AADAuthenticationMethodPolicyHardware * Initial release. +* AADAuthenticationRequirement + * Initial release. * AADEntitlementManagementSettings * Initial release. * AADFeatureRolloutPolicy diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/MSFT_AADAuthenticationRequirement.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/MSFT_AADAuthenticationRequirement.psm1 new file mode 100644 index 0000000000..392a3e0f88 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/MSFT_AADAuthenticationRequirement.psm1 @@ -0,0 +1,381 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter()] + [ValidateSet('enabled', 'disabled')] + [System.String] + $PerUserMfaState, + + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + try + { + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + + $getValue = $null + $url = $Global:MSCloudLoginConnectionProfile.MicrosoftGraph.ResourceUrl + "beta/users/$Id/authentication/requirements" + $getValue = Invoke-MgGraphRequest -Method Get -Uri $url + + if ($null -eq $getValue) + { + Write-Verbose -Message "Could not find an Azure AD Authentication Requirement for user with id {$Id}" + return $nullResult + } + + Write-Verbose -Message "An Azure AD Authentication Method Policy Requirement for a user with Id {$Id} was found." + + $results = @{ + PerUserMfaState = $getValue.perUserMfaState + Id = $Id + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + Managedidentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + return [System.Collections.Hashtable] $results + } + catch + { + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter()] + [ValidateSet('enabled', 'disabled')] + [System.String] + $PerUserMfaState, + + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + $url = $Global:MSCloudLoginConnectionProfile.MicrosoftGraph.ResourceUrl + "beta/users/$Id/authentication/requirements" + + $params = @{} + if ($PerUserMfaState -eq 'enabled' -and $currentInstance.PerUserMfaState -eq 'disabled') + { + $params = @{ + "perUserMfaState" = "enabled" + } + elseif ($PerUserMfaState -eq 'disabled' -and $currentInstance.PerUserMfaState -eq 'enabled') + { + $params = @{ + "perUserMfaState" = "disabled" + } + } + + $jsonParams = $params | ConvertTo-Json + + Invoke-MgGraphRequest -Method PATCH -Uri $url -Body $jsonParams +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter()] + [ValidateSet('enabled', 'disabled')] + [System.String] + $PerUserMfaState, + + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + Write-Verbose -Message "Testing configuration of the Azure AD Authentication Requirement for a user with Id {$Id}" + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() + + $testResult = $true + + $CurrentValues.remove('Id') | Out-Null + $ValuesToCheck.remove('Id') | Out-Null + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + if ($testResult) + { + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + } + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + [array]$getValue = Get-MgUser -ErrorAction Stop | Where-Object -FilterScript {$null -ne $_.Id} + + $i = 1 + $dscContent = '' + if ($getValue.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $getValue) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + $displayedKey = $config.Id + if (-not [String]::IsNullOrEmpty($config.DisplayName)) + { + $displayedKey = $config.DisplayName + } + + Write-Host " |---[$i/$($getValue.Count)] $displayedKey" -NoNewline + $params = @{ + Id = $config.Id + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + Managedidentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/MSFT_AADAuthenticationRequirement.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/MSFT_AADAuthenticationRequirement.schema.mof new file mode 100644 index 0000000000..186479b5a4 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/MSFT_AADAuthenticationRequirement.schema.mof @@ -0,0 +1,14 @@ +[ClassVersion("1.0.0.0"), FriendlyName("AADAuthenticationRequirement")] +class MSFT_AADAuthenticationRequirement : OMI_BaseResource +{ + [Write, Description("The state of the MFA enablement for the user. Possible values are: enabled, disabled."), ValueMap{"enabled","disabled"}, Values{"enabled","disabled"}] String PerUserMfaState; + [Key, Description("The unique identifier for an entity. Read-only.")] String Id; + + [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Secret of the Azure Active Directory tenant used for authentication."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/readme.md new file mode 100644 index 0000000000..8495f479ee --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/readme.md @@ -0,0 +1,6 @@ + +# AADAuthenticationRequirement + +## Description + +Azure AD Authentication Requirement Resource to set up Per-User MFA settings diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/settings.json new file mode 100644 index 0000000000..65c0642985 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/settings.json @@ -0,0 +1,20 @@ +{ + "resourceName": "AADAuthenticationRequirement", + "description": "This resource configures Azure AD Authentication MFA Requirements for a user.", + "roles": { + "read": [], + "update": [] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADAuthenticationRequirement/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADAuthenticationRequirement/2-Update.ps1 new file mode 100644 index 0000000000..807138beab --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADAuthenticationRequirement/2-Update.ps1 @@ -0,0 +1,34 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + Node localhost + { + AADAuthenticationRequirement "AADAuthenticationRequirement-98ceffcc-7c54-4227-8844-835af5a023ce" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Id = "98ceffcc-7c54-4227-8844-835af5a023ce" + PerUserMfaState = "disabled" + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAuthenticationRequirement.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAuthenticationRequirement.Tests.ps1 new file mode 100644 index 0000000000..25f990dd66 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAuthenticationRequirement.Tests.ps1 @@ -0,0 +1,160 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -GenericStubModule $GenericStubPath + +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Id = "98ceffcc-7c54-4227-8844-835af5a023ce" + PerUserMfaState = 'Enabled' + Credential = $Credential; + } + + Mock -CommandName Invoke-MgGraphRequest -MockWith { + return @{ + Id = "98ceffcc-7c54-4227-8844-835af5a023ce" + PerUserMfaState = 'Enabled' + Credential = $Credential; + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state - Enable" -Fixture { + BeforeAll { + $testParams = @{ + Id = "98ceffcc-7c54-4227-8844-835af5a023ce" + PerUserMfaState = 'Enabled' + Credential = $Credential; + } + + Mock -CommandName Invoke-MgGraphRequest -MockWith { + return @{ + Id = "98ceffcc-7c54-4227-8844-835af5a023ce" + PerUserMfaState = 'Disabled' + Credential = $Credential; + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).PerUserMfaState | Should -Be 'Disabled' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Invoke-MgGraphRequest -Exactly 1 -ParameterFilter { $Method -eq 'PATCH' } + } + } + + Context -Name "The instance exists and values are NOT in the desired state - Disable" -Fixture { + BeforeAll { + $testParams = @{ + Id = "98ceffcc-7c54-4227-8844-835af5a023ce" + PerUserMfaState = 'Disabled' + Credential = $Credential; + } + + Mock -CommandName Invoke-MgGraphRequest -MockWith { + return @{ + Id = "98ceffcc-7c54-4227-8844-835af5a023ce" + PerUserMfaState = 'Enabled' + Credential = $Credential; + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).PerUserMfaState | Should -Be 'Enabled' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Invoke-MgGraphRequest -Exactly 1 -ParameterFilter { $Method -eq 'PATCH' } + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + Mock -CommandName Invoke-MgGraphRequest -MockWith { + return @{ + Id = "98ceffcc-7c54-4227-8844-835af5a023ce" + PerUserMfaState = 'Enabled' + Credential = $Credential; + } + } + + Mock -CommandName Get-MgUser -MockWith { + return @{ + Id = "98ceffcc-7c54-4227-8844-835af5a023ce" + Credential = $Credential; + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope From d2aad00f9b69faa0740ae3503e4082cabfb3431b Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 3 Oct 2024 11:11:32 +0000 Subject: [PATCH 019/252] Updated {Update} AAD Integration Tests --- .../M365DSCIntegration.AAD.Update.Tests.ps1 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 index c9363e1d89..5ded12c7de 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 @@ -408,6 +408,14 @@ ); State = "enabled"; } + AADAuthenticationRequirement 'AADAuthenticationRequirement-98ceffcc-7c54-4227-8844-835af5a023ce' + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Id = "98ceffcc-7c54-4227-8844-835af5a023ce" + PerUserMfaState = "disabled" + } AADAuthenticationStrengthPolicy 'AADAuthenticationStrengthPolicy-Example' { AllowedCombinations = @("windowsHelloForBusiness","fido2","deviceBasedPush"); # Updated Property From 8e9263bb50897c39b3997d486693debe53a5f59e Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 3 Oct 2024 11:13:17 +0000 Subject: [PATCH 020/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 08ad6e8253..eed76accce 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -2044,6 +2044,56 @@ } ] }, + { + "ClassName": "MSFT_AADAuthenticationRequirement", + "Parameters": [ + { + "CIMType": "String", + "Name": "PerUserMfaState", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Id", + "Option": "Key" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "ApplicationSecret", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_AADAuthenticationStrengthPolicy", "Parameters": [ From 826ad2d1119c24713a3e040a2ca8c179f7d481c7 Mon Sep 17 00:00:00 2001 From: "Ritik Mittal (from Dev Box)" Date: Thu, 3 Oct 2024 16:58:14 +0530 Subject: [PATCH 021/252] Added permissions --- .../settings.json | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/settings.json index 65c0642985..e56d74c0d4 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/settings.json @@ -8,12 +8,32 @@ "permissions": { "graph": { "delegated": { - "read": [], - "update": [] + "read": + [ + { + "name": "UserAuthenticationMethod.Read.All" + } + ], + "update": + [ + { + "name": "UserAuthenticationMethod.ReadWrite.All" + } + ] }, "application": { - "read": [], - "update": [] + "read": + [ + { + "name": "UserAuthenticationMethod.Read.All" + } + ], + "update": + [ + { + "name": "UserAuthenticationMethod.ReadWrite.All" + } + ] } } } From 9112965abc17f622408a5b019a9070160bce2434 Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Thu, 3 Oct 2024 18:18:48 +0530 Subject: [PATCH 022/252] Added Warning message --- .../DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index c88da22921..d8c5b97231 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -941,7 +941,7 @@ function Set-TargetResource } else { - Write-Warning -Message "KeyCredentials is a readonly property and cannot be configured." + Write-Warning -Message "KeyCredentials cannot be updated for AAD Applications with more than one KeyCredentials due to technical limitation of Update-MgApplication Cmdlet. Learn more at: https://learn.microsoft.com/en-us/graph/api/application-addkey" } } } From 50c74247bf7e636d45859c7b7f56258cd88b9383 Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Thu, 3 Oct 2024 16:54:46 +0200 Subject: [PATCH 023/252] Fix handling of one-property elements in the Settings Catalog --- CHANGELOG.md | 2 + .../Modules/M365DSCDRGUtil.psm1 | 80 ++++++++++++++----- 2 files changed, 61 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a312616ab..5c0c824190 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -85,6 +85,8 @@ * Add support for more complex Intune Settings Catalog properties * Update handling of `Update-IntuneDeviceConfigurationPolicy` to throw on error FIXES [#5055](https://github.com/microsoft/Microsoft365DSC/issues/5055) + * Fixes an issue for the handling of skipped one-property elements in the + Settings Catalog. FIXES [#5086](https://github.com/microsoft/Microsoft365DSC/issues/5086) * M365DSCResourceGenerator * Update Intune resource generation for the Settings Catalog. * O365ExternalConnection diff --git a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 index 542a206b3d..962544bf28 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 @@ -105,7 +105,7 @@ function Rename-M365DSCCimInstanceParameter $subValue = Rename-M365DSCCimInstanceParameter $property -KeyMapping $KeyMapping if ($null -ne $subValue) { - $hashProperties.add($keyName, $subValue) + $hashProperties.Add($keyName, $subValue) } } catch @@ -830,7 +830,7 @@ function Convert-M365DSCDRGComplexTypeToHashtable $propertyName = $key[0].ToString().ToLower() + $key.Substring(1, $key.Length - 1) $propertyValue = $results[$key] $results.remove($key) | Out-Null - $results.add($propertyName, $propertyValue) + $results.Add($propertyName, $propertyValue) } } } @@ -1015,11 +1015,11 @@ function Get-SettingCatalogPolicySettingsFromTemplate $settingKey = $DSCParams.keys | Where-Object -FilterScript { $templateSetting.settingDefinitionId -like "*$($_)" } if ((-not [String]::IsNullOrEmpty($settingKey)) -and $DSCParams."$settingKey") { - $setting.add('@odata.type', '#microsoft.graph.deviceManagementConfigurationSetting') + $setting.Add('@odata.type', '#microsoft.graph.deviceManagementConfigurationSetting') $myFormattedSetting = Format-M365DSCParamsToSettingInstance -DSCParams @{$settingKey = $DSCParams."$settingKey" } ` -TemplateSetting $templateSetting - $setting.add('settingInstance', $myFormattedSetting) + $setting.Add('settingInstance', $myFormattedSetting) $settings += $setting $DSCParams.Remove($settingKey) | Out-Null } @@ -1033,23 +1033,23 @@ function Get-SettingCatalogPolicySettingsFromTemplate foreach ($groupCollectionTemplateSetting in $groupCollectionTemplateSettings) { $setting = @{} - $setting.add('@odata.type', '#microsoft.graph.deviceManagementConfigurationSetting') + $setting.Add('@odata.type', '#microsoft.graph.deviceManagementConfigurationSetting') $settingInstance = [ordered]@{} - $settingInstance.add('@odata.type', '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance') - $settingInstance.add('settingDefinitionId', $groupCollectionTemplateSetting.settingDefinitionId) - $settingInstance.add('settingInstanceTemplateReference', @{ + $settingInstance.Add('@odata.type', '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance') + $settingInstance.Add('settingDefinitionId', $groupCollectionTemplateSetting.settingDefinitionId) + $settingInstance.Add('settingInstanceTemplateReference', @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSettingInstanceTemplateReference' 'settingInstanceTemplateId' = $groupCollectionTemplateSetting.settingInstanceTemplateId }) $groupSettingCollectionValues = @() $groupSettingCollectionValueChildren = @() $groupSettingCollectionValue = @{} - $groupSettingCollectionValue.add('@odata.type', '#microsoft.graph.deviceManagementConfigurationGroupSettingValue') + $groupSettingCollectionValue.Add('@odata.type', '#microsoft.graph.deviceManagementConfigurationGroupSettingValue') $settingValueTemplateId = $groupCollectionTemplateSetting.AdditionalProperties.groupSettingCollectionValueTemplate.settingValueTemplateId if (-Not [string]::IsNullOrEmpty($settingValueTemplateId)) { - $groupSettingCollectionValue.add('settingValueTemplateReference', @{'settingValueTemplateId' = $SettingValueTemplateId }) + $groupSettingCollectionValue.Add('settingValueTemplateReference', @{'settingValueTemplateId' = $SettingValueTemplateId }) } foreach ($key in $DSCParams.keys) @@ -1067,10 +1067,10 @@ function Get-SettingCatalogPolicySettingsFromTemplate $groupSettingCollectionValueChildren += $groupSettingCollectionValueChild } } - $groupSettingCollectionValue.add('children', $groupSettingCollectionValueChildren) + $groupSettingCollectionValue.Add('children', $groupSettingCollectionValueChildren) $groupSettingCollectionValues += $groupSettingCollectionValue - $settingInstance.add('groupSettingCollectionValue', $groupSettingCollectionValues) - $setting.add('settingInstance', $settingInstance) + $settingInstance.Add('groupSettingCollectionValue', $groupSettingCollectionValues) + $setting.Add('settingInstance', $settingInstance) if ($setting.settingInstance.groupSettingCollectionValue.children.count -gt 0) { @@ -1202,7 +1202,7 @@ function ConvertTo-IntunePolicyAssignment } if ($assignment.dataType -like '*CollectionAssignmentTarget') { - $target.add('collectionId', $assignment.collectionId) + $target.Add('collectionId', $assignment.collectionId) } elseif ($assignment.dataType -like '*GroupAssignmentTarget') { @@ -1401,7 +1401,7 @@ function Update-DeviceConfigurationPolicyAssignment #Skipping assignment if group not found from either groupId or groupDisplayName if ($null -ne $group) { - $formattedTarget.add('groupId',$group.Id) + $formattedTarget.Add('groupId',$group.Id) } } if ($target.collectionId) @@ -1735,18 +1735,56 @@ function Get-IntuneSettingCatalogPolicySettingInstanceValue if ($childSettingValue.Keys.Count -gt 0) { - if ($childSettingValue.Keys -notcontains 'settingDefinitionId') + # If only one child item is allowed but we have multiple values, we need to create an object for each child + # Happens e.g. for the IntuneDeviceControlPolicyWindows10 resource --> {ruleid} and {ruleid}_ruledata definitions + if ($childSettingValue.groupSettingCollectionValue.Count -gt 1 -and + $childDefinition.AdditionalProperties.maximumCount -eq 1 -and + $groupSettingCollectionDefinitionChildren.Count -eq 1) { - $childSettingValue.Add('settingDefinitionId', $childDefinition.Id) + $childSettingValueOld = $childSettingValue + $childSettingValue = @() + foreach ($childSettingValueItem in $childSettingValueOld.groupSettingCollectionValue) + { + $childSettingValueInner = @{ + children = @() + } + $childSettingValueItem.Add('@odata.type', $childSettingType) + $childSettingValueInner.children += @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance' + groupSettingCollectionValue = @( + @{ + children = $childSettingValueItem.children + } + ) + settingDefinitionId = $childDefinition.Id + } + if (-not [string]::IsNullOrEmpty($childSettingInstanceTemplate.settingInstanceTemplateId)) + { + $childSettingValueInner.children[0].groupSettingCollectionValue.settingInstanceTemplateReference = @{ + 'settingInstanceTemplateId' = $childSettingInstanceTemplate.settingInstanceTemplateId + } + } + $childSettingValue += $childSettingValueInner + } + $groupSettingCollectionValue += $childSettingValue } - if (-not [string]::IsNullOrEmpty($childSettingInstanceTemplate.settingInstanceTemplateId)) + else { - $childSettingValue.Add('settingInstanceTemplateReference', @{'settingInstanceTemplateId' = $childSettingInstanceTemplate.settingInstanceTemplateId }) + if ($childSettingValue.Keys -notcontains 'settingDefinitionId') + { + $childSettingValue.Add('settingDefinitionId', $childDefinition.Id) + } + if (-not [string]::IsNullOrEmpty($childSettingInstanceTemplate.settingInstanceTemplateId)) + { + $childSettingValue.Add('settingInstanceTemplateReference', @{'settingInstanceTemplateId' = $childSettingInstanceTemplate.settingInstanceTemplateId }) + } + $childSettingValue.Add('@odata.type', $childSettingType) + $groupSettingCollectionValueChildren += $childSettingValue } - $childSettingValue.Add('@odata.type', $childSettingType) - $groupSettingCollectionValueChildren += $childSettingValue } } + + # Does not happen for wrapped children elements if ($groupSettingCollectionValueChildren.Count -gt 0) { $groupSettingCollectionValue += @{ From 61627d57e0de3d9fc90449406ab6e54d24df60a1 Mon Sep 17 00:00:00 2001 From: Dan Lag Date: Thu, 3 Oct 2024 11:03:36 -0400 Subject: [PATCH 024/252] Added support for ApplicationSecret --- CHANGELOG.md | 5 +++++ .../MSFT_AADEntitlementManagementSettings.psm1 | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2196377267..83dd9bc7fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change log for Microsoft365DSC +# UNRELEASED + +* AADEntitlementManagementSettings + * Added support for ApplicationSecret + # 1.24.1002.1 * AADAdministrativeUnit diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/MSFT_AADEntitlementManagementSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/MSFT_AADEntitlementManagementSettings.psm1 index f145e6744d..7ffb6e65bc 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/MSFT_AADEntitlementManagementSettings.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/MSFT_AADEntitlementManagementSettings.psm1 @@ -28,6 +28,10 @@ function Get-TargetResource [System.String] $TenantId, + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + [Parameter()] [System.String] $CertificateThumbprint, @@ -72,6 +76,7 @@ function Get-TargetResource Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId + ApplicationSecret = $ApplicationSecret CertificateThumbprint = $CertificateThumbprint ManagedIdentity = $ManagedIdentity.IsPresent AccessTokens = $AccessTokens @@ -120,6 +125,10 @@ function Set-TargetResource [System.String] $TenantId, + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + [Parameter()] [System.String] $CertificateThumbprint, @@ -181,6 +190,10 @@ function Test-TargetResource [System.String] $TenantId, + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + [Parameter()] [System.String] $CertificateThumbprint, @@ -281,6 +294,7 @@ function Export-TargetResource Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId + ApplicationSecret = $ApplicationSecret CertificateThumbprint = $CertificateThumbprint ManagedIdentity = $ManagedIdentity.IsPresent AccessTokens = $AccessTokens From c8512ffa0d9c5cecde33daa7b2e0be338b558933 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Thu, 3 Oct 2024 11:38:59 -0700 Subject: [PATCH 025/252] start-descconfig service worked with two main complex types - categories and Assignments. --- .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 113 +++++++++++------- ...SFT_IntuneMobileAppsMacOSLobApp.schema.mof | 8 +- .../Modules/M365DSCDRGUtil.psm1 | 9 +- 3 files changed, 81 insertions(+), 49 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 index 0f67f9b590..c2b4423610 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 @@ -118,31 +118,23 @@ function Get-TargetResource $nullResult.Ensure = 'Absent' try { - if ($null -ne $Script:exportedInstances -and $Script:ExportMode) - { - $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Id -eq $Id} - } - else - { - $instance = Get-MgBetaDeviceAppManagementMobileApp ` - -MobileAppId $Id ` - -Filter "microsoft.graph.managedApp/appAvailability eq null" ` - -ExpandProperty "categories,assignments" ` - -ErrorAction Stop - } + $instance = Get-MgBetaDeviceAppManagementMobileApp ` + -Filter "(isof('microsoft.graph.macOSLobApp') and displayName eq '$DisplayName')" ` + -ExpandProperty "categories,assignments" ` + -ErrorAction SilentlyContinue if ($null -eq $instance) { - Write-Verbose -Message "No Mobile app with Id {$Id} was found. Search with DisplayName." + Write-Verbose -Message "No Mobile app with DisplayName {$DisplayName} was found. Search with DisplayName." $instance = Get-MgBetaDeviceAppManagementMobileApp ` - -Filter "displayName eq '$DisplayName'" ` + -MobileAppId $Id ` -ExpandProperty "categories,assignments" ` - -ErrorAction SilentlyContinue + -ErrorAction Stop } if ($null -eq $instance) { - Write-Verbose -Message "No Mobile app with {$DisplayName} was found." + Write-Verbose -Message "No Mobile app with {$Id} was found." return $nullResult } @@ -270,7 +262,6 @@ function Set-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $Assignments, - #endregion [Parameter()] @@ -320,23 +311,27 @@ function Set-TargetResource #endregion $currentInstance = Get-TargetResource @PSBoundParameters - $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + $PSBoundParameters.Remove('Categories') | Out-Null + $PSBoundParameters.Remove('Assignments') | Out-Null + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters $setParameters.remove('Id') | Out-Null $setParameters.remove('Ensure') | Out-Null + $setParameters.remove('Categories') | Out-Null + $setParameters.remove('Assignments') | Out-Null + + if($null -ne $Categories) + { + [System.Object[]]$categoriesValue = ConvertTo-M365DSCIntuneAppCategories -Categories $Categories + $setParameters.Add('Categories', $categoriesValue) + } # CREATE if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { - if($null -ne $Categories) - { - [System.Object[]]$categoriesValue = ConvertTo-M365DSCIntuneAppCategories -Categories $Categories - $setParameters.Add('Categories', $categoriesValue) - } + $app = New-MgBetaDeviceAppManagementMobileApp @setParameters - $app = New-MgBetaDeviceAppManagementMobileApp @SetParameters $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments - if ($app.id) { Update-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $app.id ` @@ -347,13 +342,7 @@ function Set-TargetResource # UPDATE elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { - if($null -ne $Categories) - { - [System.Object[]]$categoriesValue = ConvertTo-M365DSCIntuneAppCategories -Categories $Categories - $setParameters.Add('Categories', $categoriesValue) - } - - Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id @SetParameters + Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id @setParameters $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments if ($app.id) @@ -484,20 +473,60 @@ function Test-TargetResource Add-M365DSCTelemetryEvent -Data $data #endregion + Write-Verbose -Message "Testing configuration of Intune Mobile MacOS App: {$DisplayName}" + $CurrentValues = Get-TargetResource @PSBoundParameters - $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + if (-not (Test-M365DSCAuthenticationParameter -BoundParameters $CurrentValues)) + { + Write-Verbose "An error occured in Get-TargetResource, the app {$displayName} will not be processed" + throw "An error occured in Get-TargetResource, the app {$displayName} will not be processed. Refer to the event viewer logs for more information." + } + $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() + $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck + $ValuesToCheck.Remove('Id') | Out-Null Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" - Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" - $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` - -Source $($MyInvocation.MyCommand.Source) ` - -DesiredValues $PSBoundParameters ` - -ValuesToCheck $ValuesToCheck.Keys + if ($CurrentValues.Ensure -ne $Ensure) + { + Write-Verbose -Message "Test-TargetResource returned $false" + return $false + } + $testResult = $true + + #Compare Cim instances + foreach ($key in $PSBoundParameters.Keys) + { + $source = $PSBoundParameters.$key + $target = $CurrentValues.$key + if ($source.getType().Name -like '*CimInstance*') + { + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + if (-Not $testResult) + { + $testResult = $false + break + } + + $ValuesToCheck.Remove($key) | Out-Null + } + } + + if ($testResult) + { + $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + } - Write-Verbose -Message "Test-TargetResource returned $testResult" + Write-Verbose -Message "Test-TargetResource returned $TestResult" - return $testResult + return $TestResult } function Export-TargetResource @@ -756,8 +785,8 @@ function ConvertTo-M365DSCIntuneAppCategories foreach ($category in $Categories) { $currentCategory = @{ - name = $category.id - value = $category.displayName + id = $category.id + displayName = $category.displayName # This 'displayName' property has to exist in microsoft.management.services.api.mobileAppCategory } $result += $currentCategory diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof index 112015fc7e..b8e59f2735 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof @@ -7,7 +7,7 @@ class MSFT_IntuneMobileAppsMacOSLobApp : OMI_BaseResource [Write, Description("The description of the app. Inherited from mobileApp.")] String Description; [Write, Description("The dewveloper of the app. Inherited from mobileApp.")] String Developer; [Write, Description("The InformationUrl of the app. Inherited from mobileApp.")] String InformationUrl; - [Write, Description("The value indicating whether the app is marked as featured by the admin. Inherited from mobileApp.")] String IsFeatured; + [Write, Description("The value indicating whether the app is marked as featured by the admin. Inherited from mobileApp.")] Boolean IsFeatured; [Write, Description("Notes for the app. Inherited from mobileApp.")] String Notes; [Write, Description("The owner of the app. Inherited from mobileApp.")] String Owner; [Write, Description("The privacy statement Url. Inherited from mobileApp.")] String PrivacyInformationUrl; @@ -48,7 +48,7 @@ class MSFT_DeviceManagementMobileAppAssignment [Write, Description("The type of the target assignment."), ValueMap{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget"}, Values{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget"}] - String odataType; + String dataType; [Write, Description("The Id of the filter for the target assignment.")] String deviceAndAppManagementAssignmentFilterId; [Write, Description("The type of filter of the target assignment i.e. Exclude or Include. Possible values are: none, include, exclude."), @@ -56,7 +56,7 @@ class MSFT_DeviceManagementMobileAppAssignment Values{"none", "include", "exclude"}] String deviceAndAppManagementAssignmentFilterType; - [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppAssignmentSetting")] String settings[]; + [Write, Description("The list of settings used with this app assignemnt."), EmbeddedInstance("MSFT_DeviceManagementMobileAppAssignmentSetting")] String settings[]; }; class MSFT_DeviceManagementMobileAppAssingmentSetting @@ -64,6 +64,6 @@ class MSFT_DeviceManagementMobileAppAssingmentSetting [Write, Description("The mobile app assignment setting type."), ValueMap{"microsoft.graph.macOsLobAppAssignmentSettings"}, Values{"microsoft.graph.macOsLobAppAssignmentSettings"}] - String odataType; + String dataType; [Write, Description("The mobile app assignment setting name.")] String uninstallOnDeviceRemoval; }; diff --git a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 index d9066bf136..f722b123ce 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 @@ -617,6 +617,7 @@ function Compare-M365DSCComplexObject } if ($Source[0].CimClass.CimClassName -eq 'MSFT_DeviceManagementConfigurationPolicyAssignments' -or + $Source[0].CimClass.CimClassName -eq 'MSFT_DeviceManagementMobileAppAssignment' -or ($Source[0].CimClass.CimClassName -like 'MSFT_Intune*Assignments' -and $Source[0].CimClass.CimClassName -ne 'MSFT_IntuneDeviceRemediationPolicyAssignments')) { @@ -734,7 +735,9 @@ function Compare-M365DSCComplexObject { if ($Source.$key.GetType().FullName -like '*CimInstance' -and ( $Source.$key.CimClass.CimClassName -eq 'MSFT_DeviceManagementConfigurationPolicyAssignments' -or - $Source.$key.CimClass.CimClassName -like 'MSFT_Intune*Assignments')) + $Source.$key.CimClass.CimClassName -like 'MSFT_DeviceManagementMobileAppAssignment' -or + $Source.$key.CimClass.CimClassName -like 'MSFT_Intune*Assignments' + )) { $compareResult = Compare-M365DSCIntunePolicyAssignment ` -Source @($Source.$key) ` @@ -1287,7 +1290,7 @@ function ConvertFrom-IntuneMobileAppAssignment $groupId = $assignment.Target.AdditionalProperties.groupId } - $hashAssignment.Add('odataType', $dataType) + $hashAssignment.Add('dataType', $dataType) if (-not [string]::IsNullOrEmpty($groupId)) { $hashAssignment.Add('groupId', $groupId) @@ -1321,7 +1324,7 @@ function ConvertFrom-IntuneMobileAppAssignment # $hashSettings = @{} # foreach ($setting in $assignment.Settings) # { - # $hashSettings.Add('odatatype', $setting.odataType) + # $hashSettings.Add('datatype', $setting.dataType) # $hashSettings.Add('uninstallOnDeviceRemoval', $setting.uninstallOnDeviceRemoval) # } # $hashAssignment.Add('settings', $hashSettings) From d23f4292b11056c8e82643b1ac487537250c5b20 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Thu, 3 Oct 2024 12:26:55 -0700 Subject: [PATCH 026/252] UTs are passing. --- .../IntuneMobileAppsMacOSLobApp/1-Create.ps1 | 19 ++ .../IntuneMobileAppsMacOSLobApp/2-Update.ps1 | 19 ++ ...5DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 | 162 +----------------- 3 files changed, 40 insertions(+), 160 deletions(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 index 097a2846b4..1998735068 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 @@ -36,6 +36,25 @@ Configuration Example PrivacyInformationUrl = ""; Publisher = "Contoso"; PublishingState = "published"; + Assignments = @( + MSFT_DeviceManagementMobileAppAssignment{ + groupDisplayName = 'All devices' + source = 'direct' + deviceAndAppManagementAssignmentFilterType = 'none' + dataType = '#microsoft.graph.allDevicesAssignmentTarget' + intent = 'required' + MSFT_DeviceManagementMobileAppAssignment{ + deviceAndAppManagementAssignmentFilterType = 'none' + source = 'direct' + dataType = '#microsoft.graph.groupAssignmentTarget' + groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' + intent = 'required' + } + }); + Categories = @(MSFT_DeviceManagementMobileAppCategory { + id = '1bff2652-03ec-4a48-941c-152e93736515' + displayName = 'Kajal 3' + }); } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 index 85ec982890..dccf286c8b 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 @@ -36,6 +36,25 @@ Configuration Example PrivacyInformationUrl = ""; Publisher = "Contoso"; PublishingState = "published"; + Assignments = @( + MSFT_DeviceManagementMobileAppAssignment{ + groupDisplayName = 'All devices' + source = 'direct' + deviceAndAppManagementAssignmentFilterType = 'none' + dataType = '#microsoft.graph.allDevicesAssignmentTarget' + intent = 'required' + MSFT_DeviceManagementMobileAppAssignment{ + deviceAndAppManagementAssignmentFilterType = 'none' + source = 'direct' + dataType = '#microsoft.graph.groupAssignmentTarget' + groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' + intent = 'required' + } + }); + Categories = @(MSFT_DeviceManagementMobileAppCategory { + id = '1bff2652-03ec-4a48-941c-152e93736515' + displayName = 'Kajal 3' + }); } } } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 index 9d40bd7a8d..716e2c5887 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 @@ -66,26 +66,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Publisher = "Contoso" PublishingState = "published" RoleScopeTagIds = @() - Categories = @( - MSFT_DeviceManagementMobileAppCategory { - id = '1bff2652-03ec-4a48-941c-152e93736515' - displayName = 'Kajal 3' - }) - Assignments = @( - MSFT_DeviceManagementMobileAppAssignment{ - groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' - source = direct - intent = required - odataType = '#microsoft.graph.groupAssignmentTarget' - deviceAndAppManagementAssignmentFilterType = 'none' - } - MSFT_DeviceManagementMobileAppAssignment{ - groupDisplayName = 'All devices' - source = direct - intent = required - odataType = '#microsoft.graph.allDevicesAssignmentTarget' - deviceAndAppManagementAssignmentFilterType = 'none' - }) Ensure = 'Present' Credential = $Credential @@ -123,26 +103,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Publisher = "Contoso" PublishingState = "published" RoleScopeTagIds = @() - Categories = @( - MSFT_DeviceManagementMobileAppCategory { - id = '1bff2652-03ec-4a48-941c-152e93736515' - displayName = 'Kajal 3' - }) - Assignments = @( - MSFT_DeviceManagementMobileAppAssignment{ - groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' - source = direct - intent = required - odataType = '#microsoft.graph.groupAssignmentTarget' - deviceAndAppManagementAssignmentFilterType = 'none' - } - MSFT_DeviceManagementMobileAppAssignment{ - groupDisplayName = 'All devices' - source = direct - intent = required - odataType = '#microsoft.graph.allDevicesAssignmentTarget' - deviceAndAppManagementAssignmentFilterType = 'none' - }) + Ensure = 'Absent' Credential = $Credential } @@ -161,26 +122,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Publisher = "Contoso" PublishingState = "published" RoleScopeTagIds = @() - Categories = @( - MSFT_DeviceManagementMobileAppCategory { - id = '1bff2652-03ec-4a48-941c-152e93736515' - displayName = 'Kajal 3' - }) - Assignments = @( - MSFT_DeviceManagementMobileAppAssignment{ - groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' - source = direct - intent = required - odataType = '#microsoft.graph.groupAssignmentTarget' - deviceAndAppManagementAssignmentFilterType = 'none' - } - MSFT_DeviceManagementMobileAppAssignment{ - groupDisplayName = 'All devices' - source = direct - intent = required - odataType = '#microsoft.graph.allDevicesAssignmentTarget' - deviceAndAppManagementAssignmentFilterType = 'none' - }) } } } @@ -212,26 +153,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Publisher = "Contoso" PublishingState = "published" RoleScopeTagIds = @() - Categories = @( - MSFT_DeviceManagementMobileAppCategory { - id = '1bff2652-03ec-4a48-941c-152e93736515' - displayName = 'Kajal 3' - }) - Assignments = @( - MSFT_DeviceManagementMobileAppAssignment{ - groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' - source = direct - intent = required - odataType = '#microsoft.graph.groupAssignmentTarget' - deviceAndAppManagementAssignmentFilterType = 'none' - } - MSFT_DeviceManagementMobileAppAssignment{ - groupDisplayName = 'All devices' - source = direct - intent = required - odataType = '#microsoft.graph.allDevicesAssignmentTarget' - deviceAndAppManagementAssignmentFilterType = 'none' - }) Ensure = 'Present' Credential = $Credential; @@ -251,26 +172,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Publisher = "Contoso" PublishingState = "published" RoleScopeTagIds = @() - Categories = @( - MSFT_DeviceManagementMobileAppCategory { - id = '1bff2652-03ec-4a48-941c-152e93736515' - displayName = 'Kajal 3' - }) - Assignments = @( - MSFT_DeviceManagementMobileAppAssignment{ - groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' - source = direct - intent = required - odataType = '#microsoft.graph.groupAssignmentTarget' - deviceAndAppManagementAssignmentFilterType = 'none' - } - MSFT_DeviceManagementMobileAppAssignment{ - groupDisplayName = 'All devices' - source = direct - intent = required - odataType = '#microsoft.graph.allDevicesAssignmentTarget' - deviceAndAppManagementAssignmentFilterType = 'none' - }) } } } @@ -295,26 +196,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Publisher = "Contoso" PublishingState = "published" RoleScopeTagIds = @() - Categories = @( - MSFT_DeviceManagementMobileAppCategory { - id = '1bff2652-03ec-4a48-941c-152e93736515' - displayName = 'Kajal 3' - }) - Assignments = @( - MSFT_DeviceManagementMobileAppAssignment{ - groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' - source = direct - intent = required - odataType = '#microsoft.graph.groupAssignmentTarget' - deviceAndAppManagementAssignmentFilterType = 'none' - } - MSFT_DeviceManagementMobileAppAssignment{ - groupDisplayName = 'All devices' - source = direct - intent = required - odataType = '#microsoft.graph.allDevicesAssignmentTarget' - deviceAndAppManagementAssignmentFilterType = 'none' - }) + Ensure = 'Present' Credential = $Credential; } @@ -333,26 +215,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Publisher = "Contoso" PublishingState = "published" RoleScopeTagIds = @() - Categories = @( - MSFT_DeviceManagementMobileAppCategory { - id = '1bff2652-03ec-4a48-941c-152e93736515' - displayName = 'Kajal 3' - }) - Assignments = @( - MSFT_DeviceManagementMobileAppAssignment{ - groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' - source = direct - intent = required - odataType = '#microsoft.graph.groupAssignmentTarget' - deviceAndAppManagementAssignmentFilterType = 'none' - } - MSFT_DeviceManagementMobileAppAssignment{ - groupDisplayName = 'All devices' - source = direct - intent = required - odataType = '#microsoft.graph.allDevicesAssignmentTarget' - deviceAndAppManagementAssignmentFilterType = 'none' - }) } } } @@ -391,26 +253,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Publisher = "Contoso" PublishingState = "published" RoleScopeTagIds = @() - Categories = @( - MSFT_DeviceManagementMobileAppCategory { - id = '1bff2652-03ec-4a48-941c-152e93736515' - displayName = 'Kajal 3' - }) - Assignments = @( - MSFT_DeviceManagementMobileAppAssignment{ - groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' - source = direct - intent = required - odataType = '#microsoft.graph.groupAssignmentTarget' - deviceAndAppManagementAssignmentFilterType = 'none' - } - MSFT_DeviceManagementMobileAppAssignment{ - groupDisplayName = 'All devices' - source = direct - intent = required - odataType = '#microsoft.graph.allDevicesAssignmentTarget' - deviceAndAppManagementAssignmentFilterType = 'none' - }) } } } From 25bcde54852c40ffc6b1d32a21bb07776a66d2f9 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 3 Oct 2024 15:51:48 -0400 Subject: [PATCH 027/252] Checkin --- CHANGELOG.md | 5 + .../MSFT_ADOPermissionGroup.psm1 | 4 +- .../MSFT_ADOPermissionGroupSettings.psm1 | 318 +++++++++++++++--- ...MSFT_ADOPermissionGroupSettings.schema.mof | 21 +- 4 files changed, 288 insertions(+), 60 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2196377267..945b7d2267 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change log for Microsoft365DSC +# UNRELEASED + +* ADOPermissionGroupSettings + * Initial release. + # 1.24.1002.1 * AADAdministrativeUnit diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroup/MSFT_ADOPermissionGroup.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroup/MSFT_ADOPermissionGroup.psm1 index 1f9df20d61..1af5a2f77b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroup/MSFT_ADOPermissionGroup.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroup/MSFT_ADOPermissionGroup.psm1 @@ -477,8 +477,8 @@ function Export-TargetResource { $Script:ExportMode = $true - $profile = Invoke-M365DSCAzureDevOPSWebRequest -Uri 'https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=5.1' - $accounts = Invoke-M365DSCAzureDevOPSWebRequest -Uri "https://app.vssps.visualstudio.com/_apis/accounts?api-version=7.1-preview.1&memberId=$($profile.id)" + $profileValue = Invoke-M365DSCAzureDevOPSWebRequest -Uri 'https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=5.1' + $accounts = Invoke-M365DSCAzureDevOPSWebRequest -Uri "https://app.vssps.visualstudio.com/_apis/accounts?api-version=7.1-preview.1&memberId=$($profileValue.id)" $i = 1 $dscContent = '' diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.psm1 index d8ff5bdb19..b53f586647 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.psm1 @@ -4,17 +4,25 @@ function Get-TargetResource [OutputType([System.Collections.Hashtable])] param ( - ##TODO - Replace the PrimaryKey [Parameter(Mandatory = $true)] [System.String] - $PrimaryKey, + $GroupName, - ##TODO - Add the list of Parameters + [Parameter(Mandatory = $true)] + [System.String] + $OrganizationName, [Parameter()] - [ValidateSet('Present', 'Absent')] [System.String] - $Ensure = 'Present', + $Descriptor, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $AllowPermissions, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $DenyPermissions, [Parameter()] [System.Management.Automation.PSCredential] @@ -57,7 +65,6 @@ function Get-TargetResource #endregion $nullResult = $PSBoundParameters - $nullResult.Ensure = 'Absent' try { if ($null -ne $Script:exportedInstances -and $Script:ExportMode) @@ -90,12 +97,14 @@ function Get-TargetResource return $nullResult } - $uri = "https://dev.azure.com/$($OrganizationName)/_apis/accesscontrollists/$($instance.originId)?api-version=7.1-preview.1" - $ace = Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri + $groupPermissions = Get-M365DSCADOGroupPermission -GroupName $instance.principalName -OrganizationName $OrganizationName $results = @{ - ##TODO - Add the list of parameters to be returned - Ensure = 'Present' + OrganizationName = $OrganizationName + GroupName = $instance.principalName + Descriptor = $instance.Descriptor + AllowPermissions = $groupPermissions.Allow + DenyPermissions = $groupPermissions.Deny Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId @@ -123,17 +132,25 @@ function Set-TargetResource [CmdletBinding()] param ( - ##TODO - Replace the PrimaryKey [Parameter(Mandatory = $true)] [System.String] - $PrimaryKey, + $GroupName, - ##TODO - Add the list of Parameters + [Parameter(Mandatory = $true)] + [System.String] + $OrganizationName, [Parameter()] - [ValidateSet('Present', 'Absent')] [System.String] - $Ensure = 'Present', + $Descriptor, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $AllowPermissions, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $DenyPermissions, [Parameter()] [System.Management.Automation.PSCredential] @@ -174,25 +191,26 @@ function Set-TargetResource $currentInstance = Get-TargetResource @PSBoundParameters - $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + $uri = "https://vssps.dev.azure.com/$($OrganizationName)/_apis/identities?subjectDescriptors=$($currentInstance.Descriptor)&api-version=7.2-preview.1" + $info = Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri + $descriptor = $info.value.descriptor - # CREATE - if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') - { - ##TODO - Replace by the New cmdlet for the resource - New-Cmdlet @SetParameters + $body = @{ + value = @() } - # UPDATE - elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') - { - ##TODO - Replace by the Update/Set cmdlet for the resource - Set-cmdlet @SetParameters - } - # REMOVE - elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + + foreach ($permission in $AllowPermissions) { - ##TODO - Replace by the Remove cmdlet for the resource - Remove-cmdlet @SetParameters + <#$content = @{ + inheritPermissions = $false + "token": "token1", + "acesDictionary": { + "Microsoft.TeamFoundation.Identity;S-1-9-1551374245-1204400969-2402986413-2179408616-0-0-0-0-1": { + "descriptor": "Microsoft.TeamFoundation.Identity;S-1-9-1551374245-1204400969-2402986413-2179408616-0-0-0-0-1", + "allow": 31, + "deny": 0 + } + }#> } } @@ -202,17 +220,25 @@ function Test-TargetResource [OutputType([System.Boolean])] param ( - ##TODO - Replace the PrimaryKey [Parameter(Mandatory = $true)] [System.String] - $PrimaryKey, + $GroupName, - ##TODO - Add the list of Parameters + [Parameter(Mandatory = $true)] + [System.String] + $OrganizationName, [Parameter()] - [ValidateSet('Present', 'Absent')] [System.String] - $Ensure = 'Present', + $Descriptor, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $AllowPermissions, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $DenyPermissions, [Parameter()] [System.Management.Automation.PSCredential] @@ -319,14 +345,16 @@ function Export-TargetResource try { $Script:ExportMode = $true - $profile = Invoke-M365DSCAzureDevOPSWebRequest -Uri 'https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=5.1' - $accounts = Invoke-M365DSCAzureDevOPSWebRequest -Uri "https://app.vssps.visualstudio.com/_apis/accounts?api-version=7.1-preview.1&memberId=$($profile.id)" + + $profileValue = Invoke-M365DSCAzureDevOPSWebRequest -Uri 'https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=5.1' + $accounts = Invoke-M365DSCAzureDevOPSWebRequest -Uri "https://app.vssps.visualstudio.com/_apis/accounts?api-version=7.1-preview.1&memberId=$($profileValue.id)" $i = 1 $dscContent = '' - if ($accounts.Length -eq 0) + if ($accounts.count -eq 0) { Write-Host $Global:M365DSCEmojiGreenCheckMark + return '' } else { @@ -334,9 +362,11 @@ function Export-TargetResource } foreach ($account in $accounts) { - $organization = 'O365DSC-Dev'#$account.Value.accountName + $organization = $account.Value.accountName $uri = "https://vssps.dev.azure.com/$organization/_apis/graph/groups?api-version=7.1-preview.1" + [array] $Script:exportedInstances = (Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri).Value + $i = 1 $dscContent = '' if ($Script:exportedInstances.Length -eq 0) @@ -350,10 +380,14 @@ function Export-TargetResource foreach ($config in $Script:exportedInstances) { $displayedKey = $config.principalName + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline $params = @{ OrganizationName = $Organization - PrincipalName = $config.principalName + GroupName = $config.principalName Descriptor = $config.descriptor Credential = $Credential ApplicationId = $ApplicationId @@ -363,18 +397,42 @@ function Export-TargetResource AccessTokens = $AccessTokens } - $Results = Get-TargetResource @Params - $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` - -Results $Results - - $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` - -ConnectionMode $ConnectionMode ` - -ModulePath $PSScriptRoot ` - -Results $Results ` - -Credential $Credential - $dscContent += $currentDSCBlock - Save-M365DSCPartialExport -Content $currentDSCBlock ` - -FileName $Global:PartialExportFileName + if (-not $config.principalName.StartsWith("[TEAM FOUNDATION]")) + { + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + if ($results.AllowPermissions.Length -gt 0) + { + $Results.AllowPermissions = Get-M365DSCADOPermissionsAsString $Results.AllowPermissions + } + + if ($results.DenyPermissions.Length -gt 0) + { + $Results.DenyPermissions = Get-M365DSCADOPermissionsAsString $Results.DenyPermissions + } + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + + if ($null -ne $Results.AllowPermissions) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock ` + -ParameterName 'AllowPermissions' + } + if ($null -ne $Results.DenyPermissions) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock ` + -ParameterName 'DenyPermissions' + } + + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + } $i++ Write-Host $Global:M365DSCEmojiGreenCheckMark } @@ -395,4 +453,158 @@ function Export-TargetResource } } +function Get-M365DSCADOGroupPermission +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param( + [Parameter(Mandatory = $true)] + [System.String] + $GroupName, + + [Parameter(Mandatory = $true)] + [System.String] + $OrganizationName + ) + + $results = @{ + Allow = @() + Deny = @() + } + + try + { + $uri = "https://vssps.dev.azure.com/$($OrganizationName)/_apis/graph/groups?api-version=7.1-preview.1" + $groupInfo = Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri + $mygroup = $groupInfo.value | Where-Object -FilterScript {$_.principalName -eq $GroupName} + + $uri = "https://vssps.dev.azure.com/$($OrganizationName)/_apis/identities?subjectDescriptors=$($mygroup.descriptor)&api-version=7.2-preview.1" + $info = Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri + $descriptor = $info.value.descriptor + + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/securitynamespaces?api-version=7.1-preview.1" + $responseSecurity = Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri + $securityNamespaces = $responseSecurity.Value + + foreach ($namespace in $securityNamespaces) + { + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/accesscontrollists/$($namespace.namespaceId)?api-version=7.2-preview.1" + $response = Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri + + foreach ($entry in $response.value) + { + $token = $entry.token + foreach ($ace in $entry.acesDictionary) + { + if ($ace.$descriptor) + { + $allow = $ace.$descriptor.Allow + $allowBinary = [Convert]::ToString($allow, 2) + + $deny = $ace.$descriptor.Deny + $denyBinary = [Convert]::ToString($deny, 2) + + # Breakdown the allow bits + $position = -1 + $bitMaskPositionsFound = @() + do + { + $position = $allowBinary.IndexOf('1', $position + 1) + if ($position -ge 0) + { + $zerosToAdd = $allowBinary.Length - $position - 1 + $value = '1' + for ($i = 1; $i -le $zerosToAdd; $i++) + { + $value += '0' + } + + $bitMaskPositionsFound += $value + } + } while($position -ge 0 -and ($position+1) -le $allowBinary.Length) + + foreach ($bitmask in $bitMaskPositionsFound) + { + $associatedAction = $namespace.actions | Where-Object -FilterScript {[Convert]::ToString($_.bit,2) -eq $bitmask} + if (-not [System.String]::IsNullOrEmpty($associatedAction.displayName)) + { + $entry = @{ + DisplayName = $associatedAction.displayName + Bit = $associatedAction.bit + NamespaceId = $namespace.namespaceId + Token = $token + } + $results.Allow += $entry + } + } + + # Breakdown the deny bits + $position = -1 + $bitMaskPositionsFound = @() + do + { + $position = $denyBinary.IndexOf('1', $position + 1) + if ($position -ge 0) + { + $zerosToAdd = $denyBinary.Length - $position - 1 + $value = '1' + for ($i = 1; $i -le $zerosToAdd; $i++) + { + $value += '0' + } + + $bitMaskPositionsFound += $value + } + } while($position -ge 0 -and ($position+1) -le $denyBinary.Length) + + foreach ($bitmask in $bitMaskPositionsFound) + { + $associatedAction = $namespace.actions | Where-Object -FilterScript {[Convert]::ToString($_.bit,2) -eq $bitmask} + if (-not [System.String]::IsNullOrEmpty($associatedAction.displayName)) + { + $entry = @{ + DisplayName = $associatedAction.displayName + Bit = $associatedAction.bit + NamespaceId = $namespace.namespaceId + } + $results.Deny += $entry + } + } + } + } + } + } + } + catch + { + throw $_ + } + return $results +} + +function Get-M365DSCADOPermissionsAsString +{ + [CmdletBinding()] + [OutputType([System.String])] + param( + [Parameter(Mandatory = $true)] + [System.Collections.ArrayList] + $Permissions + ) + + $StringContent = [System.Text.StringBuilder]::new() + $StringContent.Append('@(') | Out-Null + foreach ($permission in $Permissions) + { + $StringContent.Append(" MSFT_ADOPermission { `r`n") | Out-Null + $StringContent.Append(" NamespaceId = '$($permission.NamespaceId)'`r`n") | Out-Null + $StringContent.Append(" DisplayName = '$($permission.DisplayName.Replace("'", "''"))'`r`n") | Out-Null + $StringContent.Append(" Bit = '$($permission.Bit)'`r`n") | Out-Null + $StringContent.Append(" Token = '$($permission.Token)'`r`n") | Out-Null + $StringContent.Append(" }`r`n") | Out-Null + } + $StringContent.Append(' )') | Out-Null + return $StringContent.ToString() +} + Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.schema.mof index be6b06c877..e0c630fb93 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.schema.mof @@ -1,10 +1,21 @@ -[ClassVersion("1.0.0.0"), FriendlyName("ResourceName")] -class MSFT_ResourceName : OMI_BaseResource +[ClassVersion("1.0.0")] +class MSFT_ADOPermission { - [Key, Description("")] String PrimaryKey; - [Write, Description("")] String OtherProperties; + [Write, Description("")] String NamespaceId; + [Write, Description("")] String DisplayName; + [Write, Description("")] UInt32 Bit; + [Write, Description("")] String Token; +}; + +[ClassVersion("1.0.0.0"), FriendlyName("ADOPermissionGroupSettings")] +class MSFT_ADOPermissionGroupSettings : OMI_BaseResource +{ + [Key, Description("")] String GroupName; + [Write, Description("")] String OrganizationName; + [Write, Description("")] String Descriptor; + [Write, Description(""), EmbeddedInstance("MSFT_ADOPermission")] string AllowPermissions[]; + [Write, Description(""), EmbeddedInstance("MSFT_ADOPermission")] string DenyPermissions[]; - [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] string Ensure; [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; From 6953462c7091c22f1c9081fbd2be6ae9da6d319d Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Thu, 3 Oct 2024 15:44:38 -0700 Subject: [PATCH 028/252] Adding an additional property specific to MacOS Lob app 'IgnoreVersionDetection', it's a Boolean property. --- .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 62 ++++++++++++++++--- ...SFT_IntuneMobileAppsMacOSLobApp.schema.mof | 6 ++ 2 files changed, 61 insertions(+), 7 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 index c2b4423610..34e71951ac 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 @@ -30,6 +30,10 @@ function Get-TargetResource [System.Boolean] $IsFeatured, + [Parameter()] + [System.Boolean] + $IgnoreVersionDetection, + [Parameter()] [System.String] $Notes, @@ -63,6 +67,7 @@ function Get-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $Assignments, + #endregion [Parameter()] @@ -121,7 +126,8 @@ function Get-TargetResource $instance = Get-MgBetaDeviceAppManagementMobileApp ` -Filter "(isof('microsoft.graph.macOSLobApp') and displayName eq '$DisplayName')" ` -ExpandProperty "categories,assignments" ` - -ErrorAction SilentlyContinue + -ErrorAction SilentlyContinue | Where-Object ` + -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.macOSLobApp' } if ($null -eq $instance) { @@ -129,7 +135,8 @@ function Get-TargetResource $instance = Get-MgBetaDeviceAppManagementMobileApp ` -MobileAppId $Id ` -ExpandProperty "categories,assignments" ` - -ErrorAction Stop + -ErrorAction Stop | Where-Object ` + -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.macOSLobApp' } } if ($null -eq $instance) @@ -153,6 +160,7 @@ function Get-TargetResource Publisher = $instance.Publisher PublishingState = $instance.PublishingState.ToString() RoleScopeTagIds = $instance.RoleScopeTagIds + IgnoreVersionDetection = $instance.AdditionalProperties.IgnoreVersionDetection Ensure = 'Present' Credential = $Credential @@ -229,6 +237,10 @@ function Set-TargetResource [System.Boolean] $IsFeatured, + [Parameter()] + [System.Boolean] + $IgnoreVersionDetection, + [Parameter()] [System.String] $Notes, @@ -262,6 +274,7 @@ function Set-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $Assignments, + #endregion [Parameter()] @@ -320,6 +333,8 @@ function Set-TargetResource $setParameters.remove('Categories') | Out-Null $setParameters.remove('Assignments') | Out-Null + $AdditionalProperties = Get-M365DSCIntuneMobileMocOSLobAppAdditionalProperties -Properties ([System.Collections.Hashtable]$PSBoundParameters) + if($null -ne $Categories) { [System.Object[]]$categoriesValue = ConvertTo-M365DSCIntuneAppCategories -Categories $Categories @@ -329,8 +344,9 @@ function Set-TargetResource # CREATE if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { - $app = New-MgBetaDeviceAppManagementMobileApp @setParameters + $app = New-MgBetaDeviceAppManagementMobileApp @setParameters -AdditionalProperties $AdditionalProperties + #region Assignments $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments if ($app.id) { @@ -338,11 +354,12 @@ function Set-TargetResource -Targets $assignmentsHash ` -Repository 'deviceAppManagement/mobileAppAssignments' } + #endregion Assignments } # UPDATE elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { - Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id @setParameters + Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id @setParameters -AdditionalProperties $AdditionalProperties $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments if ($app.id) @@ -391,6 +408,10 @@ function Test-TargetResource [System.Boolean] $IsFeatured, + [Parameter()] + [System.Boolean] + $IgnoreVersionDetection, + [Parameter()] [System.String] $Notes, @@ -424,7 +445,6 @@ function Test-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $Assignments, - #endregion [Parameter()] @@ -583,9 +603,10 @@ function Export-TargetResource { $Script:ExportMode = $true [array] $Script:exportedInstances = Get-MgBetaDeviceAppManagementMobileApp ` - -Filter "microsoft.graph.managedApp/appAvailability eq null" ` + -Filter "isof('microsoft.graph.macOSLobApp')" ` -ExpandProperty "categories,assignments" ` - -ErrorAction Stop + -ErrorAction Stop | Where-Object ` + -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.macOSLobApp' } $i = 1 $dscContent = '' @@ -614,6 +635,9 @@ function Export-TargetResource Publisher = $config.Publisher PublishingState = $config.PublishingState.ToString() RoleScopeTagIds = $config.RoleScopeTagIds + + IgnoreVersionDetection = $config.AdditionalProperties.IgnoreVersionDetection + # LargeIcon = $config.LargeIcon # ChildApps = $config.ChildApps @@ -830,6 +854,30 @@ function Get-M365DSCIntuneAppCategoriesAsString return $StringContent } +function Get-M365DSCIntuneMobileMocOSLobAppAdditionalProperties +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = 'true')] + [System.Collections.Hashtable] + $Properties + ) + + $results = @{'@odata.type' = '#microsoft.graph.macOSLobApp' } + foreach ($property in $properties.Keys) + { + if ($property -ne 'Verbose') + { + $propertyName = $property[0].ToString().ToLower() + $property.Substring(1, $property.Length - 1) + $propertyValue = $properties.$property + $results.Add($propertyName, $propertyValue) + } + } + return $results +} + #endregion Helper functions Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof index b8e59f2735..5b2f809801 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof @@ -18,6 +18,12 @@ class MSFT_IntuneMobileAppsMacOSLobApp : OMI_BaseResource [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppCategory")] String Categories[]; [Write, Description("The list of assignments for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppAssignment")] String Assignments[]; + [Write, Description("The privacy statement Url. Inherited from mobileApp.")] String BundleId; + [Write, Description("The publisher of the app. Inherited from mobileApp.")] String BuildNumber; + + [Write, Description("Wether to ignore the version of the app or not.")] Boolean IgnoreVersionDetection; + + [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] String Ensure; [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; From 9cc1a46dc4aa93beef4dc95f7b30c4f0658604d7 Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Fri, 4 Oct 2024 09:46:25 +0530 Subject: [PATCH 029/252] minor --- .../MSFT_EXOMigrationEndpoint.psm1 | 6 +++--- .../MSFT_EXOMigrationEndpoint.schema.mof | 2 +- .../Resources/EXOMigrationEndpoint/1-Create.ps1 | 16 +++++++++++++++- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEndpoint/MSFT_EXOMigrationEndpoint.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEndpoint/MSFT_EXOMigrationEndpoint.psm1 index 2898ab3ac5..8e8ef54b1a 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEndpoint/MSFT_EXOMigrationEndpoint.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEndpoint/MSFT_EXOMigrationEndpoint.psm1 @@ -25,7 +25,7 @@ function Get-TargetResource $Authentication, [Parameter()] - [ValidateSet('Exchange Remote', 'Outlook Anywhere', 'Google Workspace', 'IMAP')] + [ValidateSet('IMAP')] [System.String] $EndpointType, @@ -208,7 +208,7 @@ function Set-TargetResource $Authentication, [Parameter()] - [ValidateSet('Exchange Remote', 'Outlook Anywhere', 'Google Workspace', 'IMAP')] + [ValidateSet('IMAP')] [System.String] $EndpointType, @@ -379,7 +379,7 @@ function Test-TargetResource $Authentication, [Parameter()] - [ValidateSet('Exchange Remote', 'Outlook Anywhere', 'Google Workspace', 'IMAP')] + [ValidateSet('IMAP')] [System.String] $EndpointType, diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEndpoint/MSFT_EXOMigrationEndpoint.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEndpoint/MSFT_EXOMigrationEndpoint.schema.mof index 8848a16f25..6f6e4c9692 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEndpoint/MSFT_EXOMigrationEndpoint.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMigrationEndpoint/MSFT_EXOMigrationEndpoint.schema.mof @@ -6,7 +6,7 @@ class MSFT_EXOMigrationEndpoint : OMI_BaseResource [Write, Description("The Application ID used for authentication.")] String AppID; [Write, Description("The URL of the Key Vault that stores the application secret.")] String AppSecretKeyVaultUrl; [Write, Description("The authentication method for the migration endpoint.")] String Authentication; - [Write, Description("The type of migration endpoint."), ValueMap{"Exchange Remote", "Outlook Anywhere", "Google Workspace", "IMAP"}, Values{"Exchange Remote", "Outlook Anywhere", "Google Workspace", "IMAP"}] String EndpointType; + [Write, Description("The type of migration endpoint."), ValueMap{"IMAP"}, Values{"IMAP"}] String EndpointType; [Write, Description("The Exchange Server address for the migration endpoint.")] String ExchangeServer; [Write, Description("The mailbox permission for the migration endpoint.")] String MailboxPermission; [Write, Description("The maximum number of concurrent incremental syncs.")] String MaxConcurrentIncrementalSyncs; diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/1-Create.ps1 index b516274848..e96d8c8010 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/1-Create.ps1 @@ -21,6 +21,20 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + EXOMigrationEndpoint "EXOMigrationEndpoint-testIMAP" + { + AcceptUntrustedCertificates = $True; + Authentication = "Basic"; + Credential = $Credscredential; + EndpointType = "IMAP"; + Ensure = "Present"; + Identity = "testIMAP"; + MailboxPermission = "Admin"; + MaxConcurrentIncrementalSyncs = "10"; + MaxConcurrentMigrations = "20"; + Port = 993; + RemoteServer = "gmail.com"; + Security = "Tls"; + } } } From 62dcb23528956a32799cb9fccaa8da767a024f7b Mon Sep 17 00:00:00 2001 From: "Ritik Mittal (from Dev Box)" Date: Fri, 4 Oct 2024 11:46:09 +0530 Subject: [PATCH 030/252] Changed key from id to upn --- .../MSFT_AADAuthenticationRequirement.psm1 | 21 ++++++++++--------- ...FT_AADAuthenticationRequirement.schema.mof | 2 +- .../AADAuthenticationRequirement/2-Update.ps1 | 6 +++--- .../Microsoft365DSC/Modules/M365DSCUtil.psm1 | 4 ++++ ...DSC.AADAuthenticationRequirement.Tests.ps1 | 16 +++++++------- 5 files changed, 27 insertions(+), 22 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/MSFT_AADAuthenticationRequirement.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/MSFT_AADAuthenticationRequirement.psm1 index 392a3e0f88..d78d5bfbf1 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/MSFT_AADAuthenticationRequirement.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/MSFT_AADAuthenticationRequirement.psm1 @@ -11,7 +11,7 @@ function Get-TargetResource [Parameter(Mandatory = $true)] [System.String] - $Id, + $UserPrincipalName, [Parameter()] [System.Management.Automation.PSCredential] @@ -62,20 +62,20 @@ function Get-TargetResource $nullResult = $PSBoundParameters $getValue = $null - $url = $Global:MSCloudLoginConnectionProfile.MicrosoftGraph.ResourceUrl + "beta/users/$Id/authentication/requirements" + $url = $Global:MSCloudLoginConnectionProfile.MicrosoftGraph.ResourceUrl + "beta/users/$UserPrincipalName/authentication/requirements" $getValue = Invoke-MgGraphRequest -Method Get -Uri $url if ($null -eq $getValue) { - Write-Verbose -Message "Could not find an Azure AD Authentication Requirement for user with id {$Id}" + Write-Verbose -Message "Could not find an Azure AD Authentication Requirement for user with UPN {$UserPrincipalName}" return $nullResult } - Write-Verbose -Message "An Azure AD Authentication Method Policy Requirement for a user with Id {$Id} was found." + Write-Verbose -Message "An Azure AD Authentication Method Policy Requirement for a user with UPN {$UserPrincipalName} was found." $results = @{ PerUserMfaState = $getValue.perUserMfaState - Id = $Id + UserPrincipalName = $UserPrincipalName Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId @@ -111,7 +111,7 @@ function Set-TargetResource [Parameter(Mandatory = $true)] [System.String] - $Id, + $UserPrincipalName, [Parameter()] [System.Management.Automation.PSCredential] @@ -155,13 +155,14 @@ function Set-TargetResource #endregion $currentInstance = Get-TargetResource @PSBoundParameters - $url = $Global:MSCloudLoginConnectionProfile.MicrosoftGraph.ResourceUrl + "beta/users/$Id/authentication/requirements" + $url = $Global:MSCloudLoginConnectionProfile.MicrosoftGraph.ResourceUrl + "beta/users/$UserPrincipalName/authentication/requirements" $params = @{} if ($PerUserMfaState -eq 'enabled' -and $currentInstance.PerUserMfaState -eq 'disabled') { $params = @{ "perUserMfaState" = "enabled" + } } elseif ($PerUserMfaState -eq 'disabled' -and $currentInstance.PerUserMfaState -eq 'enabled') { @@ -188,7 +189,7 @@ function Test-TargetResource [Parameter(Mandatory = $true)] [System.String] - $Id, + $UserPrincipalName, [Parameter()] [System.Management.Automation.PSCredential] @@ -231,7 +232,7 @@ function Test-TargetResource Add-M365DSCTelemetryEvent -Data $data #endregion - Write-Verbose -Message "Testing configuration of the Azure AD Authentication Requirement for a user with Id {$Id}" + Write-Verbose -Message "Testing configuration of the Azure AD Authentication Requirement for a user with UPN {$UserPrincipalName}" $CurrentValues = Get-TargetResource @PSBoundParameters $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() @@ -336,7 +337,7 @@ function Export-TargetResource Write-Host " |---[$i/$($getValue.Count)] $displayedKey" -NoNewline $params = @{ - Id = $config.Id + UserPrincipalName = $config.UserPrincipalName Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/MSFT_AADAuthenticationRequirement.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/MSFT_AADAuthenticationRequirement.schema.mof index 186479b5a4..f1182e0ff3 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/MSFT_AADAuthenticationRequirement.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/MSFT_AADAuthenticationRequirement.schema.mof @@ -2,7 +2,7 @@ class MSFT_AADAuthenticationRequirement : OMI_BaseResource { [Write, Description("The state of the MFA enablement for the user. Possible values are: enabled, disabled."), ValueMap{"enabled","disabled"}, Values{"enabled","disabled"}] String PerUserMfaState; - [Key, Description("The unique identifier for an entity. Read-only.")] String Id; + [Key, Description("The unique identifier for an entity. Read-only.")] String UserPrincipalName; [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADAuthenticationRequirement/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADAuthenticationRequirement/2-Update.ps1 index 807138beab..ec3edca920 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/AADAuthenticationRequirement/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/AADAuthenticationRequirement/2-Update.ps1 @@ -22,13 +22,13 @@ Configuration Example Node localhost { - AADAuthenticationRequirement "AADAuthenticationRequirement-98ceffcc-7c54-4227-8844-835af5a023ce" + AADAuthenticationRequirement "AADAuthenticationRequirement-TestMailbox109@xtasdftestorg.onmicrosoft.com" { ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint - Id = "98ceffcc-7c54-4227-8844-835af5a023ce" - PerUserMfaState = "disabled" + PerUserMfaState = "disabled"; + UserPrincipalName = "TestMailbox109@$OrganizationName"; } } } diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index d8e020b073..148c450c1a 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -3825,6 +3825,10 @@ function Get-M365DSCExportContentForResource { $primaryKey = $Results.DomainName } + elseif ($Keys.Contains('UserPrincipalName')) + { + $primaryKey = $Results.UserPrincipalName + } if ([String]::IsNullOrEmpty($primaryKey) -and ` -not $Keys.Contains('IsSingleInstance')) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAuthenticationRequirement.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAuthenticationRequirement.Tests.ps1 index 25f990dd66..0b80d7243d 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAuthenticationRequirement.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAuthenticationRequirement.Tests.ps1 @@ -45,14 +45,14 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance exists and values are already in the desired state" -Fixture { BeforeAll { $testParams = @{ - Id = "98ceffcc-7c54-4227-8844-835af5a023ce" + UserPrincipalName = "user@test.com" PerUserMfaState = 'Enabled' Credential = $Credential; } Mock -CommandName Invoke-MgGraphRequest -MockWith { return @{ - Id = "98ceffcc-7c54-4227-8844-835af5a023ce" + UserPrincipalName = "user@test.com" PerUserMfaState = 'Enabled' Credential = $Credential; } @@ -67,14 +67,14 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance exists and values are NOT in the desired state - Enable" -Fixture { BeforeAll { $testParams = @{ - Id = "98ceffcc-7c54-4227-8844-835af5a023ce" + UserPrincipalName = "user@test.com" PerUserMfaState = 'Enabled' Credential = $Credential; } Mock -CommandName Invoke-MgGraphRequest -MockWith { return @{ - Id = "98ceffcc-7c54-4227-8844-835af5a023ce" + UserPrincipalName = "user@test.com" PerUserMfaState = 'Disabled' Credential = $Credential; } @@ -98,14 +98,14 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance exists and values are NOT in the desired state - Disable" -Fixture { BeforeAll { $testParams = @{ - Id = "98ceffcc-7c54-4227-8844-835af5a023ce" + UserPrincipalName = "user@test.com" PerUserMfaState = 'Disabled' Credential = $Credential; } Mock -CommandName Invoke-MgGraphRequest -MockWith { return @{ - Id = "98ceffcc-7c54-4227-8844-835af5a023ce" + UserPrincipalName = "user@test.com" PerUserMfaState = 'Enabled' Credential = $Credential; } @@ -136,7 +136,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Invoke-MgGraphRequest -MockWith { return @{ - Id = "98ceffcc-7c54-4227-8844-835af5a023ce" + UserPrincipalName = "user@test.com" PerUserMfaState = 'Enabled' Credential = $Credential; } @@ -144,7 +144,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-MgUser -MockWith { return @{ - Id = "98ceffcc-7c54-4227-8844-835af5a023ce" + UserPrincipalName = "user@test.com" Credential = $Credential; } } From 5f2d0ad6eca721414cacd1444bc0ba0bbf4de7b8 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 4 Oct 2024 06:17:24 +0000 Subject: [PATCH 031/252] Updated {Update} AAD Integration Tests --- .../Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 index 5ded12c7de..e28b8587c9 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 @@ -408,13 +408,13 @@ ); State = "enabled"; } - AADAuthenticationRequirement 'AADAuthenticationRequirement-98ceffcc-7c54-4227-8844-835af5a023ce' + AADAuthenticationRequirement 'AADAuthenticationRequirement-TestMailbox109@xtasdftestorg.onmicrosoft.com' { ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint - Id = "98ceffcc-7c54-4227-8844-835af5a023ce" - PerUserMfaState = "disabled" + PerUserMfaState = "disabled"; + UserPrincipalName = "TestMailbox109@$OrganizationName"; } AADAuthenticationStrengthPolicy 'AADAuthenticationStrengthPolicy-Example' { From dabd354272e2b31d867fa0c23543c3eb5fd176af Mon Sep 17 00:00:00 2001 From: "Ritik Mittal (from Dev Box)" Date: Fri, 4 Oct 2024 11:48:28 +0530 Subject: [PATCH 032/252] Fixed UT --- .../Microsoft365DSC.AADAuthenticationRequirement.Tests.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAuthenticationRequirement.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAuthenticationRequirement.Tests.ps1 index 0b80d7243d..04b2234a09 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAuthenticationRequirement.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAuthenticationRequirement.Tests.ps1 @@ -144,6 +144,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-MgUser -MockWith { return @{ + Id = "98ceffcc-7c54-4227-8844-835af5a023ce" UserPrincipalName = "user@test.com" Credential = $Credential; } From 84c6043a43ecf359e61cbcb3477d6745044383e6 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 4 Oct 2024 06:19:01 +0000 Subject: [PATCH 033/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index eed76accce..95916364b2 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -2054,7 +2054,7 @@ }, { "CIMType": "String", - "Name": "Id", + "Name": "UserPrincipalName", "Option": "Key" }, { From aef70c18b5a09cbbed356516630892f5a731a2e1 Mon Sep 17 00:00:00 2001 From: "Ritik Mittal (from Dev Box)" Date: Fri, 4 Oct 2024 16:23:45 +0530 Subject: [PATCH 034/252] Added AADOnPremisePublishingProfileConnectorGroup resource --- ...SFT_AADConnectorGroupApplicationProxy.psm1 | 455 ++++++++++++++++++ ...DConnectorGroupApplicationProxy.schema.mof | 16 + .../readme.md | 6 + .../settings.json | 33 ++ .../1-Create.ps1 | 36 ++ .../2-Update.ps1 | 35 ++ .../3-Remove.ps1 | 34 ++ ...ADConnectorGroupApplicationProxy.Tests.ps1 | 198 ++++++++ Tests/Unit/Stubs/Microsoft365.psm1 | 331 +++++++++++++ 9 files changed, 1144 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/MSFT_AADConnectorGroupApplicationProxy.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/MSFT_AADConnectorGroupApplicationProxy.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADConnectorGroupApplicationProxy/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADConnectorGroupApplicationProxy/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADConnectorGroupApplicationProxy/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADConnectorGroupApplicationProxy.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/MSFT_AADConnectorGroupApplicationProxy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/MSFT_AADConnectorGroupApplicationProxy.psm1 new file mode 100644 index 0000000000..5e244d28ec --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/MSFT_AADConnectorGroupApplicationProxy.psm1 @@ -0,0 +1,455 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [ValidateSet('nam','eur','aus','asia','ind','unknownFutureValue')] + [System.String] + $Region, + + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + #endregion + + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + try + { + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + + $getValue = $null + #region resource generator code + $getValue = Get-MgBetaOnPremisePublishingProfileConnectorGroup ` + -ConnectorGroupId $Id ` + -OnPremisesPublishingProfileId 'applicationProxy' -ErrorAction SilentlyContinue + + if ($null -eq $getValue) + { + Write-Verbose -Message "Could not find an Azure AD Connector Group Application Proxy with Id {$Id}" + return $nullResult + } + #endregion + + $Id = $getValue.Id + Write-Verbose -Message "An Azure AD Connector Group Application Proxy with Id {$Id} was found" + + $enumRegion = $null + if ($null -ne $getValue.Region) + { + $enumRegion = $getValue.Region.ToString() + } + #endregion + + $results = @{ + #region resource generator code + Name = $getValue.Name + Region = $enumRegion + Id = $getValue.Id + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + #endregion + } + + return [System.Collections.Hashtable] $results + } + catch + { + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [ValidateSet('nam','eur','aus','asia','ind','unknownFutureValue')] + [System.String] + $Region, + + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + #endregion + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + + $BoundParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + $OnPremisesPublishingProfileId = "applicationProxy" + + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + Write-Verbose -Message "Creating an Azure AD Connector Group Application Proxy with Name {$DisplayName}" + + $createParameters = ([Hashtable]$BoundParameters).Clone() + $createParameters = Rename-M365DSCCimInstanceParameter -Properties $createParameters + $createParameters.Remove('Id') | Out-Null + + #region resource generator code + $policy = New-MgBetaOnPremisePublishingProfileConnectorGroup ` + -OnPremisesPublishingProfileId $OnPremisesPublishingProfileId ` + -BodyParameter $createParameters + #endregion + } + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Updating the Azure AD Connector Group Application Proxy with Id {$($currentInstance.Id)}" + + $updateParameters = ([Hashtable]$BoundParameters).Clone() + $updateParameters.Remove('Id') | Out-Null + + Update-MgBetaOnPremisePublishingProfileConnectorGroup ` + -ConnectorGroupId $currentInstance.Id ` + -OnPremisesPublishingProfileId $OnPremisesPublishingProfileId ` + -BodyParameter $UpdateParameters + #endregion + } + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Removing the Azure AD Connector Group Application Proxy with Id {$($currentInstance.Id)}" + #region resource generator code + Remove-MgBetaOnPremisePublishingProfileConnectorGroup ` + -ConnectorGroupId $currentInstance.Id ` + -OnPremisesPublishingProfileId $OnPremisesPublishingProfileId + #endregion + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + #region resource generator code + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [ValidateSet('nam','eur','aus','asia','ind','unknownFutureValue')] + [System.String] + $Region, + + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + #endregion + + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + Write-Verbose -Message "Testing configuration of the Azure AD Connector Group Application Proxy with Id {$Id} and Name {$Name}" + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() + + if ($CurrentValues.Ensure -ne $Ensure) + { + Write-Verbose -Message "Test-TargetResource returned $false" + return $false + } + $testResult = $true + + $ValuesToCheck.Remove('Id') | Out-Null + $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + if ($testResult) + { + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + } + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + #region resource generator code + [array]$getValue = Get-MgBetaOnPremisePublishingProfileConnectorGroup -OnPremisesPublishingProfileId 'applicationProxy' -ErrorAction Stop + #endregion + + $i = 1 + $dscContent = '' + if ($getValue.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $getValue) + { + $displayedKey = $config.Id + if (-not [string]::IsNullOrEmpty($config.name)) + { + $displayedKey = $config.name + } + + Write-Host " |---[$i/$($getValue.Count)] $displayedKey" -NoNewline + $params = @{ + Id = $config.Id + Name = $config.Name + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/MSFT_AADConnectorGroupApplicationProxy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/MSFT_AADConnectorGroupApplicationProxy.schema.mof new file mode 100644 index 0000000000..a41c3653cf --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/MSFT_AADConnectorGroupApplicationProxy.schema.mof @@ -0,0 +1,16 @@ + +[ClassVersion("1.0.0.0"), FriendlyName("AADConnectorGroupApplicationProxy")] +class MSFT_AADConnectorGroupApplicationProxy : OMI_BaseResource +{ + [Write, Description("The name associated with the connectorGroup.")] String Name; + [Write, Description("The region the connectorGroup is assigned to and will optimize traffic for. This region can only be set if no connectors or applications are assigned to the connectorGroup. The possible values are: nam (for North America), eur (for Europe), aus (for Australia), asia (for Asia), ind (for India), and unknownFutureValue."), ValueMap{"nam","eur","aus","asia","ind","unknownFutureValue"}, Values{"nam","eur","aus","asia","ind","unknownFutureValue"}] String Region; + [Key, Description("The unique identifier for an entity. Read-only.")] String Id; + [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; + [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Secret of the Azure Active Directory tenant used for authentication."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/readme.md new file mode 100644 index 0000000000..8067eb666a --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/readme.md @@ -0,0 +1,6 @@ + +# AADConnectorGroupApplicationProxy + +## Description + +Azure AD Connector Group Application Proxy diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/settings.json new file mode 100644 index 0000000000..8394b8c68b --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/settings.json @@ -0,0 +1,33 @@ +{ + "resourceName": "AADConnectorGroupApplicationProxy", + "description": "This resource configures an Azure AD Connector Group Application Proxy.", + "permissions": { + "graph": { + "delegated": { + "read": [ + { + "name": "Directory.ReadWrite.All" + } + ], + "update": [ + { + "name": "Directory.ReadWrite.All" + } + ] + }, + "application": { + "read": [ + { + "name": "Directory.ReadWrite.All" + } + ], + "update": [ + { + "name": "Directory.ReadWrite.All" + } + ] + } + } + } +} + diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADConnectorGroupApplicationProxy/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADConnectorGroupApplicationProxy/1-Create.ps1 new file mode 100644 index 0000000000..2f3be28fb9 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADConnectorGroupApplicationProxy/1-Create.ps1 @@ -0,0 +1,36 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + AADConnectorGroupApplicationProxy "AADConnectorGroupApplicationProxy-testgroup" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Present"; + Id = "4984dcf7-d9e9-4663-90b4-5db09f92a669"; + Name = "testgroup"; + Region = "nam"; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADConnectorGroupApplicationProxy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADConnectorGroupApplicationProxy/2-Update.ps1 new file mode 100644 index 0000000000..fd34be2c06 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADConnectorGroupApplicationProxy/2-Update.ps1 @@ -0,0 +1,35 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADConnectorGroupApplicationProxy "AADConnectorGroupApplicationProxy-testgroup" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Present"; + Id = "4984dcf7-d9e9-4663-90b4-5db09f92a669"; + Name = "testgroup-new"; + Region = "nam"; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADConnectorGroupApplicationProxy/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADConnectorGroupApplicationProxy/3-Remove.ps1 new file mode 100644 index 0000000000..79c6eefb37 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADConnectorGroupApplicationProxy/3-Remove.ps1 @@ -0,0 +1,34 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + AADConnectorGroupApplicationProxy "AADConnectorGroupApplicationProxy-testgroup" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Absent"; + Id = "4984dcf7-d9e9-4663-90b4-5db09f92a669"; + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADConnectorGroupApplicationProxy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADConnectorGroupApplicationProxy.Tests.ps1 new file mode 100644 index 0000000000..8b3034c05e --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADConnectorGroupApplicationProxy.Tests.ps1 @@ -0,0 +1,198 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource "AADConnectorGroupApplicationProxy" -GenericStubModule $GenericStubPath +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName Get-PSSession -MockWith { + } + + Mock -CommandName Remove-PSSession -MockWith { + } + + Mock -CommandName Update-MgBetaOnPremisePublishingProfileConnectorGroup -MockWith { + } + + Mock -CommandName New-MgBetaOnPremisePublishingProfileConnectorGroup -MockWith { + } + + Mock -CommandName Remove-MgBetaOnPremisePublishingProfileConnectorGroup -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + Context -Name "The AADConnectorGroupApplicationProxy should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + Id = "FakeStringValue" + Name = "FakeStringValue" + Region = "nam" + Ensure = "Present" + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaOnPremisePublishingProfileConnectorGroup -MockWith { + return $null + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + It 'Should Create the group from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-MgBetaOnPremisePublishingProfileConnectorGroup -Exactly 1 + } + } + + Context -Name "The AADConnectorGroupApplicationProxy exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + Id = "FakeStringValue" + Name = "FakeStringValue" + Region = "nam" + Ensure = "Absent" + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaOnPremisePublishingProfileConnectorGroup -MockWith { + return @{ + Id = "FakeStringValue" + Name = "FakeStringValue" + Region = "nam" + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should Remove the group from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-MgBetaOnPremisePublishingProfileConnectorGroup -Exactly 1 + } + } + Context -Name "The AADConnectorGroupApplicationProxy Exists and Values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Id = "FakeStringValue" + Name = "FakeStringValue" + Region = "nam" + Ensure = "Present" + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaOnPremisePublishingProfileConnectorGroup -MockWith { + return @{ + Id = "FakeStringValue" + Name = "FakeStringValue" + Region = "nam" + + } + } + } + + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The AADConnectorGroupApplicationProxy exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Id = "FakeStringValue" + Name = "FakeStringValue" + Region = "nam" + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaOnPremisePublishingProfileConnectorGroup -MockWith { + return @{ + Id = "FakeStringValue" + Name = "NewFakeStringValue" + Region = "nam" + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Update-MgBetaOnPremisePublishingProfileConnectorGroup -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + + Mock -CommandName Get-MgBetaOnPremisePublishingProfileConnectorGroup -MockWith { + return @{ + Id = "FakeStringValue" + Name = "FakeStringValue" + Region = "nam" + + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index af684909f3..9a27e57934 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -94722,3 +94722,334 @@ function Update-MgBetaExternalConnection ) } #endregion +#region MgBetaOnPremisePublishingProfileConnectorGroup +function Get-MgBetaOnPremisePublishingProfileConnectorGroup +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $ConnectorGroupId, + + [Parameter()] + [System.String] + $OnPremisesPublishingProfileId, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject[]] + $HttpPipelineAppend, + + [Parameter()] + [PSObject[]] + $HttpPipelinePrepend, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $CountVariable + ) +} + +function New-MgBetaOnPremisePublishingProfileConnectorGroup +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $OnPremisesPublishingProfileId, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [PSObject[]] + $Applications, + + [Parameter()] + [System.String] + $ConnectorGroupType, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsDefault, + + [Parameter()] + [PSObject[]] + $Members, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.String] + $Region, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject[]] + $HttpPipelineAppend, + + [Parameter()] + [PSObject[]] + $HttpPipelinePrepend, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm + ) +} + +function Remove-MgBetaOnPremisePublishingProfileConnectorGroup +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $ConnectorGroupId, + + [Parameter()] + [System.String] + $OnPremisesPublishingProfileId, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject[]] + $HttpPipelineAppend, + + [Parameter()] + [PSObject[]] + $HttpPipelinePrepend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm + ) +} + +function Update-MgBetaOnPremisePublishingProfileConnectorGroup +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $ConnectorGroupId, + + [Parameter()] + [System.String] + $OnPremisesPublishingProfileId, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [PSObject[]] + $Applications, + + [Parameter()] + [System.String] + $ConnectorGroupType, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsDefault, + + [Parameter()] + [PSObject[]] + $Members, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.String] + $Region, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject[]] + $HttpPipelineAppend, + + [Parameter()] + [PSObject[]] + $HttpPipelinePrepend, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm + ) +} + +#endregion + From 23a3ec2d4d3800ae8746f3aaae1318ac7e8c6059 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 4 Oct 2024 10:54:42 +0000 Subject: [PATCH 035/252] Updated {Create} AAD Integration Tests --- .../M365DSCIntegration.AAD.Create.Tests.ps1 | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 index d45e6582da..c51f4401d2 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 @@ -149,6 +149,16 @@ SignInFrequencyValue = 1; State = "disabled"; } + AADConnectorGroupApplicationProxy 'AADConnectorGroupApplicationProxy-testgroup' + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Present"; + Id = "4984dcf7-d9e9-4663-90b4-5db09f92a669"; + Name = "testgroup"; + Region = "nam"; + } AADCrossTenantAccessPolicyConfigurationPartner 'AADCrossTenantAccessPolicyConfigurationPartner' { PartnerTenantId = "e7a80bcf-696e-40ca-8775-a7f85fbb3ebc"; # O365DSC.onmicrosoft.com From 4b8eef74a768a48ad379aacf537a3049337e6970 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 4 Oct 2024 10:54:59 +0000 Subject: [PATCH 036/252] Updated {Update} AAD Integration Tests --- .../M365DSCIntegration.AAD.Update.Tests.ps1 | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 index c9363e1d89..8fb74044f3 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 @@ -459,6 +459,16 @@ SignInFrequencyValue = 2; # Updated Porperty State = "disabled"; } + AADConnectorGroupApplicationProxy 'AADConnectorGroupApplicationProxy-testgroup' + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Present"; + Id = "4984dcf7-d9e9-4663-90b4-5db09f92a669"; + Name = "testgroup-new"; + Region = "nam"; + } AADCrossTenantAccessPolicy 'AADCrossTenantAccessPolicy' { AllowedCloudEndpoints = @("microsoftonline.us"); From d5b241abf69a0a11615ce2fa21ac349817f43db1 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 4 Oct 2024 10:55:12 +0000 Subject: [PATCH 037/252] Updated {Update} AAD Integration Tests --- .../M365DSCIntegration.AAD.Remove.Tests.ps1 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 index e4054cdd9c..50df775325 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 @@ -149,6 +149,14 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + AADConnectorGroupApplicationProxy 'AADConnectorGroupApplicationProxy-testgroup' + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Absent"; + Id = "4984dcf7-d9e9-4663-90b4-5db09f92a669"; + } AADCrossTenantAccessPolicyConfigurationPartner 'AADCrossTenantAccessPolicyConfigurationPartner' { ApplicationId = $ApplicationId From c1b857bc5a75a6aaf2495e3e20168dcd7f791402 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 4 Oct 2024 10:56:25 +0000 Subject: [PATCH 038/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 08ad6e8253..a7ecb03652 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -2499,6 +2499,66 @@ } ] }, + { + "ClassName": "MSFT_AADConnectorGroupApplicationProxy", + "Parameters": [ + { + "CIMType": "String", + "Name": "Name", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Region", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Id", + "Option": "Key" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "ApplicationSecret", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_AADCrossTenantAccessPolicy", "Parameters": [ From b3c5dc7fb2924043bd9b05a10ff4eb4614a96f87 Mon Sep 17 00:00:00 2001 From: "Ritik Mittal (from Dev Box)" Date: Fri, 4 Oct 2024 16:30:57 +0530 Subject: [PATCH 039/252] Added changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f91122ea29..6d7033497e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,8 @@ * Added ReportSuspiciousActivitySettings * AADAuthenticationMethodPolicyHardware * Initial release. +* AADConnectorGroupApplicationProxy + * Initial release. * AADEntitlementManagementSettings * Initial release. * AADFeatureRolloutPolicy From b48abe086a02e953cf54ed172355768504f60a0b Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Fri, 4 Oct 2024 12:33:43 +0200 Subject: [PATCH 040/252] Migrate Intune EDR resource to Settings Catalog cmdlets --- CHANGELOG.md | 4 + ...ntDetectionAndResponsePolicyWindows10.psm1 | 667 ++++++------------ ...ctionAndResponsePolicyWindows10.schema.mof | 1 + .../1-Create.ps1 | 3 + .../2-Update.ps1 | 3 + .../Modules/M365DSCDRGUtil.psm1 | 250 +------ ...ectionAndResponsePolicyWindows10.Tests.ps1 | 238 +++---- 7 files changed, 321 insertions(+), 845 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f91122ea29..fc03f0c5cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,13 @@ * AADEntitlementManagementSettings * Added support for ApplicationSecret +* IntuneEndpointDetectionAndResponsePolicyWindows10 + * Migrate to new Settings Catalog cmdlets. * M365DSCDRGUtil * Fixes an issue for the handling of skipped one-property elements in the Settings Catalog. FIXES [#5086](https://github.com/microsoft/Microsoft365DSC/issues/5086) + * Add Set support for secret Settings Catalog values + * Removed unused functions # 1.24.1002.1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyWindows10/MSFT_IntuneEndpointDetectionAndResponsePolicyWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyWindows10/MSFT_IntuneEndpointDetectionAndResponsePolicyWindows10.psm1 index 047fb4e9e6..a7a6ad3a6e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyWindows10/MSFT_IntuneEndpointDetectionAndResponsePolicyWindows10.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyWindows10/MSFT_IntuneEndpointDetectionAndResponsePolicyWindows10.psm1 @@ -12,6 +12,10 @@ function Get-TargetResource [System.String] $DisplayName, + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + [Parameter()] [System.String] $Description, @@ -96,106 +100,74 @@ function Get-TargetResource if ($null -eq $policy) { - Write-Verbose -Message "No Endpoint Detection And Response Policy with Id {$Identity} was found" - $policyTemplateID = '0385b795-0f2f-44ac-8602-9f65bf6adede_1' - $filter = "name eq '$DisplayName' and templateReference/TemplateId eq '$policyTemplateID'" - $policy = Get-MgBetaDeviceManagementConfigurationPolicy -Filter $filter -ErrorAction SilentlyContinue - if ($null -eq $policy) + Write-Verbose -Message "Could not find an Intune Endpoint Detection And Response Policy for Windows10 with Id {$Identity}" + + if (-not [System.String]::IsNullOrEmpty($DisplayName)) { - Write-Verbose -Message "No Endpoint Detection And Response Policy with displayName {$DisplayName} was found" - return $nullResult + $policy = Get-MgBetaDeviceManagementConfigurationPolicy ` + -Filter "Name eq '$DisplayName'" ` + -ErrorAction SilentlyContinue } } - $policy = Get-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $policy.Id -ExpandProperty 'settings' -ErrorAction SilentlyContinue - + if ($null -eq $policy) + { + Write-Verbose -Message "Could not find an Intune Endpoint Detection And Response Policy for Windows10 with Name {$DisplayName}." + return $nullResult + } $Identity = $policy.Id + Write-Verbose -Message "An Intune Endpoint Detection And Response Policy for Windows10 with Id {$Identity} and Name {$DisplayName} was found" - Write-Verbose -Message "Found Endpoint Detection And Response Policy with Id {$($policy.id)} and displayName {$($policy.Name)}" - - #Retrieve policy specific settings - $settings = @() - $settings += $policy.settings + # Retrieve policy specific settings + [array]$settings = Get-MgBetaDeviceManagementConfigurationPolicySetting ` + -DeviceManagementConfigurationPolicyId $Identity ` + -ExpandProperty 'settingDefinitions' ` + -ErrorAction Stop - $returnHashtable = @{} - $returnHashtable.Add('Identity', $Identity) - $returnHashtable.Add('DisplayName', $policy.name) - $returnHashtable.Add('Description', $policy.description) - - foreach ($setting in $settings.settingInstance) + $policySettings = @{} + $policySettings = Export-IntuneSettingCatalogPolicySettings -Settings $settings -ReturnHashtable $policySettings + if ($policySettings.ClientConfigurationPackageType -eq 'onboarding_fromconnector') { - $addToParameters = $true - $settingName = $setting.settingDefinitionId.Split('_') | Select-Object -Last 1 - - switch ($setting.AdditionalProperties.'@odata.type') - { - - '#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance' - { - $settingValue = $setting.AdditionalProperties.simpleSettingValue.value - } - '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' - { - $settingValue = $setting.AdditionalProperties.choiceSettingValue.value.split('_') | Select-Object -Last 1 - } - '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance' - { - $values = @() - foreach ($value in $setting.AdditionalProperties.groupSettingCollectionValue.children) - { - $settingName = $value.settingDefinitionId.split('_') | Select-Object -Last 1 - $settingValue = $value.choiceSettingValue.value.split('_') | Select-Object -Last 1 - $returnHashtable.Add($settingName, $settingValue) - $addToParameters = $false - } - } - '#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance' - { - $values = @() - foreach ($value in $setting.AdditionalProperties.simpleSettingCollectionValue.value) - { - $values += $value - } - $settingValue = $values - } - Default - { - $settingValue = $setting.value - } - } - - if ($addToParameters) - { - $returnHashtable.Add($settingName, $settingValue) - } - + $policySettings.Add('ConfigurationType', 'AutoFromConnector') } - - #Removing telemetryreportingfrequency as deprecated and doen't need to be evaluated adn enforced - $returnHashtable.Remove('telemetryreportingfrequency') - - $returnAssignments = @() - $currentAssignments = Get-MgBetaDeviceManagementConfigurationPolicyAssignment -DeviceManagementConfigurationPolicyId $Identity -All - - if ($null -ne $currentAssignments -and $currentAssignments.count -gt 0 ) + else { - $returnAssignments += ConvertFrom-IntunePolicyAssignment -Assignments ($currentAssignments) + $policySettings.Add('ConfigurationType', $policySettings.ClientConfigurationPackageType) } + $policySettings.Remove('ClientConfigurationPackageType') + $policySettings.Remove('onboarding') + $policySettings.Remove('offboarding') + $policySettings.Remove('onboarding_fromconnector') + + # Removing TelemetryReportingFrequency because it's deprecated and doesn't need to be evaluated and enforced + $policySettings.Remove('telemetryreportingfrequency') + + $results = @{ + #region resource generator code + Description = $policy.Description + DisplayName = $policy.Name + RoleScopeTagIds = $policy.RoleScopeTagIds + Identity = $policy.Id + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + #endregion + } + $results += $policySettings - $returnHashtable.Add('Assignments', $returnAssignments) - - Write-Verbose -Message "Found Endpoint Protection Policy {$($policy.name)}" - - $returnHashtable.Add('Ensure', 'Present') - $returnHashtable.Add('Credential', $Credential) - $returnHashtable.Add('ApplicationId', $ApplicationId) - $returnHashtable.Add('TenantId', $TenantId) - $returnHashtable.Add('ApplicationSecret', $ApplicationSecret) - $returnHashtable.Add('CertificateThumbprint', $CertificateThumbprint) - $returnHashtable.Add('ManagedIdentity', $ManagedIdentity.IsPresent) - $returnHashtable.Add("AccessTokens", $AccessTokens) + $assignmentsValues = Get-MgBetaDeviceManagementConfigurationPolicyAssignment -DeviceManagementConfigurationPolicyId $Identity + $assignmentResult = @() + if ($assignmentsValues.Count -gt 0) + { + $assignmentResult += ConvertFrom-IntunePolicyAssignment -Assignments $assignmentsValues -IncludeDeviceFilter $true + } + $results.Add('Assignments', $assignmentResult) - return $returnHashtable + return $results } catch { @@ -222,6 +194,10 @@ function Set-TargetResource [System.String] $DisplayName, + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + [Parameter()] [System.String] $Description, @@ -291,14 +267,35 @@ function Set-TargetResource #endregion $currentPolicy = Get-TargetResource @PSBoundParameters - $PSBoundParameters.Remove('Ensure') | Out-Null - $PSBoundParameters.Remove('Credential') | Out-Null - $PSBoundParameters.Remove('ApplicationId') | Out-Null - $PSBoundParameters.Remove('TenantId') | Out-Null - $PSBoundParameters.Remove('ApplicationSecret') | Out-Null - $PSBoundParameters.Remove('CertificateThumbprint') | Out-Null - $PSBoundParameters.Remove('ManagedIdentity') | Out-Null - $PSBoundParameters.Remove('AccessTokens') | Out-Null + $BoundParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + switch ($ConfigurationType) + { + 'AutoFromConnector' + { + $BoundParameters.Add('ClientConfigurationPackageType', 'onboarding_fromconnector') + $BoundParameters.Add('onboarding_fromconnector', $ConfigurationBlob) + $BoundParameters.Remove('ConfigurationBlob') | Out-Null + } + 'Onboard' + { + $BoundParameters.Add('ClientConfigurationPackageType', 'onboard') + $BoundParameters.Add('onboarding', $ConfigurationBlob) + $BoundParameters.Remove('ConfigurationBlob') | Out-Null + } + 'Offboard' + { + $BoundParameters.Add('ClientConfigurationPackageType', 'offboard') + $BoundParameters.Add('offboarding', $ConfigurationBlob) + $BoundParameters.Remove('ConfigurationBlob') | Out-Null + } + } + + if ([System.String]::IsNullOrEmpty($ConfigurationBlob)) + { + throw "ConfigurationBlob is required for configurationType '$($DSCParams.ConfigurationType)'" + } + $BoundParameters.Remove('ConfigurationType') | Out-Null $templateReferenceId = '0385b795-0f2f-44ac-8602-9f65bf6adede_1' $platforms = 'windows10' @@ -306,82 +303,64 @@ function Set-TargetResource if ($Ensure -eq 'Present' -and $currentPolicy.Ensure -eq 'Absent') { - Write-Verbose -Message "Creating new Endpoint Protection Policy {$DisplayName}" - $PSBoundParameters.Remove('Assignments') | Out-Null + Write-Verbose -Message "Creating an Intune Endpoint Protection And Response Policy for Windows10 with Name {$DisplayName}" + $BoundParameters.Remove('Assignments') | Out-Null - $settings = @() - $formattedSettings = Get-IntuneSettingCatalogPolicySetting ` - -DSCParams ([System.Collections.Hashtable]$PSBoundParameters) ` + $settings = Get-IntuneSettingCatalogPolicySetting ` + -DSCParams ([System.Collections.Hashtable]$BoundParameters) ` -TemplateId $templateReferenceId - if ($null -ne $formattedSettings) - { - $settings += $formattedSettings - } - $createParameters = @{ - name = $DisplayName - description = $Description - templateReference = @{templateId = $templateReferenceId } - platforms = $platforms - technologies = $technologies - settings = $settings + Name = $DisplayName + Description = $Description + TemplateReference = @{ templateId = $templateReferenceId } + Platforms = $platforms + Technologies = $technologies + Settings = $settings } - write-verbose ($createParameters|convertto-json -depth 100) + #region resource generator code $policy = New-MgBetaDeviceManagementConfigurationPolicy -bodyParameter $createParameters - $assignmentsHash = @() - if ($null -ne $Assignments -and $Assignments.count -gt 0 ) + if ($policy.Id) { - $assignmentsHash += ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + Update-DeviceConfigurationPolicyAssignment ` + -DeviceConfigurationPolicyId $policy.Id ` + -Targets $assignmentsHash ` + -Repository 'deviceManagement/configurationPolicies' } - - Update-DeviceConfigurationPolicyAssignment ` - -DeviceConfigurationPolicyId $policy.id ` - -Targets $assignmentsHash - + #endregion } elseif ($Ensure -eq 'Present' -and $currentPolicy.Ensure -eq 'Present') { - Write-Verbose -Message "Updating existing Endpoint Protection Policy {$($currentPolicy.DisplayName)}" - $PSBoundParameters.Remove('Assignments') | Out-Null + Write-Verbose -Message "Updating the Intune Endpoint Protection And Response Policy for Windows10 {$($currentPolicy.DisplayName)}" + $BoundParameters.Remove('Assignments') | Out-Null - #format settings from PSBoundParameters for update - $settings = @() - $formattedSettings = Get-IntuneSettingCatalogPolicySetting ` - -DSCParams ([System.Collections.Hashtable]$PSBoundParameters) ` + $settings = Get-IntuneSettingCatalogPolicySetting ` + -DSCParams ([System.Collections.Hashtable]$BoundParameters) ` -TemplateId $templateReferenceId - if ($null -ne $formattedSettings) - { - $settings += $formattedSettings - } - - Update-DeviceManagementConfigurationPolicy ` - -DeviceManagementConfigurationPolicyId $currentPolicy.Identity ` - -DisplayName $DisplayName ` + Update-IntuneDeviceConfigurationPolicy ` + -DeviceConfigurationPolicyId $currentPolicy.Identity ` + -Name $DisplayName ` -Description $Description ` - -TemplateReference $templateReferenceId ` + -TemplateReferenceId $templateReferenceId ` -Platforms $platforms ` -Technologies $technologies ` -Settings $settings - #region update policy assignments - $assignmentsHash = @() - if ($null -ne $Assignments -and $Assignments.count -gt 0 ) - { - $assignmentsHash += ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments - } - + #region resource generator code + $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments Update-DeviceConfigurationPolicyAssignment ` -DeviceConfigurationPolicyId $currentPolicy.Identity ` - -Targets $assignmentsHash + -Targets $assignmentsHash ` + -Repository 'deviceManagement/configurationPolicies' #endregion } elseif ($Ensure -eq 'Absent' -and $currentPolicy.Ensure -eq 'Present') { - Write-Verbose -Message "Removing Endpoint Protection Policy {$($currentPolicy.DisplayName)}" + Write-Verbose -Message "Removing the Intune Endpoint Protection And Response Policy for Windows 10 with Id {$($currentPolicy.Identity)}" Remove-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $currentPolicy.Identity } } @@ -400,6 +379,10 @@ function Test-TargetResource [System.String] $DisplayName, + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + [Parameter()] [System.String] $Description, @@ -467,34 +450,69 @@ function Test-TargetResource -Parameters $PSBoundParameters Add-M365DSCTelemetryEvent -Data $data #endregion - Write-Verbose -Message "Testing configuration of Endpoint Protection Policy {$DisplayName}" + Write-Verbose -Message "Testing configuration of the Intune Endpoint Protection And Response Policy for Windows10 with Id {$Identity} and Name {$DisplayName}" $CurrentValues = Get-TargetResource @PSBoundParameters + [Hashtable]$ValuesToCheck = @{} + $MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object { + if ($_.Key -notlike '*Variable' -or $_.Key -notin @('Verbose', 'Debug', 'ErrorAction', 'WarningAction', 'InformationAction')) + { + if ($null -ne $CurrentValues[$_.Key] -or $null -ne $PSBoundParameters[$_.Key]) + { + $ValuesToCheck.Add($_.Key, $null) + if (-not $PSBoundParameters.ContainsKey($_.Key)) + { + $PSBoundParameters.Add($_.Key, $null) + } + } + } + } - Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" - Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + if ($CurrentValues.Ensure -ne $Ensure) + { + Write-Verbose -Message "Test-TargetResource returned $false" + return $false + } + $testResult = $true + + #Compare Cim instances + foreach ($key in $PSBoundParameters.Keys) + { + $source = $PSBoundParameters.$key + $target = $CurrentValues.$key + if ($null -ne $source -and $source.GetType().Name -like '*CimInstance*') + { + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + if (-not $testResult) + { + break + } + + $ValuesToCheck.Remove($key) | Out-Null + } + } - $ValuesToCheck = ([hashtable]$PSBoundParameters).clone() $ValuesToCheck.Remove('Identity') | Out-Null $ValuesToCheck.Remove('ConfigurationBlob') | Out-Null + $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck - $source = $PSBoundParameters.Assignments - $target = $CurrentValues.Assignments - $ValuesToCheck.Remove('Assignments') | Out-Null - - $testResult = Compare-M365DSCIntunePolicyAssignment -Source $source -Target $target + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" if ($testResult) { - $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` -Source $($MyInvocation.MyCommand.Source) ` -DesiredValues $PSBoundParameters ` -ValuesToCheck $ValuesToCheck.Keys } - Write-Verbose -Message "Test-TargetResource returned $TestResult" + Write-Verbose -Message "Test-TargetResource returned $testResult" - return $TestResult + return $testResult } function Export-TargetResource @@ -558,9 +576,12 @@ function Export-TargetResource { $policyTemplateID = '0385b795-0f2f-44ac-8602-9f65bf6adede_1' [array]$policies = Get-MgBetaDeviceManagementConfigurationPolicy ` - -All:$true ` + -All ` -Filter $Filter ` - -ErrorAction Stop | Where-Object -FilterScript { $_.TemplateReference.TemplateId -eq $policyTemplateID } ` + -ErrorAction Stop | Where-Object ` + -FilterScript { + $_.TemplateReference.TemplateId -eq $policyTemplateID + } if ($policies.Length -eq 0) { @@ -593,48 +614,38 @@ function Export-TargetResource } $Results = Get-TargetResource @params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results - if ($Results.Ensure -eq 'Present') + if ($Results.Assignments) { - $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` - -Results $Results - - if ($Results.Assignments) + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString -ComplexObject ([Array]$Results.Assignments) -CIMInstanceName DeviceManagementConfigurationPolicyAssignments + if ($complexTypeStringResult) { - $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString -ComplexObject ([Array]$Results.Assignments) -CIMInstanceName DeviceManagementConfigurationPolicyAssignments - if ($complexTypeStringResult) - { - $Results.Assignments = $complexTypeStringResult - } - else - { - $Results.Remove('Assignments') | Out-Null - } + $Results.Assignments = $complexTypeStringResult } - - $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` - -ConnectionMode $ConnectionMode ` - -ModulePath $PSScriptRoot ` - -Results $Results ` - -Credential $Credential - - if ($Results.Assignments) + else { - $isCIMArray = $false - if ($Results.Assignments.getType().Fullname -like '*[[\]]') - { - $isCIMArray = $true - } - $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Assignments' -IsCIMArray:$isCIMArray + $Results.Remove('Assignments') | Out-Null } + } - $dscContent += $currentDSCBlock - Save-M365DSCPartialExport -Content $currentDSCBlock ` - -FileName $Global:PartialExportFileName + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential - Write-Host $Global:M365DSCEmojiGreenCheckMark - $i++ + if ($Results.Assignments) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "Assignments" -IsCIMArray:$true } + + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark } return $dscContent } @@ -661,278 +672,4 @@ function Export-TargetResource } } -function Get-IntuneSettingCatalogPolicySetting -{ - [CmdletBinding()] - [OutputType([System.Array])] - param( - [Parameter(Mandatory = 'true')] - [System.Collections.Hashtable] - $DSCParams, - [Parameter(Mandatory = 'true')] - [System.String] - $TemplateId - ) - - $DSCParams.Remove('Identity') | Out-Null - $DSCParams.Remove('DisplayName') | Out-Null - $DSCParams.Remove('Description') | Out-Null - - #Prepare setting definitions mapping - $settingDefinitions = Get-MgBetaDeviceManagementConfigurationPolicyTemplateSettingTemplate -DeviceManagementConfigurationPolicyTemplateId $TemplateId - $settingInstances = @() - foreach ($settingDefinition in $settingDefinitions.SettingInstanceTemplate) - { - - $settingInstance = @{} - $settingName = $settingDefinition.SettingDefinitionId.split('_') | Select-Object -Last 1 - $settingType = $settingDefinition.AdditionalProperties.'@odata.type'.replace('InstanceTemplate', 'Instance') - $settingInstance.Add('settingDefinitionId', $settingDefinition.settingDefinitionId) - $settingInstance.Add('@odata.type', $settingType) - if (-Not [string]::IsNullOrEmpty($settingDefinition.settingInstanceTemplateId)) - { - $settingInstance.Add('settingInstanceTemplateReference', @{'settingInstanceTemplateId' = $settingDefinition.settingInstanceTemplateId }) - } - $settingValueName = $settingType.replace('#microsoft.graph.deviceManagementConfiguration', '').replace('Instance', 'Value') - $settingValueName = $settingValueName.Substring(0, 1).ToLower() + $settingValueName.Substring(1, $settingValueName.length - 1 ) - $settingValueType = $settingDefinition.AdditionalProperties."$($settingValueName)Template".'@odata.type' - if ($null -ne $settingValueType) - { - $settingValueType = $settingValueType.replace('ValueTemplate', 'Value') - } - $settingValueTemplateId = $settingDefinition.AdditionalProperties."$($settingValueName)Template".settingValueTemplateId - $settingValue = Get-IntuneSettingCatalogPolicySettingInstanceValue ` - -DSCParams $DSCParams ` - -SettingDefinition $settingDefinition ` - -SettingName $settingName ` - -SettingType $settingType ` - -SettingValueName $settingValueName ` - -SettingValueType $settingValueType ` - -SettingValueTemplateId $settingValueTemplateId - - if ($null -ne $settingValue) { - $childSettingType = "" - switch ($DSCParams['ConfigurationType']) - { - 'AutoFromConnector' - { - $childSettingType = 'onboarding_fromconnector' - } - 'Onboard' - { - $childSettingType = 'onboarding' - } - 'Offboard' - { - $childSettingType = 'offboarding' - } - } - - if ($settingName -eq 'configurationType') - { - if ([System.String]::IsNullOrEmpty($DSCParams['ConfigurationBlob'])) - { - throw "ConfigurationBlob is required for configurationType '$($DSCParams['ConfigurationType'])'" - } - - $children = @() - $children += @{ - '@odata.type' = "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance" - settingDefinitionId = "device_vendor_msft_windowsadvancedthreatprotection_$($childSettingType)" - simpleSettingValue = @{ - '@odata.type' = "#microsoft.graph.deviceManagementConfigurationSecretSettingValue" - value = $DSCParams['ConfigurationBlob'] - valueState = "NotEncrypted" - } - } - $settingValue.choiceSettingValue.Add("children", $children) - } - $settingInstance += ($settingValue) - $settingInstances += @{ - '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' - 'settingInstance' = $settingInstance - } - } else { - Continue - } - } - - return $settingInstances -} - -function Get-IntuneSettingCatalogPolicySettingInstanceValue -{ - [CmdletBinding()] - [OutputType([System.Collections.Hashtable])] - param( - [Parameter(Mandatory = 'true')] - [System.Collections.Hashtable] - $DSCParams, - - [Parameter()] - $SettingDefinition, - - [Parameter()] - [System.String] - $SettingType, - - [Parameter()] - [System.String] - $SettingName, - - [Parameter()] - [System.String] - $SettingValueName, - - [Parameter()] - [System.String] - $SettingValueType, - - [Parameter()] - [System.String] - $SettingValueTemplateId - ) - - $settingValueReturn = @{} - switch ($settingType) - { - '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance' - { - $groupSettingCollectionValue = @{} - $groupSettingCollectionValueChildren = @() - - $groupSettingCollectionDefinitionChildren = $SettingDefinition.AdditionalProperties.groupSettingCollectionValueTemplate.children - foreach ($childDefinition in $groupSettingCollectionDefinitionChildren) - { - $childSettingName = $childDefinition.settingDefinitionId.split('_') | Select-Object -Last 1 - $childSettingType = $childDefinition.'@odata.type'.replace('InstanceTemplate', 'Instance') - $childSettingValueName = $childSettingType.replace('#microsoft.graph.deviceManagementConfiguration', '').replace('Instance', 'Value') - $childSettingValueType = "#microsoft.graph.deviceManagementConfiguration$($childSettingValueName)" - $childSettingValueName = $childSettingValueName.Substring(0, 1).ToLower() + $childSettingValueName.Substring(1, $childSettingValueName.length - 1 ) - $childSettingValueTemplateId = $childDefinition.$childSettingValueName.settingValueTemplateId - $childSettingValue = Get-IntuneSettingCatalogPolicySettingInstanceValue ` - -DSCParams $DSCParams ` - -SettingDefinition $childDefinition ` - -SettingName $childSettingName ` - -SettingType $childDefinition.'@odata.type' ` - -SettingValueName $childSettingValueName ` - -SettingValueType $childSettingValueType ` - -SettingValueTemplateId $childSettingValueTemplateId - - if ($null -ne $childSettingValue) - { - $childSettingValue.add('settingDefinitionId', $childDefinition.settingDefinitionId) - $childSettingValue.add('@odata.type', $childSettingType ) - $groupSettingCollectionValueChildren += $childSettingValue - } - } - $groupSettingCollectionValue.add('children', $groupSettingCollectionValueChildren) - $settingValueReturn.Add('groupSettingCollectionValue', @($groupSettingCollectionValue)) - } - '#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance' - { - $values = @() - foreach ( $key in $DSCParams.Keys) - { - if ($settingName -eq ($key.tolower())) - { - $values = $DSCParams[$key] - break - } - } - $settingValueCollection = @() - foreach ($v in $values) - { - $settingValueCollection += @{ - value = $v - '@odata.type' = $settingValueType - } - } - $settingValueReturn.Add($settingValueName, $settingValueCollection) - } - Default - { - $value = $null - foreach ( $key in $DSCParams.Keys) - { - if ($settingName -eq ($key.tolower())) - { - $value = "$($SettingDefinition.settingDefinitionId)_$($DSCParams[$key])" - break - } - } - $settingValue = @{} - - if (-Not [string]::IsNullOrEmpty($settingValueType)) - { - $settingValue.add('@odata.type', $settingValueType) - } - if (-Not [string]::IsNullOrEmpty($settingValueTemplateId)) - { - $settingValue.Add('settingValueTemplateReference', @{'settingValueTemplateId' = $settingValueTemplateId }) - } - $settingValue.add('value', $value) - if ($null -eq $value) - { - return $null - } - $settingValueReturn.Add($settingValueName, $settingValue) - } - } - return $settingValueReturn -} - -function Update-DeviceManagementConfigurationPolicy -{ - [CmdletBinding()] - param ( - [Parameter(Mandatory = 'true')] - [System.String] - $DeviceManagementConfigurationPolicyId, - - [Parameter(Mandatory = 'true')] - [System.String] - $DisplayName, - - [Parameter()] - [System.String] - $Description, - - [Parameter()] - [System.String] - $TemplateReferenceId, - - [Parameter()] - [System.String] - $Platforms, - - [Parameter()] - [System.String] - $Technologies, - - [Parameter()] - [System.Array] - $Settings - ) - - $templateReference = @{ - 'templateId' = $TemplateReferenceId - } - - $Uri = "https://graph.microsoft.com/beta/deviceManagement/ConfigurationPolicies/$DeviceManagementConfigurationPolicyId" - $policy = [ordered]@{ - 'name' = $DisplayName - 'description' = $Description - 'platforms' = $Platforms - 'technologies' = $Technologies - 'templateReference' = $templateReference - 'settings' = $Settings - } - #write-verbose (($policy|ConvertTo-Json -Depth 20)) - Invoke-MgGraphRequest -Method PUT ` - -Uri $Uri ` - -ContentType 'application/json' ` - -Body ($policy | ConvertTo-Json -Depth 20) 4> $null -} - Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyWindows10/MSFT_IntuneEndpointDetectionAndResponsePolicyWindows10.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyWindows10/MSFT_IntuneEndpointDetectionAndResponsePolicyWindows10.schema.mof index 6b2b758d61..f4dc9d7295 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyWindows10/MSFT_IntuneEndpointDetectionAndResponsePolicyWindows10.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyWindows10/MSFT_IntuneEndpointDetectionAndResponsePolicyWindows10.schema.mof @@ -14,6 +14,7 @@ class MSFT_IntuneEndpointDetectionAndResponsePolicyWindows10 : OMI_BaseResource { [Write, Description("Identity of the endpoint detection and response policy for Windows 10.")] String Identity; [Key, Description("Display name of the endpoint detection and response policy for Windows 10.")] String DisplayName; + [Write, Description("List of Scope Tags for this Entity instance.")] String RoleScopeTagIds[]; [Write, Description("Description of the endpoint detection and response policy for Windows 10.")] String Description; [Write, Description("Assignments of the endpoint detection and response policy for Windows 10."), EmbeddedInstance("MSFT_DeviceManagementConfigurationPolicyAssignments")] String Assignments[]; [Write, Description("Return or set Windows Defender Advanced Threat Protection Sample Sharing configuration parameter: 0 - none, 1 - All"), ValueMap{"0", "1"}, Values{"0", "1"}] String SampleSharing; diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyWindows10/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyWindows10/1-Create.ps1 index 2cf142bdf2..85a7af0f70 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyWindows10/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyWindows10/1-Create.ps1 @@ -31,6 +31,9 @@ Configuration Example ApplicationId = $ApplicationId; TenantId = $TenantId; CertificateThumbprint = $CertificateThumbprint; + ConfigurationBlob = "Blob" + ConfigurationType = "onboard" + SampleSharing = 1 } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyWindows10/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyWindows10/2-Update.ps1 index 21679df4b0..e68894c238 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyWindows10/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyWindows10/2-Update.ps1 @@ -31,6 +31,9 @@ Configuration Example ApplicationId = $ApplicationId; TenantId = $TenantId; CertificateThumbprint = $CertificateThumbprint; + ConfigurationBlob = "Blob" + ConfigurationType = "onboard" + SampleSharing = 1 } } } diff --git a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 index 962544bf28..8d1e1f69d7 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 @@ -501,7 +501,6 @@ function Get-M365DSCDRGSimpleObjectTypeToString [Parameter()] [System.String] $Space = ' ' - ) $returnValue = '' @@ -837,250 +836,6 @@ function Convert-M365DSCDRGComplexTypeToHashtable return [hashtable]$results } -function Get-SettingCatalogSettingValue -{ - [CmdletBinding()] - [OutputType([System.Collections.Hashtable],[System.Collections.Hashtable[]])] - param ( - [Parameter()] - $SettingValue, - [Parameter()] - $SettingValueType - - ) - - switch -Wildcard ($SettingValueType) - { - '*ChoiceSettingInstance' - { - $complexValue = @{} - $complexValue.Add('odataType',$SettingValue.'@odata.type') - $complexValue.Add('Value',$SettingValue.value) - $children = @() - foreach($child in $SettingValue.children) - { - $complexChild = @{} - $complexChild.Add('SettingDefinitionId', $child.settingDefinitionId) - $complexChild.Add('odataType', $child.'@odata.type') - $valueName = $child.'@odata.type'.replace('#microsoft.graph.deviceManagementConfiguration', '').replace('Instance', 'Value') - $valueName = Get-StringFirstCharacterToLower -Value $valueName - $rawValue = $child.$valueName - $childSettingValue = Get-SettingCatalogSettingValue -SettingValue $rawValue -SettingValueType $child.'@odata.type' - $complexChild.Add($valueName,$childSettingValue) - $children += $complexChild - } - $complexValue.Add('Children',$children) - } - '*ChoiceSettingCollectionInstance' - { - $complexCollection = @() - foreach($item in $SettingValue) - { - $complexValue = @{} - $complexValue.Add('Value',$item.value) - $children = @() - foreach($child in $item.children) - { - $complexChild = @{} - $complexChild.Add('SettingDefinitionId', $child.settingDefinitionId) - $complexChild.Add('odataType', $child.'@odata.type') - $valueName = $child.'@odata.type'.replace('#microsoft.graph.deviceManagementConfiguration', '').replace('Instance', 'Value') - $valueName = Get-StringFirstCharacterToLower -Value $valueName - $rawValue = $child.$valueName - $childSettingValue = Get-SettingCatalogSettingValue -SettingValue $rawValue -SettingValueType $child.'@odata.type' - $complexChild.Add($valueName,$childSettingValue) - $children += $complexChild - } - $complexValue.Add('Children',$children) - $complexCollection += $complexValue - } - return ,([hashtable[]]$complexCollection) - } - '*SimpleSettingInstance' - { - $complexValue = @{} - $complexValue.Add('odataType',$SettingValue.'@odata.type') - $valueName = 'IntValue' - $value = $SettingValue.value - if($SettingValue.'@odata.type' -ne '#microsoft.graph.deviceManagementConfigurationIntegerSettingValue') - { - $valueName = 'StringValue' - } - $complexValue.Add($valueName,$value) - if($SettingValue.'@odata.type' -eq '#microsoft.graph.deviceManagementConfigurationSecretSettingValue') - { - $complexValue.Add('ValueState',$SettingValue.valueState) - } - } - '*SimpleSettingCollectionInstance' - { - $complexCollection = @() - - foreach($item in $SettingValue) - { - $complexValue = @{} - $complexValue.Add('odataType',$item.'@odata.type') - $valueName = 'IntValue' - $value = $item.value - if($item.'@odata.type' -ne '#microsoft.graph.deviceManagementConfigurationIntegerSettingValue') - { - $valueName = 'StringValue' - } - $complexValue.Add($valueName,$value) - if($item.'@odata.type' -eq '#microsoft.graph.deviceManagementConfigurationSecretSettingValue') - { - $complexValue.Add('ValueState',$item.valueState) - } - $complexCollection += $complexValue - } - return ,([hashtable[]]$complexCollection) - } - '*GroupSettingInstance' - { - $complexValue = @{} - $complexValue.Add('odataType',$SettingValue.'@odata.type') - $children = @() - foreach($child in $SettingValue.children) - { - $complexChild = @{} - $complexChild.Add('SettingDefinitionId', $child.settingDefinitionId) - $complexChild.Add('odataType', $child.'@odata.type') - $valueName = $child.'@odata.type'.replace('#microsoft.graph.deviceManagementConfiguration', '').replace('Instance', 'Value') - $valueName = Get-StringFirstCharacterToLower -Value $valueName - $rawValue = $child.$valueName - $settingValue = Get-SettingCatalogSettingValue -SettingValue $rawValue -SettingValueType $child.'@odata.type' - $complexChild.Add($valueName,$settingValue) - $children += $complexChild - } - $complexValue.Add('Children',$children) - } - '*GroupSettingCollectionInstance' - { - $complexCollection = @() - foreach($groupSettingValue in $SettingValue) - { - $complexValue = @{} - #$complexValue.Add('odataType',$SettingValue.'@odata.type') - $children = @() - foreach($child in $groupSettingValue.children) - { - $complexChild = @{} - $complexChild.Add('SettingDefinitionId', $child.settingDefinitionId) - $complexChild.Add('odataType', $child.'@odata.type') - $valueName = $child.'@odata.type'.replace('#microsoft.graph.deviceManagementConfiguration', '').replace('Instance', 'Value') - $valueName = Get-StringFirstCharacterToLower -Value $valueName - $rawValue = $child.$valueName - $settingValue = Get-SettingCatalogSettingValue -SettingValue $rawValue -SettingValueType $child.'@odata.type' - $complexChild.Add($valueName,$settingValue) - $children += $complexChild - } - $complexValue.Add('Children',$children) - $complexCollection += $complexValue - } - return ,([hashtable[]]$complexCollection) - } - } - return $complexValue -} - -function Get-SettingCatalogPolicySettingsFromTemplate -{ - [CmdletBinding()] - [OutputType([System.Array])] - param - ( - [Parameter(Mandatory = $true)] - [System.Collections.Hashtable] - $DSCParams, - - [Parameter(Mandatory = $true)] - [System.String] - $templateReferenceId - ) - - $DSCParams.Remove('Identity') | Out-Null - $DSCParams.Remove('DisplayName') | Out-Null - $DSCParams.Remove('Description') | Out-Null - - $settings = @() - - $templateSettings = Get-MgDeviceManagementConfigurationPolicyTemplateSettingTemplate -DeviceManagementConfigurationPolicyTemplateId $templateReferenceId - - $simpleSettings = @() - $simpleSettings += $templateSettings.SettingInstanceTemplate | Where-Object -FilterScript ` - { $_.AdditionalProperties.'@odata.type' -ne '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstanceTemplate' } - foreach ($templateSetting in $simpleSettings) - { - $setting = @{} - $settingKey = $DSCParams.keys | Where-Object -FilterScript { $templateSetting.settingDefinitionId -like "*$($_)" } - if ((-not [String]::IsNullOrEmpty($settingKey)) -and $DSCParams."$settingKey") - { - $setting.Add('@odata.type', '#microsoft.graph.deviceManagementConfigurationSetting') - $myFormattedSetting = Format-M365DSCParamsToSettingInstance -DSCParams @{$settingKey = $DSCParams."$settingKey" } ` - -TemplateSetting $templateSetting - - $setting.Add('settingInstance', $myFormattedSetting) - $settings += $setting - $DSCParams.Remove($settingKey) | Out-Null - } - } - - #Prepare attacksurfacereductionrules groupCollectionTemplateSettings - $groupCollectionTemplateSettings = @() - $groupCollectionTemplateSettings += $templateSettings.SettingInstanceTemplate | Where-Object -FilterScript ` - { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstanceTemplate' } - - foreach ($groupCollectionTemplateSetting in $groupCollectionTemplateSettings) - { - $setting = @{} - $setting.Add('@odata.type', '#microsoft.graph.deviceManagementConfigurationSetting') - $settingInstance = [ordered]@{} - $settingInstance.Add('@odata.type', '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance') - $settingInstance.Add('settingDefinitionId', $groupCollectionTemplateSetting.settingDefinitionId) - $settingInstance.Add('settingInstanceTemplateReference', @{ - '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSettingInstanceTemplateReference' - 'settingInstanceTemplateId' = $groupCollectionTemplateSetting.settingInstanceTemplateId - }) - $groupSettingCollectionValues = @() - $groupSettingCollectionValueChildren = @() - $groupSettingCollectionValue = @{} - $groupSettingCollectionValue.Add('@odata.type', '#microsoft.graph.deviceManagementConfigurationGroupSettingValue') - - $settingValueTemplateId = $groupCollectionTemplateSetting.AdditionalProperties.groupSettingCollectionValueTemplate.settingValueTemplateId - if (-Not [string]::IsNullOrEmpty($settingValueTemplateId)) - { - $groupSettingCollectionValue.Add('settingValueTemplateReference', @{'settingValueTemplateId' = $SettingValueTemplateId }) - } - - foreach ($key in $DSCParams.keys) - { - $templateValue = $groupCollectionTemplateSetting.AdditionalProperties.groupSettingCollectionValueTemplate.children | Where-Object ` - -FilterScript { $_.settingDefinitionId -like "*$key" } - if ($templateValue) - { - $groupSettingCollectionValueChild = Format-M365DSCParamsToSettingInstance ` - -DSCParams @{$key = $DSCParams."$key" } ` - -TemplateSetting $templateValue ` - -IncludeSettingValueTemplateId $false ` - -IncludeSettingInstanceTemplateId $false - - $groupSettingCollectionValueChildren += $groupSettingCollectionValueChild - } - } - $groupSettingCollectionValue.Add('children', $groupSettingCollectionValueChildren) - $groupSettingCollectionValues += $groupSettingCollectionValue - $settingInstance.Add('groupSettingCollectionValue', $groupSettingCollectionValues) - $setting.Add('settingInstance', $settingInstance) - - if ($setting.settingInstance.groupSettingCollectionValue.children.count -gt 0) - { - $settings += $setting - } - } - - return $settings -} - function ConvertFrom-IntunePolicyAssignment { [CmdletBinding()] @@ -1965,6 +1720,11 @@ function Get-IntuneSettingCatalogPolicySettingInstanceValue $settingValue = @{} if (-not [string]::IsNullOrEmpty($SettingValueType)) { + if ($SettingDefinition.AdditionalProperties.valueDefinition.isSecret) + { + $SettingValueType = "#microsoft.graph.deviceManagementConfigurationSecretSettingValue" + $settingValue.Add('valueState', 'NotEncrypted') + } $settingValue.Add('@odata.type', $SettingValueType) } if (-not [string]::IsNullOrEmpty($settingValueTemplateId)) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneEndpointDetectionAndResponsePolicyWindows10.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneEndpointDetectionAndResponsePolicyWindows10.Tests.ps1 index fc863b5c09..e9801b6c53 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneEndpointDetectionAndResponsePolicyWindows10.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneEndpointDetectionAndResponsePolicyWindows10.Tests.ps1 @@ -44,12 +44,101 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Remove-MgBetaDeviceManagementConfigurationPolicy -MockWith { } - Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicyTemplate -MockWith { + Mock -CommandName Update-IntuneDeviceConfigurationPolicy -MockWith { + } + + Mock -CommandName Get-IntuneSettingCatalogPolicySetting -MockWith { + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicy -MockWith { return @{ - TemplateId = '0385b795-0f2f-44ac-8602-9f65bf6adede_1' + Id = '619bd4a4-3b3b-4441-bd6f-3f4c0c444870' + Description = 'My Test Description' + Name = 'My Test' + Platforms = "windows10" + Technologies = "mdm,microsoftSense" + TemplateReference = @{ + TemplateId = '0385b795-0f2f-44ac-8602-9f65bf6adede_1' + } } } + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicySetting -MockWith { + return @( + @{ + Id = 0 + SettingDefinitions = @( + @{ + Id = 'device_vendor_msft_windowsadvancedthreatprotection_onboarding' + Name = 'Onboarding' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingDefinition' + valueDefinition = @{ + isSecret = $true + } + } + } + @{ + Id = 'device_vendor_msft_windowsadvancedthreatprotection_configurationtype' + Name = 'ClientConfigurationPackageType' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + } + } + ) + SettingInstance = @{ + SettingDefinitionId = 'device_vendor_msft_windowsadvancedthreatprotection_configurationtype' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = '23ab0ea3-1b12-429a-8ed0-7390cf699160' + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + choiceSettingValue = @{ + children = @( + @{ + settingDefinitionId = 'device_vendor_msft_windowsadvancedthreatprotection_onboarding' + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance' + simpleSettingValue = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSecretSettingValue' + value = '84db67dd-caf8-4f86-bf00-b8897972d51f' + valueState = 'encryptedValueToken' + } + } + ) + value = 'device_vendor_msft_windowsadvancedthreatprotection_configurationtype_onboard' + } + value = "TEST" + } + } + } + @{ + Id = 1 + SettingDefinitions = @( + @{ + Id = 'device_vendor_msft_windowsadvancedthreatprotection_configuration_samplesharing' + Name = 'SampleSharing' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + } + } + ) + SettingInstance = @{ + SettingDefinitionId = 'device_vendor_msft_windowsadvancedthreatprotection_configuration_samplesharing' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = '6998c81e-2814-4f5e-b492-a6159128a97b' + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + choiceSettingValue = @{ + children = @() + value = "device_vendor_msft_windowsadvancedthreatprotection_configuration_samplesharing_0" + } + } + } + } + ) + } + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicyAssignment -MockWith { return @(@{ Id = '12345-12345-12345-12345-12345' @@ -69,18 +158,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } Mock -CommandName Update-DeviceConfigurationPolicyAssignment -MockWith { } - Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicyTemplateSettingTemplate -MockWith { - return @{ - Id = '12345-12345-12345-12345-12345' - SettingInstanceTemplate = @{ - settingDefinitionId = 'device_vendor_msft_windowsadvancedthreatprotection_configuration_samplesharing' - settingInstanceTemplateId = '6998c81e-2814-4f5e-b492-a6159128a97b' - AdditionalProperties = @{ - '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' - } - } - } - } # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { @@ -105,6 +182,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { DisplayName = 'My Test' Ensure = 'Present' Identity = '619bd4a4-3b3b-4441-bd6f-3f4c0c444870' + ConfigurationBlob = "FakeValue" + ConfigurationType = "onboard" sampleSharing = "0" } @@ -141,39 +220,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { DisplayName = 'My Test' Ensure = 'Present' Identity = '619bd4a4-3b3b-4441-bd6f-3f4c0c444870' - sampleSharing = "0" - } - - Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicy -MockWith { - return @{ - Id = '619bd4a4-3b3b-4441-bd6f-3f4c0c444870' - Description = 'My Test Description' - Name = 'My Test' - } - } - - Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicySetting -MockWith { - return @{ - Id = 0 - SettingDefinitions = $null - SettingInstance = @{ - SettingDefinitionId = 'device_vendor_msft_windowsadvancedthreatprotection_configuration_samplesharing' - SettingInstanceTemplateReference = @{ - SettingInstanceTemplateId = '6998c81e-2814-4f5e-b492-a6159128a97b' - } - AdditionalProperties = @{ - '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' - choiceSettingValue = @{ - children = @() - value = "device_vendor_msft_windowsadvancedthreatprotection_configuration_samplesharing_1" - } - } - - } - AdditionalProperties = $null - } - } - Mock -CommandName Update-DeviceManagementConfigurationPolicy -MockWith { + ConfigurationBlob = "FakeValue" + ConfigurationType = "onboard" + sampleSharing = "1" # Drift } } @@ -187,7 +236,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should update the instance from the Set method' { Set-TargetResource @testParams - Should -Invoke -CommandName Update-DeviceManagementConfigurationPolicy -Exactly 1 + Should -Invoke -CommandName Update-IntuneDeviceConfigurationPolicy -Exactly 1 } } @@ -206,32 +255,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { DeviceAndAppManagementAssignmentFilterType = 'none' } -ClientOnly) ) - } - - Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicy -MockWith { - return @{ - Id = '619bd4a4-3b3b-4441-bd6f-3f4c0c444870' - Description = 'My Test Description' - Name = 'My Test' - Settings = @{ - Id = 0 - SettingDefinitions = $null - SettingInstance = @{ - SettingDefinitionId = 'device_vendor_msft_windowsadvancedthreatprotection_configuration_samplesharing' - SettingInstanceTemplateReference = @{ - SettingInstanceTemplateId = '6998c81e-2814-4f5e-b492-a6159128a97b' - } - AdditionalProperties = @{ - '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' - choiceSettingValue = @{ - children = @() - value = "device_vendor_msft_windowsadvancedthreatprotection_configuration_samplesharing_0" - } - } - } - AdditionalProperties = $null - } - } + ConfigurationBlob = "FakeValue" + ConfigurationType = "onboard" + sampleSharing = "0" } } @@ -254,35 +280,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { DisplayName = 'My Test' Ensure = 'Absent' Identity = '619bd4a4-3b3b-4441-bd6f-3f4c0c444870' - } - - Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicy -MockWith { - return @{ - Id = '619bd4a4-3b3b-4441-bd6f-3f4c0c444870' - Description = 'My Test Description' - Name = 'My Test' - } - } - - Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicySetting -MockWith { - return @{ - Id = 0 - SettingDefinitions = $null - SettingInstance = @{ - SettingDefinitionId = 'device_vendor_msft_windowsadvancedthreatprotection_configuration_samplesharing' - SettingInstanceTemplateReference = @{ - SettingInstanceTemplateId = '6998c81e-2814-4f5e-b492-a6159128a97b' - } - AdditionalProperties = @{ - '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' - choiceSettingValue = @{ - children = @() - value = "device_vendor_msft_windowsadvancedthreatprotection_configuration_samplesharing_0" - } - } - } - AdditionalProperties = $null - } + ConfigurationBlob = "FakeValue" + ConfigurationType = "onboard" + sampleSharing = "1" } } @@ -307,38 +307,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $testParams = @{ Credential = $Credential } - - Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicy -MockWith { - return @{ - Id = '619bd4a4-3b3b-4441-bd6f-3f4c0c444870' - Description = 'My Test Description' - Name = 'My Test' - TemplateReference = @{ - TemplateId = '0385b795-0f2f-44ac-8602-9f65bf6adede_1' - } - } - } - - Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicySetting -MockWith { - return @{ - Id = 0 - SettingDefinitions = $null - SettingInstance = @{ - SettingDefinitionId = 'device_vendor_msft_windowsadvancedthreatprotection_configuration_samplesharing' - SettingInstanceTemplateReference = @{ - SettingInstanceTemplateId = '6998c81e-2814-4f5e-b492-a6159128a97b' - } - AdditionalProperties = @{ - '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' - choiceSettingValue = @{ - children = @() - value = "device_vendor_msft_windowsadvancedthreatprotection_configuration_samplesharing_0" - } - } - } - AdditionalProperties = $null - } - } } It 'Should Reverse Engineer resource from the Export method' { From 3c57bf8da46a821cd1bb3278fa1e6b34e0a4e919 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 4 Oct 2024 13:14:45 +0000 Subject: [PATCH 041/252] Updated Resources and Cmdlet documentation pages --- .../azure-ad/AADAuthenticationRequirement.md | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 docs/docs/resources/azure-ad/AADAuthenticationRequirement.md diff --git a/docs/docs/resources/azure-ad/AADAuthenticationRequirement.md b/docs/docs/resources/azure-ad/AADAuthenticationRequirement.md new file mode 100644 index 0000000000..92c8880213 --- /dev/null +++ b/docs/docs/resources/azure-ad/AADAuthenticationRequirement.md @@ -0,0 +1,86 @@ +# AADAuthenticationRequirement + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **PerUserMfaState** | Write | String | The state of the MFA enablement for the user. Possible values are: enabled, disabled. | `enabled`, `disabled` | +| **UserPrincipalName** | Key | String | The unique identifier for an entity. Read-only. | | +| **Credential** | Write | PSCredential | Credentials of the Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **ApplicationSecret** | Write | PSCredential | Secret of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Azure AD Authentication Requirement Resource to set up Per-User MFA settings + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - UserAuthenticationMethod.Read.All + +- **Update** + + - UserAuthenticationMethod.ReadWrite.All + +#### Application permissions + +- **Read** + + - UserAuthenticationMethod.Read.All + +- **Update** + + - UserAuthenticationMethod.ReadWrite.All + +## Examples + +### Example 1 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + Node localhost + { + AADAuthenticationRequirement "AADAuthenticationRequirement-TestMailbox109@xtasdftestorg.onmicrosoft.com" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + PerUserMfaState = "disabled"; + UserPrincipalName = "TestMailbox109@$OrganizationName"; + } + } +} +``` + From 9709cba6348c79022453f8bc3276525eed8ae902 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 4 Oct 2024 10:02:02 -0400 Subject: [PATCH 042/252] Initial Release --- .../MSFT_AADDeviceRegistrationPolicy.psm1 | 24 +++++++++++++++++-- ...SFT_AADDeviceRegistrationPolicy.schema.mof | 1 + 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/MSFT_AADDeviceRegistrationPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/MSFT_AADDeviceRegistrationPolicy.psm1 index 807616920f..c6d32acefa 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/MSFT_AADDeviceRegistrationPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/MSFT_AADDeviceRegistrationPolicy.psm1 @@ -9,6 +9,10 @@ function Get-TargetResource [System.String] $IsSingleInstance, + [Parameter()] + [Boolean] + $AzureADJoinIsAdminConfigurable, + [Parameter()] [ValidateSet('All', 'Selected', 'None')] [System.String] @@ -202,6 +206,10 @@ function Set-TargetResource [System.String] $IsSingleInstance, + [Parameter()] + [Boolean] + $AzureADJoinIsAdminConfigurable, + [Parameter()] [ValidateSet('All', 'Selected', 'None')] [System.String] @@ -343,8 +351,9 @@ function Set-TargetResource userDeviceQuota = $UserDeviceQuota multiFactorAuthConfiguration = $MultiFactorAuthConfigurationValue azureADJoin = @{ + isAdminConfigurable =$AzureADJoinIsAdminConfigurable allowedToJoin = @{ - '@odata.type' = $AzureADAllowedToJoin + '@odata.type' = $azureADRegistrationAllowedToRegister users = $AzureADAllowedToJoinUsers groups = $AzureADAllowedToJoinGroups } @@ -357,11 +366,18 @@ function Set-TargetResource } } } - localAdminPasswordSettings = @{ + localAdminPassword = @{ isEnabled = $LocalAdminPasswordIsEnabled } + azureADRegistration = @{ + isAdminConfigurable = $false + allowedToRegister = @{ + '@odata.type' = "#microsoft.graph.allDeviceRegistrationMembership" + } + } } $uri = $Global:MSCloudLoginConnectionProfile.MicrosoftGraph.ResourceUrl + 'beta/policies/deviceRegistrationPolicy' + Write-Verbose -Message "Updating Device Registration Policy with payload:`r`n$(ConvertTo-Json $updateParameters -Depth 10)" Invoke-MgGraphRequest -Method PUT -Uri $uri -Body $updateParameters } @@ -376,6 +392,10 @@ function Test-TargetResource [System.String] $IsSingleInstance, + [Parameter()] + [Boolean] + $AzureADJoinIsAdminConfigurable, + [Parameter()] [ValidateSet('All', 'Selected', 'None')] [System.String] diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/MSFT_AADDeviceRegistrationPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/MSFT_AADDeviceRegistrationPolicy.schema.mof index 944ef367d8..5096bb720f 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/MSFT_AADDeviceRegistrationPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/MSFT_AADDeviceRegistrationPolicy.schema.mof @@ -2,6 +2,7 @@ class MSFT_AADDeviceRegistrationPolicy : OMI_BaseResource { [Key, Description("Only valid value is 'Yes'."), ValueMap{"Yes"}, Values{"Yes"}] String IsSingleInstance; + [Write, Description("Determines whether or not administrators can configure Azure AD Join.")] Boolean AzureADJoinIsAdminConfigurable; [Write, Description("Specifies the maximum number of devices that a user can have within your organization before blocking new device registrations. The default value is set to 50. If this property isn't specified during the policy update operation, it's automatically reset to 0 to indicate that users aren't allowed to join any devices.")] UInt32 UserDeviceQuota; [Write, Description("Scope that a device registration policy applies to."), ValueMap{"All", "Selected", "None"}, Values{"All", "Selected", "None"}] String AzureADAllowedToJoin; [Write, Description("List of users that this policy applies to.")] String AzureADAllowedToJoinUsers[]; From b3d8fae22b9d38f2f6c5231ca045320b0ef48d2d Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 4 Oct 2024 10:02:09 -0400 Subject: [PATCH 043/252] Fixes --- CHANGELOG.md | 2 + .../settings.json | 8 +- .../AADDeviceRegistrationPolicy/2-Update.ps1 | 39 ++-- ...5DSC.AADDeviceRegistrationPolicy.Tests.ps1 | 178 +++++++++++++----- Tests/Unit/Stubs/Microsoft365.psm1 | 6 + 5 files changed, 165 insertions(+), 68 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f91122ea29..11f72f2631 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ # UNRELEASED +* AADDeviceRegistrationPolicy + * Initial release. * AADEntitlementManagementSettings * Added support for ApplicationSecret * M365DSCDRGUtil diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/settings.json index 6cf3fe9eed..3324b5f4e0 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDeviceRegistrationPolicy/settings.json @@ -1,12 +1,12 @@ { - "resourceName": "AADAttributeSet", - "description": "Represents a group of related custom security attribute definitions.", + "resourceName": "AADDeviceRegistrationPolicy", + "description": "Represents the policy scope that controls quota restrictions, additional authentication, and authorization policies to register device identities to your organization.", "roles": { "read": [ - "Attribute Definition Reader" + "Security Reader" ], "update": [ - "Attribute Definition Administrator" + "Authentication Policy Administrator" ] }, "permissions": { diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADDeviceRegistrationPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADDeviceRegistrationPolicy/2-Update.ps1 index 52b8df2775..255c5e3155 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/AADDeviceRegistrationPolicy/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/AADDeviceRegistrationPolicy/2-Update.ps1 @@ -5,24 +5,39 @@ It is not meant to use as a production baseline. Configuration Example { - param - ( - [Parameter(Mandatory = $true)] - [PSCredential] - $credsCredential - ) + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + [Parameter()] + [System.String] + $CertificateThumbprint + ) Import-DscResource -ModuleName Microsoft365DSC node localhost { - AADAttributeSet "AADAttributeSetTest" + AADDeviceRegistrationPolicy "MyDeviceRegistrationPolicy" { - Credential = $credsCredential; - Description = "Attribute set with 420 attributes"; - Ensure = "Present"; - Id = "TestAttributeSet"; - MaxAttributesPerSet = 300; # Updated Property + ApplicationId = $ApplicationId; + AzureADAllowedToJoin = "Selected"; + AzureADAllowedToJoinGroups = @(); + AzureADAllowedToJoinUsers = @("AlexW@M365x73318397.OnMicrosoft.com"); + AzureAdJoinLocalAdminsRegisteringGroups = @(); + AzureAdJoinLocalAdminsRegisteringMode = "Selected"; + AzureAdJoinLocalAdminsRegisteringUsers = @("AllanD@M365x73318397.OnMicrosoft.com"); + CertificateThumbprint = $CertificateThumbprint; + IsSingleInstance = "Yes"; + LocalAdminPasswordIsEnabled = $False; + LocalAdminsEnableGlobalAdmins = $True; + MultiFactorAuthConfiguration = $False; + TenantId = $TenantId; + UserDeviceQuota = 50; } } } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADDeviceRegistrationPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADDeviceRegistrationPolicy.Tests.ps1 index 39e93e112f..5a438157f0 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADDeviceRegistrationPolicy.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADDeviceRegistrationPolicy.Tests.ps1 @@ -15,7 +15,7 @@ Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` -Resolve) $Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` - -DscResource "AADAttributeSet" -GenericStubModule $GenericStubPath + -DscResource "AADDeviceRegistrationPolicy" -GenericStubModule $GenericStubPath Describe -Name $Global:DscHelper.DescribeHeader -Fixture { InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope @@ -33,6 +33,17 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Remove-MgBetaDirectoryAttributeSet -MockWith { } + Mock -CommandName Get-MgUser -MockWith { + return @{ + id = '12345-12345-12345-12345-12345' + UserPrincipalName = "john.smith@contoso.com" + } + } + + Mock -CommandName Invoke-MgGraphRequest -MockWith { + return $null + } + Mock -CommandName New-M365DSCConnection -MockWith { return "Credentials" } @@ -43,45 +54,57 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $Script:exportedInstances =$null $Script:ExportMode = $false } - # Test contexts - Context -Name "The instance should exist but it DOES NOT" -Fixture { - BeforeAll { - $testParams = @{ - Description = "This is my super context test"; - MaxAttributesPerSet = 420; - Ensure = "Present"; - Id = "c3"; - Credential = $Credential; - } - - Mock -CommandName Get-MgBetaDirectoryAttributeSet -MockWith { - return $null - } - } - It 'Should return Values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' - } - It 'Should return false from the Test method' { - Test-TargetResource @testParams | Should -Be $false - } - } Context -Name "The instance exists and values are already in the desired state" -Fixture { BeforeAll { $testParams = @{ - Description = "This is my super context test"; - MaxAttributesPerSet = 420; - Ensure = "Present"; - Id = "c3"; - Credential = $Credential; + AzureADAllowedToJoin = "None"; + AzureADAllowedToJoinGroups = @(); + AzureADAllowedToJoinUsers = @(); + AzureAdJoinLocalAdminsRegisteringGroups = @(); + AzureAdJoinLocalAdminsRegisteringMode = "Selected"; + AzureAdJoinLocalAdminsRegisteringUsers = @("john.smith@contoso.com"); + IsSingleInstance = "Yes"; + LocalAdminPasswordIsEnabled = $False; + LocalAdminsEnableGlobalAdmins = $True; + MultiFactorAuthConfiguration = $False; + UserDeviceQuota = 50; + Credential = $Credential; } - Mock -CommandName Get-MgBetaDirectoryAttributeSet -MockWith { + Mock -CommandName Get-MgBetaPolicyDeviceRegistrationPolicy -MockWith { return @{ - Description = "This is my super context test"; - MaxAttributesPerSet = 420; - Id = "c3"; + AzureAdJoin = @{ + IsAdminConfigurable = $true + AllowedToJoin = @{ + "@odata.type" = "#microsoft.graph.allDeviceRegistrationMembership" + } + LocalAdmins = @{ + EnableGlobalAdmins = $true + RegisteringUsers = @{ + AdditionalProperties = @{ + "@odata.type" = "#microsoft.graph.enumeratedDeviceRegistrationMembership" + users = @('12345-12345-12345-12345-12345') + groups = @() + } + } + } + } + AzureADRegistration = @{ + IsAdminConfigurable = $false + AllowedToRegister = @{ + "@odata.type" = "#microsoft.graph.allDeviceRegistrationMembership" + } + } + Description = "Tenant-wide policy that manages initial provisioning controls using quota restrictions, additional authentication and authorization checks" + DisplayName = "Device Registration Policy" + Id = "deviceRegistrationPolicy" + LocalAdminPassword = @{ + IsEnabled = $false + } + MultiFactorAuthConfiguration = "notRequired" + UserDeviceQuota = 50 } } } @@ -94,35 +117,61 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance exists and values are NOT in the desired state" -Fixture { BeforeAll { $testParams = @{ - Description = "This is my super context test"; - MaxAttributesPerSet = 420; - Ensure = "Present"; - Id = "c3"; - Credential = $Credential; + AzureADAllowedToJoin = "Selected"; + AzureADAllowedToJoinGroups = @(); + AzureADAllowedToJoinUsers = @("john.smith@contoso.com"); + AzureAdJoinLocalAdminsRegisteringGroups = @(); + AzureAdJoinLocalAdminsRegisteringMode = "Selected"; + AzureAdJoinLocalAdminsRegisteringUsers = @("john.smith@contoso.com"); + IsSingleInstance = "Yes"; + LocalAdminPasswordIsEnabled = $False; + LocalAdminsEnableGlobalAdmins = $False; # drift + MultiFactorAuthConfiguration = $False; + UserDeviceQuota = 50; + Credential = $Credential; } - Mock -CommandName Get-MgBetaDirectoryAttributeSet -MockWith { + Mock -CommandName Get-MgBetaPolicyDeviceRegistrationPolicy -MockWith { return @{ - Description = "This is my super context test"; - MaxAttributesPerSet = 431; #drift - Ensure = "Present"; - Id = "c3"; - Credential = $Credential; + AzureAdJoin = @{ + IsAdminConfigurable = $true + AllowedToJoin = @{ + "@odata.type" = "#microsoft.graph.allDeviceRegistrationMembership" + } + LocalAdmins = @{ + EnableGlobalAdmins = $true + RegisteringUsers = @{ + users = @() + groups = @() + "@odata.type" = "#microsoft.graph.enumeratedDeviceRegistrationMembership" + } + } + } + AzureADRegistration = @{ + IsAdminConfigurable = $false + AllowedToRegister = @{ + "@odata.type" = "#microsoft.graph.allDeviceRegistrationMembership" + } + } + Description = "Tenant-wide policy that manages initial provisioning controls using quota restrictions, additional authentication and authorization checks" + DisplayName = "Device Registration Policy" + Id = "deviceRegistrationPolicy" + LocalAdminPassword = @{ + IsEnabled = $false + } + MultiFactorAuthConfiguration = "notRequired" + UserDeviceQuota = 50 } } } - It 'Should return Values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Present' - } - It 'Should return false from the Test method' { Test-TargetResource @testParams | Should -Be $false } It 'Should call the Set method' { Set-TargetResource @testParams - Should -Invoke -CommandName Update-MgBetaDirectoryAttributeSet -Exactly 1 + Should -Invoke -CommandName Invoke-MgGraphRequest -Exactly 1 } } @@ -134,11 +183,36 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - Mock -CommandName Get-MgBetaDirectoryAttributeSet -MockWith { + Mock -CommandName Get-MgBetaPolicyDeviceRegistrationPolicy -MockWith { return @{ - Description = "This is my super context test"; - MaxAttributesPerSet = 420; - Id = "c3"; + AzureAdJoin = @{ + IsAdminConfigurable = $true + AllowedToJoin = @{ + "@odata.type" = "#microsoft.graph.allDeviceRegistrationMembership" + } + LocalAdmins = @{ + EnableGlobalAdmins = $true + RegisteringUsers = @{ + users = @() + groups = @() + "@odata.type" = "#microsoft.graph.enumeratedDeviceRegistrationMembership" + } + } + } + AzureADRegistration = @{ + IsAdminConfigurable = $false + AllowedToRegister = @{ + "@odata.type" = "#microsoft.graph.allDeviceRegistrationMembership" + } + } + Description = "Tenant-wide policy that manages initial provisioning controls using quota restrictions, additional authentication and authorization checks" + DisplayName = "Device Registration Policy" + Id = "deviceRegistrationPolicy" + LocalAdminPassword = @{ + IsEnabled = $false + } + MultiFactorAuthConfiguration = "notRequired" + UserDeviceQuota = 50 } } } diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index af684909f3..82c6b69ce8 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -18,6 +18,12 @@ function Invoke-AzRest } #endregion +function Get-MgBetaPolicyDeviceRegistrationPolicy +{ + [CmdletBinding] + param() +} + #region Microsoft.Graph.Beta.Applications function Get-MgBetaApplication { From 065e6f15527e5362b90b15f47a17268cec486258 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 4 Oct 2024 10:24:11 -0400 Subject: [PATCH 044/252] Update Graph.PermissionList.txt --- Tests/QA/Graph.PermissionList.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/QA/Graph.PermissionList.txt b/Tests/QA/Graph.PermissionList.txt index 3acae21c4a..bb13a7818d 100644 --- a/Tests/QA/Graph.PermissionList.txt +++ b/Tests/QA/Graph.PermissionList.txt @@ -1 +1 @@ -AccessReview.Read.All,AccessReview.ReadWrite.All,AccessReview.ReadWrite.Membership,AdministrativeUnit.Read.All,AdministrativeUnit.ReadWrite.All,Agreement.Read.All,AppCatalog.ReadWrite.All,AppCertTrustConfiguration.Read.All,AppCertTrustConfiguration.ReadWrite.All,Application.Read.All,Application.ReadWrite.All,Application.ReadWrite.OwnedBy,Application-RemoteDesktopConfig.ReadWrite.All,AppRoleAssignment.ReadWrite.All,BrowserSiteLists.Read.All,BrowserSiteLists.ReadWrite.All,Calendars.Read,Calendars.ReadBasic,Calendars.ReadWrite,Channel.Delete.All,ChannelMember.ReadWrite.All,ChannelSettings.Read.All,ChannelSettings.ReadWrite.All,CloudPC.Read.All,CloudPC.ReadWrite.All,CrossTenantUserProfileSharing.Read.All,CrossTenantUserProfileSharing.ReadWrite.All,CustomSecAttributeDefinition.Read.All,CustomSecAttributeDefinition.ReadWrite.All,CustomSecAttributeProvisioning.Read.All,CustomSecAttributeProvisioning.ReadWrite.All,DelegatedPermissionGrant.ReadWrite.All,Device.Read.All,Device.ReadWrite.All,DeviceManagement.Scripts.Read.All,DeviceManagement.Scripts.ReadWrite.All,DeviceManagementApps.Read.All,DeviceManagementApps.ReadWrite.All,DeviceManagementConfiguration.Read.All,DeviceManagementConfiguration.ReadWrite.All,DeviceManagementManagedDevices.Read.All,DeviceManagementManagedDevices.ReadWrite.All,DeviceManagementRBAC.Read.All,DeviceManagementRBAC.ReadWrite.All,DeviceManagementServiceConfig.Read.All,DeviceManagementServiceConfig.ReadWrite.All,Directory.Read.All,Directory.ReadWrite.All,DirectoryRecommendations.Read.All,DirectoryRecommendations.ReadWrite.All,Domain.Read.All,Domain.ReadWrite.All,EntitlementManagement.Read.All,EntitlementManagement.ReadWrite.All,Group.Create,Group.Read.All,Group.ReadWrite.All,Group-Conversation.Read.All,Group-Conversation.ReadWrite.All,GroupMember.Read.All,GroupMember.ReadWrite.All,IdentityProvider.Read.All,IdentityProvider.ReadWrite.All,Organization.Read.All,Organization.ReadWrite.All,OrganizationalBranding.Read.All,OrganizationalBranding.ReadWrite.All,OrgContact.Read.All,OrgSettings-AppsAndServices.Read.All,OrgSettings-DynamicsVoice.Read.All,OrgSettings-Forms.Read.All,OrgSettings-Microsoft365Install.Read.All,OrgSettings-Todo.Read.All,PeopleSettings.Read.All,PeopleSettings.ReadWrite.All,Policy.Read.All,Policy.Read.ApplicationConfiguration,Policy.Read.ConditionalAccess,Policy.ReadWrite.ApplicationConfiguration,Policy.ReadWrite.AuthenticationMethod,Policy.ReadWrite.Authorization,Policy.ReadWrite.ConditionalAccess,ProfilePhoto.Read.All,ProfilePhoto.ReadWrite.All,ReportSettings.Read.All,RoleEligibilitySchedule.Read.Directory,RoleManagement.Read.All,RoleManagement.Read.CloudPC,RoleManagement.Read.Directory,RoleManagement.Read.Exchange,RoleManagement.ReadWrite.CloudPC,RoleManagement.ReadWrite.Directory,RoleManagement.ReadWrite.Exchange,RoleManagementPolicy.Read.Directory,SharePointTenantSettings.Read.All,Synchronization.Read.All,Synchronization.ReadWrite.All,Tasks.Read.All,TeamSettings.ReadWrite.All,User.Read.All,User.ReadWrite.All,EntitlementManagement.Read.All,ExternalConnection.Read.All,ExternalConnection.ReadWrite.All, +AccessReview.Read.All,AccessReview.ReadWrite.All,AccessReview.ReadWrite.Membership,AdministrativeUnit.Read.All,AdministrativeUnit.ReadWrite.All,Agreement.Read.All,AppCatalog.ReadWrite.All,AppCertTrustConfiguration.Read.All,AppCertTrustConfiguration.ReadWrite.All,Application.Read.All,Application.ReadWrite.All,Application.ReadWrite.OwnedBy,Application-RemoteDesktopConfig.ReadWrite.All,AppRoleAssignment.ReadWrite.All,BrowserSiteLists.Read.All,BrowserSiteLists.ReadWrite.All,Calendars.Read,Calendars.ReadBasic,Calendars.ReadWrite,Channel.Delete.All,ChannelMember.ReadWrite.All,ChannelSettings.Read.All,ChannelSettings.ReadWrite.All,CloudPC.Read.All,CloudPC.ReadWrite.All,CrossTenantUserProfileSharing.Read.All,CrossTenantUserProfileSharing.ReadWrite.All,CustomSecAttributeDefinition.Read.All,CustomSecAttributeDefinition.ReadWrite.All,CustomSecAttributeProvisioning.Read.All,CustomSecAttributeProvisioning.ReadWrite.All,DelegatedPermissionGrant.ReadWrite.All,Device.Read.All,Device.ReadWrite.All,DeviceManagement.Scripts.Read.All,DeviceManagement.Scripts.ReadWrite.All,DeviceManagementApps.Read.All,DeviceManagementApps.ReadWrite.All,DeviceManagementConfiguration.Read.All,DeviceManagementConfiguration.ReadWrite.All,DeviceManagementManagedDevices.Read.All,DeviceManagementManagedDevices.ReadWrite.All,DeviceManagementRBAC.Read.All,DeviceManagementRBAC.ReadWrite.All,DeviceManagementServiceConfig.Read.All,DeviceManagementServiceConfig.ReadWrite.All,Directory.Read.All,Directory.ReadWrite.All,DirectoryRecommendations.Read.All,DirectoryRecommendations.ReadWrite.All,Domain.Read.All,Domain.ReadWrite.All,EntitlementManagement.Read.All,EntitlementManagement.ReadWrite.All,Group.Create,Group.Read.All,Group.ReadWrite.All,Group-Conversation.Read.All,Group-Conversation.ReadWrite.All,GroupMember.Read.All,GroupMember.ReadWrite.All,IdentityProvider.Read.All,IdentityProvider.ReadWrite.All,Organization.Read.All,Organization.ReadWrite.All,OrganizationalBranding.Read.All,OrganizationalBranding.ReadWrite.All,OrgContact.Read.All,OrgSettings-AppsAndServices.Read.All,OrgSettings-DynamicsVoice.Read.All,OrgSettings-Forms.Read.All,OrgSettings-Microsoft365Install.Read.All,OrgSettings-Todo.Read.All,PeopleSettings.Read.All,PeopleSettings.ReadWrite.All,Policy.Read.All,Policy.Read.ApplicationConfiguration,Policy.Read.ConditionalAccess,Policy.ReadWrite.ApplicationConfiguration,Policy.ReadWrite.AuthenticationMethod,Policy.ReadWrite.Authorization,Policy.ReadWrite.ConditionalAccess,ProfilePhoto.Read.All,ProfilePhoto.ReadWrite.All,ReportSettings.Read.All,RoleEligibilitySchedule.Read.Directory,RoleManagement.Read.All,RoleManagement.Read.CloudPC,RoleManagement.Read.Directory,RoleManagement.Read.Exchange,RoleManagement.ReadWrite.CloudPC,RoleManagement.ReadWrite.Directory,RoleManagement.ReadWrite.Exchange,RoleManagementPolicy.Read.Directory,SharePointTenantSettings.Read.All,Synchronization.Read.All,Synchronization.ReadWrite.All,Tasks.Read.All,TeamSettings.ReadWrite.All,User.Read.All,User.ReadWrite.All,EntitlementManagement.Read.All,ExternalConnection.Read.All,ExternalConnection.ReadWrite.All,UserAuthenticationMethod.Read.All,Policy.Read.DeviceConfiguration, From 17c7d1f7a35967846c24600aad466e1bd8980be3 Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Fri, 4 Oct 2024 20:10:19 +0530 Subject: [PATCH 045/252] minor --- .../EXOMailboxFolderPermission/1-Create.ps1 | 10 ++++++---- .../EXOMailboxFolderPermission/2-Update.ps1 | 10 ++++++---- .../Resources/EXOMailboxIRMAccess/1-Create.ps1 | 12 +++++++----- .../{2-Update.ps1 => 2-Remove.ps1} | 11 ++++++++++- .../Resources/EXOManagementScope/1-Create.ps1 | 4 +++- .../Resources/EXOManagementScope/2-Update.ps1 | 4 +++- .../Resources/EXOManagementScope/3-Remove.ps1 | 4 +++- .../Resources/EXOMigrationEndpoint/1-Create.ps1 | 4 +++- .../Resources/EXOMigrationEndpoint/2-Update.ps1 | 5 +++-- .../Resources/EXOMigrationEndpoint/3-Remove.ps1 | 4 +++- 10 files changed, 47 insertions(+), 21 deletions(-) rename Modules/Microsoft365DSC/Examples/Resources/EXOMailboxIRMAccess/{2-Update.ps1 => 2-Remove.ps1} (50%) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxFolderPermission/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxFolderPermission/1-Create.ps1 index 512a22ca2a..30d854debf 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxFolderPermission/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxFolderPermission/1-Create.ps1 @@ -25,10 +25,12 @@ Configuration Example { EXOMailboxFolderPermission "EXOMailboxFolderPermission-admin:\Calendar" { - Credential = $Credscredential; - Ensure = "Present"; - Identity = "amdin:\Calendar"; - UserPermissions = @(MSFT_EXOMailboxFolderUserPermission { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Present"; + Identity = "amdin:\Calendar"; + UserPermissions = @(MSFT_EXOMailboxFolderUserPermission { User = 'Default' AccessRights = 'AvailabilityOnly' } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxFolderPermission/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxFolderPermission/2-Update.ps1 index 22c39789c9..53f644e60e 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxFolderPermission/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxFolderPermission/2-Update.ps1 @@ -23,10 +23,12 @@ Configuration Example { EXOMailboxFolderPermission "EXOMailboxFolderPermission-admin:\Calendar" { - Credential = $Credscredential; - Ensure = "Present"; - Identity = "admin:\Calendar"; - UserPermissions = @(MSFT_EXOMailboxFolderUserPermission { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Present"; + Identity = "admin:\Calendar"; + UserPermissions = @(MSFT_EXOMailboxFolderUserPermission { User = 'Default' AccessRights = 'AvailabilityOnly' } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxIRMAccess/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxIRMAccess/1-Create.ps1 index f47d2d2105..224ba6554e 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxIRMAccess/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxIRMAccess/1-Create.ps1 @@ -23,11 +23,13 @@ Configuration Example { EXOMailboxIRMAccess "EXOMailboxIRMAccess-qwe@testorg.onmicrosoft.com" { - AccessLevel = "Block"; - Credential = $Credscredential; - Ensure = "Present"; - Identity = "qwe@$OrganizationName"; - User = "admin@$OrganizationName"; + AccessLevel = "Block"; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Present"; + Identity = "qwe@$OrganizationName"; + User = "admin@$OrganizationName"; } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxIRMAccess/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxIRMAccess/2-Remove.ps1 similarity index 50% rename from Modules/Microsoft365DSC/Examples/Resources/EXOMailboxIRMAccess/2-Update.ps1 rename to Modules/Microsoft365DSC/Examples/Resources/EXOMailboxIRMAccess/2-Remove.ps1 index b516274848..e57be7daf4 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxIRMAccess/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxIRMAccess/2-Remove.ps1 @@ -21,6 +21,15 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + EXOMailboxIRMAccess "EXOMailboxIRMAccess-qwe@testorg.onmicrosoft.com" + { + AccessLevel = "Block"; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Absent"; + Identity = "qwe@$OrganizationName"; + User = "admin@$OrganizationName"; + } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/1-Create.ps1 index ba630d844a..e583a1d42c 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/1-Create.ps1 @@ -25,7 +25,9 @@ Configuration Example { EXOManagementScope "EXOManagementScope-Test New DGs" { - Credential = $Credscredential; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint Ensure = "Present"; Exclusive = $False; Identity = "Test New DGs"; diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/2-Update.ps1 index 64528717e8..8ceabe1be9 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/2-Update.ps1 @@ -23,7 +23,9 @@ Configuration Example { EXOManagementScope "EXOManagementScope-Test New DGs" { - Credential = $Credscredential; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint Ensure = "Present"; Exclusive = $False; Identity = "Test New DGs"; diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/3-Remove.ps1 index 3524dc103d..1b2e95e5af 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/3-Remove.ps1 @@ -23,7 +23,9 @@ Configuration Example { EXOManagementScope "EXOManagementScope-Test New DGs" { - Credential = $Credscredential; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint Ensure = "Absent"; Exclusive = $False; Identity = "Test New DGs"; diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/1-Create.ps1 index e96d8c8010..58211df214 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/1-Create.ps1 @@ -25,7 +25,9 @@ Configuration Example { AcceptUntrustedCertificates = $True; Authentication = "Basic"; - Credential = $Credscredential; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint EndpointType = "IMAP"; Ensure = "Present"; Identity = "testIMAP"; diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/2-Update.ps1 index 4ec28ef8fc..85ec1ba902 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/2-Update.ps1 @@ -25,7 +25,9 @@ Configuration Example { AcceptUntrustedCertificates = $True; Authentication = "Basic"; - Credential = $Credscredential; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint EndpointType = "IMAP"; Ensure = "Present"; Identity = "testIMAP"; @@ -37,6 +39,5 @@ Configuration Example # value for security updated from Tls to None Security = "None"; } - } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/3-Remove.ps1 index 9ac7745bec..e1e47e2730 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMigrationEndpoint/3-Remove.ps1 @@ -25,7 +25,9 @@ Configuration Example { AcceptUntrustedCertificates = $True; Authentication = "Basic"; - Credential = $Credscredential; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint EndpointType = "IMAP"; Ensure = "Absent"; Identity = "testIMAP"; From 1e65b28c55ec3681f86d9919c535d7b6999c9927 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 4 Oct 2024 11:12:51 -0400 Subject: [PATCH 046/252] Update Microsoft365.psm1 --- Tests/Unit/Stubs/Microsoft365.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 82c6b69ce8..bbc1300dac 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -20,7 +20,7 @@ function Invoke-AzRest function Get-MgBetaPolicyDeviceRegistrationPolicy { - [CmdletBinding] + [CmdletBinding()] param() } From 717adca2f08f5e97d27c8c43f89f762082bb0351 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 4 Oct 2024 15:26:27 +0000 Subject: [PATCH 047/252] Updated Resources and Cmdlet documentation pages --- .../azure-ad/AADDeviceRegistrationPolicy.md | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 docs/docs/resources/azure-ad/AADDeviceRegistrationPolicy.md diff --git a/docs/docs/resources/azure-ad/AADDeviceRegistrationPolicy.md b/docs/docs/resources/azure-ad/AADDeviceRegistrationPolicy.md new file mode 100644 index 0000000000..9d62cc0431 --- /dev/null +++ b/docs/docs/resources/azure-ad/AADDeviceRegistrationPolicy.md @@ -0,0 +1,105 @@ +# AADDeviceRegistrationPolicy + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **IsSingleInstance** | Key | String | Only valid value is 'Yes'. | `Yes` | +| **AzureADJoinIsAdminConfigurable** | Write | Boolean | Determines whether or not administrators can configure Azure AD Join. | | +| **UserDeviceQuota** | Write | UInt32 | Specifies the maximum number of devices that a user can have within your organization before blocking new device registrations. The default value is set to 50. If this property isn't specified during the policy update operation, it's automatically reset to 0 to indicate that users aren't allowed to join any devices. | | +| **AzureADAllowedToJoin** | Write | String | Scope that a device registration policy applies to. | `All`, `Selected`, `None` | +| **AzureADAllowedToJoinUsers** | Write | StringArray[] | List of users that this policy applies to. | | +| **AzureADAllowedToJoinGroups** | Write | StringArray[] | List of groups that this policy applies to. | | +| **MultiFactorAuthConfiguration** | Write | Boolean | Specifies the authentication policy for a user to complete registration using Microsoft Entra join or Microsoft Entra registered within your organization. | | +| **LocalAdminsEnableGlobalAdmins** | Write | Boolean | Indicates whether global administrators are local administrators on all Microsoft Entra-joined devices. This setting only applies to future registrations. Default is true. | | +| **AzureAdJoinLocalAdminsRegisteringMode** | Write | String | Scope that a device registration policy applies to for local admins. | `All`, `Selected`, `None` | +| **AzureAdJoinLocalAdminsRegisteringGroups** | Write | StringArray[] | List of groups that this policy applies to. | | +| **AzureAdJoinLocalAdminsRegisteringUsers** | Write | StringArray[] | List of users that this policy applies to. | | +| **LocalAdminPasswordIsEnabled** | Write | Boolean | Specifies whether this policy scope is configurable by the admin. The default value is false. An admin can set it to true to enable Local Admin Password Solution (LAPS) within their organzation. | | +| **Credential** | Write | PSCredential | Credentials of the Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **ApplicationSecret** | Write | PSCredential | Secret of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Represents the policy scope that controls quota restrictions, additional authentication, and authorization policies to register device identities to your organization. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - Policy.Read.DeviceConfiguration + +- **Update** + + - Policy.ReadWrite.DeviceConfiguration + +## Examples + +### Example 1 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + AADDeviceRegistrationPolicy "MyDeviceRegistrationPolicy" + { + ApplicationId = $ApplicationId; + AzureADAllowedToJoin = "Selected"; + AzureADAllowedToJoinGroups = @(); + AzureADAllowedToJoinUsers = @("AlexW@M365x73318397.OnMicrosoft.com"); + AzureAdJoinLocalAdminsRegisteringGroups = @(); + AzureAdJoinLocalAdminsRegisteringMode = "Selected"; + AzureAdJoinLocalAdminsRegisteringUsers = @("AllanD@M365x73318397.OnMicrosoft.com"); + CertificateThumbprint = $CertificateThumbprint; + IsSingleInstance = "Yes"; + LocalAdminPasswordIsEnabled = $False; + LocalAdminsEnableGlobalAdmins = $True; + MultiFactorAuthConfiguration = $False; + TenantId = $TenantId; + UserDeviceQuota = 50; + } + } +} +``` + From e73e9f2a3d84dacd14a27129e50e942c227f7496 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 4 Oct 2024 15:26:51 +0000 Subject: [PATCH 048/252] Updated {Update} AAD Integration Tests --- .../M365DSCIntegration.AAD.Update.Tests.ps1 | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 index e28b8587c9..cbb9f05169 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 @@ -602,6 +602,23 @@ CertificateThumbprint = $CertificateThumbprint Ensure = "Present"; } + AADDeviceRegistrationPolicy 'MyDeviceRegistrationPolicy' + { + ApplicationId = $ApplicationId; + AzureADAllowedToJoin = "Selected"; + AzureADAllowedToJoinGroups = @(); + AzureADAllowedToJoinUsers = @("AlexW@M365x73318397.OnMicrosoft.com"); + AzureAdJoinLocalAdminsRegisteringGroups = @(); + AzureAdJoinLocalAdminsRegisteringMode = "Selected"; + AzureAdJoinLocalAdminsRegisteringUsers = @("AllanD@M365x73318397.OnMicrosoft.com"); + CertificateThumbprint = $CertificateThumbprint; + IsSingleInstance = "Yes"; + LocalAdminPasswordIsEnabled = $False; + LocalAdminsEnableGlobalAdmins = $True; + MultiFactorAuthConfiguration = $False; + TenantId = $TenantId; + UserDeviceQuota = 50; + } AADEntitlementManagementAccessPackage 'myAccessPackage' { AccessPackagesIncompatibleWith = @(); From 6bb79eb6b70cd49bddcc0aeb17632d9f0ddab268 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 4 Oct 2024 15:28:41 +0000 Subject: [PATCH 049/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 95916364b2..86844fd218 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -2844,6 +2844,106 @@ } ] }, + { + "ClassName": "MSFT_AADDeviceRegistrationPolicy", + "Parameters": [ + { + "CIMType": "String", + "Name": "IsSingleInstance", + "Option": "Key" + }, + { + "CIMType": "Boolean", + "Name": "AzureADJoinIsAdminConfigurable", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "UserDeviceQuota", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AzureADAllowedToJoin", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AzureADAllowedToJoinUsers", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AzureADAllowedToJoinGroups", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "MultiFactorAuthConfiguration", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "LocalAdminsEnableGlobalAdmins", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AzureAdJoinLocalAdminsRegisteringMode", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AzureAdJoinLocalAdminsRegisteringGroups", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AzureAdJoinLocalAdminsRegisteringUsers", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "LocalAdminPasswordIsEnabled", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "ApplicationSecret", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_AccessPackageResourceRoleScope", "Parameters": [ From 1b3d7aa4b740c10818b7306055f046439ed0ddd0 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 4 Oct 2024 13:10:09 -0400 Subject: [PATCH 050/252] Update MSFT_ADOPermissionGroupSettings.psm1 --- .../MSFT_ADOPermissionGroupSettings.psm1 | 62 +++++++++++++++---- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.psm1 index b53f586647..c7f5c005ec 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.psm1 @@ -195,22 +195,58 @@ function Set-TargetResource $info = Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri $descriptor = $info.value.descriptor - $body = @{ - value = @() + # Get all Namespaces from the Allow and Deny + $namespacesToUpdate = @() + foreach ($namespace in $AllowPermissions) + { + if ($namespacesToUpdate.Length -eq 0 -or -not $namespacesToUpdate.NameSpaceId.Contains($namespace.namespaceId)) + { + $namespacesToUpdate += $namespace + } + } + foreach ($namespace in $DenyPermissions) + { + if ($namespacesToUpdate.Length -eq 0 -or -not $namespacesToUpdate.NameSpaceId.Contains($namespace.namespaceId)) + { + $namespacesToUpdate += $namespace + } } - foreach ($permission in $AllowPermissions) + foreach ($namespace in $namespacesToUpdate) { - <#$content = @{ - inheritPermissions = $false - "token": "token1", - "acesDictionary": { - "Microsoft.TeamFoundation.Identity;S-1-9-1551374245-1204400969-2402986413-2179408616-0-0-0-0-1": { - "descriptor": "Microsoft.TeamFoundation.Identity;S-1-9-1551374245-1204400969-2402986413-2179408616-0-0-0-0-1", - "allow": 31, - "deny": 0 - } - }#> + $allowPermissionValue = 0 + $denyPermissionValue = 0 + $allowPermissionsEntries = $AllowPermissions | Where-Object -FilterScript {$_.NamespaceId -eq $namespace.namespaceId} + foreach ($entry in $allowPermissionsEntries) + { + $allowPermissionValue += [Uint32]::Parse($entry.Bit) + } + + $denyPermissionsEntries = $DenyPermissions | Where-Object -FilterScript {$_.NamespaceId -eq $namespace.namespaceId} + foreach ($entry in $denyPermissionsEntries) + { + $denyPermissionValue += [Uint32]::Parse($entry.Bit) + } + + $updateParams = @{ + merge = $false + token = $namespace.token + accessControlEntries = @( + @{ + descriptor = $descriptor + allow = $allowPermissionValue + deny = $denyPermissionValue + extendedInfo = @{} + } + ) + } + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/accesscontrolentries/$($namespace.namespaceId)?api-version=7.1" + $body = ConvertTo-Json $updateParams -Depth 10 -Compress + Write-Verbose -Message "Updating with payload:`r`n$body" + Invoke-M365DSCAzureDevOPSWebRequest -Method POST ` + -Uri $uri ` + -Body $body ` + -ContentType 'application/json' } } From cd66dffb74c2efc621d0141b2d329dbaf3d9bbac Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 4 Oct 2024 15:50:28 -0400 Subject: [PATCH 051/252] Initial release --- .../MSFT_ADOPermissionGroupSettings.psm1 | 42 ++++- .../MSFT_ADOPermissionGroupSettings/readme.md | 4 +- .../settings.json | 24 +-- .../ADOPermissionGroupSettings/2-Update.ps1 | 29 ++-- ...65DSC.ADOPermissionGroupSettings.Tests.ps1 | 146 +++++++++--------- 5 files changed, 133 insertions(+), 112 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.psm1 index c7f5c005ec..c405642904 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.psm1 @@ -316,13 +316,46 @@ function Test-TargetResource $CurrentValues = Get-TargetResource @PSBoundParameters $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + # Evaluate Permissions + $testResult = $true + foreach ($permission in $AllowPermissions) + { + $instance = $CurrentValues.AllowPermissions | Where-Object -FilterScript {$_.Token -eq $permission.Token -and ` + $_.DisplayName -eq $permission.DisplayName -and ` + $_.Bit -eq $permission.Bit -and ` + $_.NamespaceId -eq $permission.NamespaceId} + if ($null -eq $instance) + { + $testResult = $false + Write-Verbose -Message "Drift detected in AllowPermission: {$($permission.DisplayName)}" + } + } + + foreach ($permission in $DenyPermissions) + { + $instance = $CurrentValues.DenyPermissions | Where-Object -FilterScript {$_.Token -eq $permission.Token -and ` + $_.DisplayName -eq $permission.DisplayName -and ` + $_.Bit -eq $permission.Bit -and ` + $_.NamespaceId -eq $permission.NamespaceId} + if ($null -eq $instance) + { + $testResult = $false + Write-Verbose -Message "Drift detected in DenyPermission: {$($permission.DisplayName)}" + } + } + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" - $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` - -Source $($MyInvocation.MyCommand.Source) ` - -DesiredValues $PSBoundParameters ` - -ValuesToCheck $ValuesToCheck.Keys + if ($testResult) + { + $ValuesToCheck.Remove('AllowPermissions') | Out-Null + $ValuesToCheck.Remove('DenyPermissions') | Out-Null + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + } Write-Verbose -Message "Test-TargetResource returned $testResult" @@ -602,6 +635,7 @@ function Get-M365DSCADOGroupPermission DisplayName = $associatedAction.displayName Bit = $associatedAction.bit NamespaceId = $namespace.namespaceId + Token = $token } $results.Deny += $entry } diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/readme.md index 32e0e7fb27..5cb632a8b1 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/readme.md @@ -1,6 +1,6 @@ -# ResourceName +# ADOPermissionGroupSettings ## Description -##TODO - Provide a short description of what the resource is set to configure. +Manages permissions in Azure DevOPS. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/settings.json index edf14b05e4..6509ef6453 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/settings.json @@ -1,13 +1,9 @@ { - "resourceName": "ResourceName", - "description": "Description of what the resource is about.", + "resourceName": "ADOPermissionGroupSettings", + "description": "Manages permissions in Azure DevOPS.", "roles": { - "read": [ - "Role" - ], - "update": [ - "Role" - ] + "read": [], + "update": [] }, "permissions": { "graph": { @@ -16,16 +12,8 @@ "update": [] }, "application": { - "read": [ - { - "name": "Permission for Monitoring and Export" - } - ], - "update": [ - { - "name": "Permission for deploying" - } - ] + "read": [], + "update": [] } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/ADOPermissionGroupSettings/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ADOPermissionGroupSettings/2-Update.ps1 index b516274848..fe74d94ba6 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/ADOPermissionGroupSettings/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/ADOPermissionGroupSettings/2-Update.ps1 @@ -7,20 +7,27 @@ Configuration Example { param( [Parameter()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint + [PSCredential] + $Credential ) Import-DscResource -ModuleName Microsoft365DSC node localhost { - + ADOPermissionGroupSettings "ADOPermissionGroupSettings-O365DSC-DEV" + { + AllowPermissions = @( + MSFT_ADOPermission { + NamespaceId = '5a27515b-ccd7-42c9-84f1-54c998f03866' + DisplayName = 'Edit identity information' + Bit = '2' + Token = 'f6492b10-7ae8-4641-8208-ff5c364a6154\dbe6034e-8fbe-4d6e-a7f3-07a7e70816c9' + } + ); + Credential = $Credential; + DenyPermissions = @(); + Descriptor = "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yNzEyNzI0MzgtMzkwMDMyNjIxNC0yMTgxNjI3NzQwLTkxMDg0NDI0NC0xLTgyODcyNzAzNC0yOTkzNjA0MTcxLTI5MjUwMjk4ODgtNTY0MDg1OTcy"; + GroupName = "[O365DSC-DEV]\My Test Group"; + OrganizationName = "O365DSC-DEV"; + } } } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOPermissionGroupSettings.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOPermissionGroupSettings.Tests.ps1 index f3ddc7d594..2ac94144c9 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOPermissionGroupSettings.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOPermissionGroupSettings.Tests.ps1 @@ -35,8 +35,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { return "Credentials" } - ##TODO - Mock any Remove/Set/New cmdlets - # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { } @@ -44,73 +42,40 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $Script:ExportMode = $false } # Test contexts - Context -Name "The instance should exist but it DOES NOT" -Fixture { - BeforeAll { - $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; - } - - ##TODO - Mock the Get-Cmdlet to return $null - Mock -CommandName Get-Cmdlet -MockWith { - return $null - } - } - It 'Should return Values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' - } - It 'Should return false from the Test method' { - Test-TargetResource @testParams | Should -Be $false - } - - It 'Should create a new instance from the Set method' { - ##TODO - Replace the New-Cmdlet by the appropriate one - Set-TargetResource @testParams - Should -Invoke -CommandName New-Cmdlet -Exactly 1 - } - } - - Context -Name "The instance exists but it SHOULD NOT" -Fixture { - BeforeAll { - $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Absent' - Credential = $Credential; - } - - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { - return @{ - - } - } - } - It 'Should return Values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Present' - } - It 'Should return false from the Test method' { - Test-TargetResource @testParams | Should -Be $false - } - - It 'Should remove the instance from the Set method' { - ##TODO - Replace the Remove-Cmdlet by the appropriate one - Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 - } - } Context -Name "The instance exists and values are already in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; + AllowPermissions = @( + (New-Ciminstance -className MSFT_ADOPermission -Property @{ + NamespaceId = '5a27515b-ccd7-42c9-84f1-54c998f03866' + DisplayName = 'Edit identity information' + Bit = '2' + Token = 'f6492b10-7ae8-4641-8208-ff5c364a6154\dbe6034e-8fbe-4d6e-a7f3-07a7e70816c9' + } -ClientOnly) + ); + Credential = $Credential; + DenyPermissions = @(); + Descriptor = "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yNzEyNzI0MzgtMzkwMDMyNjIxNC0yMTgxNjI3NzQwLTkxMDg0NDI0NC0xLTgyODcyNzAzNC0yOTkzNjA0MTcxLTI5MjUwMjk4ODgtNTY0MDg1OTcy"; + GroupName = "[O365DSC-DEV]\My Test Group"; + OrganizationName = "O365DSC-DEV"; } - ##TODO - Mock the Get-Cmdlet to return the desired values - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Invoke-M365DSCAzureDevOPSWebRequest -MockWith { return @{ - + value = @{ + token ='f6492b10-7ae8-4641-8208-ff5c364a6154\dbe6034e-8fbe-4d6e-a7f3-07a7e70816c9' + acesDictionary = @( + @{ + descriptor = @{ + Allow = 2 + Deny = 0 + } + } + ) + } + principalName = "[O365DSC-DEV]\My Test Group" + Descriptor = "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yNzEyNzI0MzgtMzkwMDMyNjIxNC0yMTgxNjI3NzQwLTkxMDg0NDI0NC0xLTgyODcyNzAzNC0yOTkzNjA0MTcxLTI5MjUwMjk4ODgtNTY0MDg1OTcy"; } } } @@ -123,31 +88,46 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance exists and values are NOT in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; + AllowPermissions = @( + (New-Ciminstance -className MSFT_ADOPermission -Property @{ + NamespaceId = '5a27515b-ccd7-42c9-84f1-54c998f03866' + DisplayName = 'Edit identity information' + Bit = '8' # Drift + Token = 'f6492b10-7ae8-4641-8208-ff5c364a6154\dbe6034e-8fbe-4d6e-a7f3-07a7e70816c9' + } -ClientOnly) + ); + Credential = $Credential; + DenyPermissions = @(); + Descriptor = "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yNzEyNzI0MzgtMzkwMDMyNjIxNC0yMTgxNjI3NzQwLTkxMDg0NDI0NC0xLTgyODcyNzAzNC0yOTkzNjA0MTcxLTI5MjUwMjk4ODgtNTY0MDg1OTcy"; + GroupName = "[O365DSC-DEV]\My Test Group"; + OrganizationName = "O365DSC-DEV"; } - ##TODO - Mock the Get-Cmdlet to return a drift - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Invoke-M365DSCAzureDevOPSWebRequest -MockWith { return @{ - + value = @{ + token ='f6492b10-7ae8-4641-8208-ff5c364a6154\dbe6034e-8fbe-4d6e-a7f3-07a7e70816c9' + acesDictionary = @( + @{ + descriptor = @{ + Allow = 2 + Deny = 0 + } + } + ) + principalName = "[O365DSC-DEV]\My Test Group" + Descriptor = "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yNzEyNzI0MzgtMzkwMDMyNjIxNC0yMTgxNjI3NzQwLTkxMDg0NDI0NC0xLTgyODcyNzAzNC0yOTkzNjA0MTcxLTI5MjUwMjk4ODgtNTY0MDg1OTcy"; + } } } } - It 'Should return Values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Present' - } - It 'Should return false from the Test method' { Test-TargetResource @testParams | Should -Be $false } It 'Should call the Set method' { Set-TargetResource @testParams - ##TODO - Replace the Update-Cmdlet by the appropriate one - Should -Invoke -CommandName Update-Cmdlet -Exactly 1 } } @@ -159,10 +139,22 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Invoke-M365DSCAzureDevOPSWebRequest -MockWith { return @{ - + value = @{ + token ='f6492b10-7ae8-4641-8208-ff5c364a6154\dbe6034e-8fbe-4d6e-a7f3-07a7e70816c9' + acesDictionary = @( + @{ + descriptor = @{ + Allow = 2 + Deny = 0 + } + } + ) + principalName = "[O365DSC-DEV]\My Test Group" + Descriptor = "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yNzEyNzI0MzgtMzkwMDMyNjIxNC0yMTgxNjI3NzQwLTkxMDg0NDI0NC0xLTgyODcyNzAzNC0yOTkzNjA0MTcxLTI5MjUwMjk4ODgtNTY0MDg1OTcy"; + AccountName = 'O365DSC-Dev' + } } } } From d49828bff8cc5747c4ff671a388c754eb8c0880e Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 4 Oct 2024 15:51:54 -0400 Subject: [PATCH 052/252] Update MSFT_ADOPermissionGroupSettings.schema.mof --- .../MSFT_ADOPermissionGroupSettings.schema.mof | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.schema.mof index e0c630fb93..e4c33762cb 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroupSettings/MSFT_ADOPermissionGroupSettings.schema.mof @@ -1,20 +1,20 @@ [ClassVersion("1.0.0")] class MSFT_ADOPermission { - [Write, Description("")] String NamespaceId; - [Write, Description("")] String DisplayName; - [Write, Description("")] UInt32 Bit; - [Write, Description("")] String Token; + [Write, Description("Id of the associate security namespace.")] String NamespaceId; + [Write, Description("Display name of the permission scope.")] String DisplayName; + [Write, Description("Bit mask for the permission")] UInt32 Bit; + [Write, Description("Token value")] String Token; }; [ClassVersion("1.0.0.0"), FriendlyName("ADOPermissionGroupSettings")] class MSFT_ADOPermissionGroupSettings : OMI_BaseResource { - [Key, Description("")] String GroupName; - [Write, Description("")] String OrganizationName; - [Write, Description("")] String Descriptor; - [Write, Description(""), EmbeddedInstance("MSFT_ADOPermission")] string AllowPermissions[]; - [Write, Description(""), EmbeddedInstance("MSFT_ADOPermission")] string DenyPermissions[]; + [Key, Description("Name of the group.")] String GroupName; + [Write, Description("Name of the DevOPS Organization.")] String OrganizationName; + [Write, Description("Descriptor for the group.")] String Descriptor; + [Write, Description("Allow permissions."), EmbeddedInstance("MSFT_ADOPermission")] string AllowPermissions[]; + [Write, Description("Deny permissions"), EmbeddedInstance("MSFT_ADOPermission")] string DenyPermissions[]; [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; From 15c70ccd2b52244cd8bc26738b6b6ffad75ad6a7 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 4 Oct 2024 20:17:49 +0000 Subject: [PATCH 053/252] Updated Resources and Cmdlet documentation pages --- .../azure-ad/ADOPermissionGroupSettings.md | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 docs/docs/resources/azure-ad/ADOPermissionGroupSettings.md diff --git a/docs/docs/resources/azure-ad/ADOPermissionGroupSettings.md b/docs/docs/resources/azure-ad/ADOPermissionGroupSettings.md new file mode 100644 index 0000000000..ed460c2a8b --- /dev/null +++ b/docs/docs/resources/azure-ad/ADOPermissionGroupSettings.md @@ -0,0 +1,98 @@ +# ADOPermissionGroupSettings + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **GroupName** | Key | String | Name of the group. | | +| **OrganizationName** | Write | String | Name of the DevOPS Organization. | | +| **Descriptor** | Write | String | Descriptor for the group. | | +| **AllowPermissions** | Write | MSFT_ADOPermission[] | Allow permissions. | | +| **DenyPermissions** | Write | MSFT_ADOPermission[] | Deny permissions | | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + +### MSFT_ADOPermission + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **NamespaceId** | Write | String | Id of the associate security namespace. | | +| **DisplayName** | Write | String | Display name of the permission scope. | | +| **Bit** | Write | UInt32 | Bit mask for the permission | | +| **Token** | Write | String | Token value | | + + +## Description + +Manages permissions in Azure DevOPS. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - None + +- **Update** + + - None + +## Examples + +### Example 1 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [PSCredential] + $Credential + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + ADOPermissionGroupSettings "ADOPermissionGroupSettings-O365DSC-DEV" + { + AllowPermissions = @( + MSFT_ADOPermission { + NamespaceId = '5a27515b-ccd7-42c9-84f1-54c998f03866' + DisplayName = 'Edit identity information' + Bit = '2' + Token = 'f6492b10-7ae8-4641-8208-ff5c364a6154\dbe6034e-8fbe-4d6e-a7f3-07a7e70816c9' + } + ); + Credential = $Credential; + DenyPermissions = @(); + Descriptor = "vssgp.Uy0xLTktMTU1MTM3NDI0NS0yNzEyNzI0MzgtMzkwMDMyNjIxNC0yMTgxNjI3NzQwLTkxMDg0NDI0NC0xLTgyODcyNzAzNC0yOTkzNjA0MTcxLTI5MjUwMjk4ODgtNTY0MDg1OTcy"; + GroupName = "[O365DSC-DEV]\My Test Group"; + OrganizationName = "O365DSC-DEV"; + } + } +} +``` + From 49230ce21aa5b91637e4adac01c27dc285ee5274 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 4 Oct 2024 20:19:31 +0000 Subject: [PATCH 054/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 86844fd218..39930e9bbd 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -5914,6 +5914,91 @@ } ] }, + { + "ClassName": "MSFT_ADOPermission", + "Parameters": [ + { + "CIMType": "String", + "Name": "NamespaceId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "Bit", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Token", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_ADOPermissionGroupSettings", + "Parameters": [ + { + "CIMType": "String", + "Name": "GroupName", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "OrganizationName", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Descriptor", + "Option": "Write" + }, + { + "CIMType": "MSFT_ADOPermission[]", + "Name": "AllowPermissions", + "Option": "Write" + }, + { + "CIMType": "MSFT_ADOPermission[]", + "Name": "DenyPermissions", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_ADOSecurityPolicy", "Parameters": [ From b17cbd90cf7be959644d448d89e5526989717443 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Fri, 4 Oct 2024 17:00:08 -0700 Subject: [PATCH 055/252] Draft Commit Intune_DSC_Win32App --- .../MSFT_IntuneMobileAppsWin32LobApp.psm1 | 408 ++++++++++++++++++ ...SFT_IntuneMobileAppsWin32LobApp.schema.mof | 15 + .../readme.md | 0 .../settings.json | 0 .../IntuneMobileAppsWin32LobApp/1-Create.ps1 | 29 ++ .../IntuneMobileAppsWin32LobApp/2-Update.ps1 | 29 ++ .../IntuneMobileAppsWin32LobApp/3-Remove.ps1 | 28 ++ ...65DSC.IntuneMobileAppWin32LOBApp.Tests.ps1 | 189 ++++++++ 8 files changed, 698 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/MSFT_IntuneMobileAppsWin32LobApp.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/MSFT_IntuneMobileAppsWin32LobApp.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWin32LobApp/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWin32LobApp/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWin32LobApp/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppWin32LOBApp.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/MSFT_IntuneMobileAppsWin32LobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/MSFT_IntuneMobileAppsWin32LobApp.psm1 new file mode 100644 index 0000000000..e5e0c6b7da --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/MSFT_IntuneMobileAppsWin32LobApp.psm1 @@ -0,0 +1,408 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + #region Intune params + + [Parameter()] + [System.String] + $Id, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + #endregion Intune params + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters | Out-Null + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + + try + { + $instance = $null + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Id -eq $Id} + } + + if ($null -eq $instance) + { + $instance = Get-MgBetaDeviceAppManagementMobileApp -MobileAppId $Id -ErrorAction Stop + + if ($null -eq $instance) + { + Write-Verbose -Message "Could not find MobileApp by Id {$Id}." + + if (-Not [string]::IsNullOrEmpty($DisplayName)) + { + $instance = Get-MgBetaDeviceAppManagementMobileAppConfiguration ` + -Filter "DisplayName eq '$DisplayName'" ` + -ErrorAction SilentlyContinue + } + } + + if ($null -eq $instance) + { + Write-Verbose -Message "Could not find MobileApp by DisplayName {$DisplayName}." + return $nullResult + } + } + + $results = @{ + Id = $instance.Id + DisplayName = $instance.DisplayName + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ApplicationSecret = $ApplicationSecret + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + #region Intune params + + [Parameter()] + [System.String] + $Id, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + #endregion Intune params + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + $setParameters.remove('Id') | Out-Null + $setParameters.remove('Ensure') | Out-Null + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + New-MgBetaDeviceAppManagementMobileApp @SetParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id @SetParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Remove-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id -Confirm:$false + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + #region Intune params + + [Parameter()] + [System.String] + $Id, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + #endregion Intune params + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-MgBetaDeviceAppManagementMobileApp -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + $displayedKey = $config.Id + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + Id = $config.Id + DisplayName = $config.DisplayName + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ApplicationSecret = $ApplicationSecret + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/MSFT_IntuneMobileAppsWin32LobApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/MSFT_IntuneMobileAppsWin32LobApp.schema.mof new file mode 100644 index 0000000000..f0d45d3874 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/MSFT_IntuneMobileAppsWin32LobApp.schema.mof @@ -0,0 +1,15 @@ +[ClassVersion("1.0.0.0"), FriendlyName("IntuneMobileAppsWin32LobApp")] +class MSFT_IntuneMobileAppsWin32LobApp : OMI_BaseResource +{ + [Key, Description("The name of the app.")] String DisplayName; + [Write, Description("The unique identifier for an entity. Read-only.")] String Id; + + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] string Ensure; + [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Secret of the Azure Active Directory tenant used for authentication."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/readme.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/settings.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWin32LobApp/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWin32LobApp/1-Create.ps1 new file mode 100644 index 0000000000..3c39a8f5d3 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWin32LobApp/1-Create.ps1 @@ -0,0 +1,29 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $DisplayName + + ) + + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + IntuneMobileAppsWin32LobApp "IntuneMobileAppsWin32LobApp-Data Management" + { + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Custom Data Management"; + Ensure = "Present"; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWin32LobApp/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWin32LobApp/2-Update.ps1 new file mode 100644 index 0000000000..232b82854e --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWin32LobApp/2-Update.ps1 @@ -0,0 +1,29 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $DisplayName + + ) + + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + IntuneMobileAppsWin32LobApp "IntuneMobileAppsWin32LobApp-Data Management" + { + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Custom Data Management updated"; + Ensure = "Present"; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWin32LobApp/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWin32LobApp/3-Remove.ps1 new file mode 100644 index 0000000000..07a910e21b --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWin32LobApp/3-Remove.ps1 @@ -0,0 +1,28 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $DisplayName + ) + + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + IntuneMobileAppsWin32LobApp "IntuneMobileAppsWin32LobApp-Data Management" + { + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Custom Data Management"; + Ensure = "Absent"; + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppWin32LOBApp.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppWin32LOBApp.Tests.ps1 new file mode 100644 index 0000000000..a3503a7a3d --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppWin32LOBApp.Tests.ps1 @@ -0,0 +1,189 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -GenericStubModule $GenericStubPath + +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { + } + Mock -CommandName New-MgBetaDeviceAppManagementMobileApp -MockWith { + } + Mock -CommandName Update-MgBetaDeviceAppManagementMobileApp -MockWith { + } + Mock -CommandName Remove-MgBetaDeviceAppManagementMobileApp -MockWith { + } + + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + + #Test contexts + + Context -Name '1. The instance should exist but it DOES NOT' -Fixture { + BeforeAll { + $testParams = @{ + Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' + DisplayName = 'Data Management' + Ensure = 'Present' + Credential = $Credential + } + + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { + return $null + } + } + + It '1.1 Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It '1.2 Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + It '1.3 Should create a new instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-MgBetaDeviceAppManagementMobileApp -Exactly 1 + } + } + + Context -Name '2. The instance exists but it SHOULD NOT' -Fixture { + BeforeAll { + $testParams = @{ + Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' + DisplayName = 'Data Management' + Ensure = 'Absent' + Credential = $Credential + } + + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { + return @{ + Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' + DisplayName = 'Data Management' + } + } + } + + It '2.1 Should return values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + It '2.2 Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + It '2.3 Should remove the instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-MgBetaDeviceAppManagementMobileApp -Exactly 1 + } + } + + Context -Name '3. The instance exists and values are already in the desired state' -Fixture { + BeforeAll { + $testParams = @{ + Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' + DisplayName = 'Data Management' + Ensure = 'Present' + Credential = $Credential + } + + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { + return @{ + Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' + DisplayName = 'Data Management' + } + } + } + + It '3.0 Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name '4. The instance exists and values are NOT in the desired state' -Fixture { + BeforeAll { + $testParams = @{ + Id = "046e0b16-76ce-4b49-bf1b-1cc5bd94fb47" + DisplayName = "Data Management" + Ensure = 'Present' + Credential = $Credential + } + + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { + return @{ + Id = "046e0b16-76ce-4b49-bf1b-1cc5bd94fb47" + DisplayName = "Data Management 1" #drift + } + } + } + + It '4.1 Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It '4.2 Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It '4.3 Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Update-MgBetaDeviceAppManagementMobileApp -Exactly 1 + } + } + + Context -Name '5. ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { + return @{ + Id = "046e0b16-76ce-4b49-bf1b-1cc5bd94fb47" + DisplayName = "Data Management" + } + } + } + + It '5.1 Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope From 6bc005bcf6bf30c55a3d7f269aa9915637d5ccd6 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Fri, 4 Oct 2024 17:44:37 -0700 Subject: [PATCH 056/252] Draft Intune DSC AndroidApp --- .../MSFT_IntuneAppCategory.schema.mof | 4 +- .../MSFT_IntuneMobileAppsAndroidLobApp.psm1 | 408 ++++++++++++++++++ .../readme.md | 0 .../settings.json | 0 .../1-Create.ps1 | 32 ++ .../2-Update.ps1 | 32 ++ .../3-Remove.ps1 | 32 ++ ...SC.IntuneMobileAppsAndroidLobApp.Tests.ps1 | 189 ++++++++ 8 files changed, 695 insertions(+), 2 deletions(-) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/MSFT_IntuneMobileAppsAndroidLobApp.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsAndroidLobApp/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsAndroidLobApp/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsAndroidLobApp/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsAndroidLobApp.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/MSFT_IntuneAppCategory.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/MSFT_IntuneAppCategory.schema.mof index 676bc98242..57c7816e7f 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/MSFT_IntuneAppCategory.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/MSFT_IntuneAppCategory.schema.mof @@ -1,7 +1,7 @@ [ClassVersion("1.0.0.0"), FriendlyName("IntuneAppCategory")] -class MSFT_IntuneAppCategory : OMI_BaseResource +class MSFT_IntuneMobileAppsAndroidLobApp : OMI_BaseResource { - [Key, Description("The name of the app category.")] String DisplayName; + [Key, Description("The name of the app.")] String DisplayName; [Write, Description("The unique identifier for an entity. Read-only.")] String Id; [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] string Ensure; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/MSFT_IntuneMobileAppsAndroidLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/MSFT_IntuneMobileAppsAndroidLobApp.psm1 new file mode 100644 index 0000000000..e5e0c6b7da --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/MSFT_IntuneMobileAppsAndroidLobApp.psm1 @@ -0,0 +1,408 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + #region Intune params + + [Parameter()] + [System.String] + $Id, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + #endregion Intune params + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters | Out-Null + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + + try + { + $instance = $null + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Id -eq $Id} + } + + if ($null -eq $instance) + { + $instance = Get-MgBetaDeviceAppManagementMobileApp -MobileAppId $Id -ErrorAction Stop + + if ($null -eq $instance) + { + Write-Verbose -Message "Could not find MobileApp by Id {$Id}." + + if (-Not [string]::IsNullOrEmpty($DisplayName)) + { + $instance = Get-MgBetaDeviceAppManagementMobileAppConfiguration ` + -Filter "DisplayName eq '$DisplayName'" ` + -ErrorAction SilentlyContinue + } + } + + if ($null -eq $instance) + { + Write-Verbose -Message "Could not find MobileApp by DisplayName {$DisplayName}." + return $nullResult + } + } + + $results = @{ + Id = $instance.Id + DisplayName = $instance.DisplayName + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ApplicationSecret = $ApplicationSecret + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + #region Intune params + + [Parameter()] + [System.String] + $Id, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + #endregion Intune params + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + $setParameters.remove('Id') | Out-Null + $setParameters.remove('Ensure') | Out-Null + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + New-MgBetaDeviceAppManagementMobileApp @SetParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id @SetParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Remove-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id -Confirm:$false + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + #region Intune params + + [Parameter()] + [System.String] + $Id, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + #endregion Intune params + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-MgBetaDeviceAppManagementMobileApp -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + $displayedKey = $config.Id + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + Id = $config.Id + DisplayName = $config.DisplayName + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ApplicationSecret = $ApplicationSecret + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/readme.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/settings.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsAndroidLobApp/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsAndroidLobApp/1-Create.ps1 new file mode 100644 index 0000000000..6d10550d7e --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsAndroidLobApp/1-Create.ps1 @@ -0,0 +1,32 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + IntuneMobileAppsAndroidLobApp "IntuneMobileAppsAndroidLobApp-Data Management" + { + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Custom Data Management"; + Ensure = "Present"; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsAndroidLobApp/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsAndroidLobApp/2-Update.ps1 new file mode 100644 index 0000000000..a7d50d91bb --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsAndroidLobApp/2-Update.ps1 @@ -0,0 +1,32 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + IntuneMobileAppsAndroidLobApp "IntuneMobileAppsAndroidLobApp-Data Management" + { + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Custom Data Management updated"; + Ensure = "Present"; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsAndroidLobApp/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsAndroidLobApp/3-Remove.ps1 new file mode 100644 index 0000000000..f9f09c6d16 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsAndroidLobApp/3-Remove.ps1 @@ -0,0 +1,32 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + IntuneMobileAppsAndroidLobApp "IntuneMobileAppsAndroidLobApp-Data Management" + { + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Custom Data Management"; + Ensure = "Absent"; + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsAndroidLobApp.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsAndroidLobApp.Tests.ps1 new file mode 100644 index 0000000000..a3503a7a3d --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsAndroidLobApp.Tests.ps1 @@ -0,0 +1,189 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -GenericStubModule $GenericStubPath + +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { + } + Mock -CommandName New-MgBetaDeviceAppManagementMobileApp -MockWith { + } + Mock -CommandName Update-MgBetaDeviceAppManagementMobileApp -MockWith { + } + Mock -CommandName Remove-MgBetaDeviceAppManagementMobileApp -MockWith { + } + + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + + #Test contexts + + Context -Name '1. The instance should exist but it DOES NOT' -Fixture { + BeforeAll { + $testParams = @{ + Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' + DisplayName = 'Data Management' + Ensure = 'Present' + Credential = $Credential + } + + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { + return $null + } + } + + It '1.1 Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It '1.2 Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + It '1.3 Should create a new instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-MgBetaDeviceAppManagementMobileApp -Exactly 1 + } + } + + Context -Name '2. The instance exists but it SHOULD NOT' -Fixture { + BeforeAll { + $testParams = @{ + Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' + DisplayName = 'Data Management' + Ensure = 'Absent' + Credential = $Credential + } + + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { + return @{ + Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' + DisplayName = 'Data Management' + } + } + } + + It '2.1 Should return values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + It '2.2 Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + It '2.3 Should remove the instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-MgBetaDeviceAppManagementMobileApp -Exactly 1 + } + } + + Context -Name '3. The instance exists and values are already in the desired state' -Fixture { + BeforeAll { + $testParams = @{ + Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' + DisplayName = 'Data Management' + Ensure = 'Present' + Credential = $Credential + } + + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { + return @{ + Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' + DisplayName = 'Data Management' + } + } + } + + It '3.0 Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name '4. The instance exists and values are NOT in the desired state' -Fixture { + BeforeAll { + $testParams = @{ + Id = "046e0b16-76ce-4b49-bf1b-1cc5bd94fb47" + DisplayName = "Data Management" + Ensure = 'Present' + Credential = $Credential + } + + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { + return @{ + Id = "046e0b16-76ce-4b49-bf1b-1cc5bd94fb47" + DisplayName = "Data Management 1" #drift + } + } + } + + It '4.1 Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It '4.2 Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It '4.3 Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Update-MgBetaDeviceAppManagementMobileApp -Exactly 1 + } + } + + Context -Name '5. ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { + return @{ + Id = "046e0b16-76ce-4b49-bf1b-1cc5bd94fb47" + DisplayName = "Data Management" + } + } + } + + It '5.1 Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope From b90fb97d3c0c7f5da3c111badc65fad9deaa052c Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Fri, 4 Oct 2024 18:15:25 -0700 Subject: [PATCH 057/252] Draft Intune DSC Win32App --- .../readme.md | 5 +++ .../settings.json | 32 +++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/readme.md index e69de29bb2..4485083c7e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/readme.md @@ -0,0 +1,5 @@ +# IntuneMobileAppsWin32LobApp + +## Description + +Configures a resource for navigation property for Intune mobile app. Default app cannot be renamed. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/settings.json index e69de29bb2..3845518060 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName": "IntuneMobileAppsWin32LobApp", + "description": "Configures a resource for navigation property for Intune mobile app.", + "permissions": { + "graph": { + "delegated": { + "read": [ + { + "name": "DeviceManagementApps.Read.All" + } + ], + "update": [ + { + "name": "DeviceManagementApps.ReadWrite.All" + } + ] + }, + "application": { + "read": [ + { + "name": "DeviceManagementApps.Read.All" + } + ], + "update": [ + { + "name": "DeviceManagementApps.ReadWrite.All" + } + ] + } + } + } +} From b823018445d026775002710e55677fa0e01f7876 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Fri, 4 Oct 2024 18:39:21 -0700 Subject: [PATCH 058/252] Exported LargeIcon. --- .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 118 +++++++++++++++++- ...SFT_IntuneMobileAppsMacOSLobApp.schema.mof | 12 +- 2 files changed, 121 insertions(+), 9 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 index 34e71951ac..bee422f00c 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 @@ -67,6 +67,10 @@ function Get-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $Assignments, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $LargeIcon, + #endregion @@ -147,6 +151,7 @@ function Get-TargetResource Write-Verbose -Message "Found Mobile app with {$DisplayName}." + $results = @{ Id = $instance.Id Description = $instance.Description @@ -160,7 +165,8 @@ function Get-TargetResource Publisher = $instance.Publisher PublishingState = $instance.PublishingState.ToString() RoleScopeTagIds = $instance.RoleScopeTagIds - IgnoreVersionDetection = $instance.AdditionalProperties.IgnoreVersionDetection + # LargeIcon = $instance.LargeIcon + IgnoreVersionDetection = $instance.AdditionalProperties.ignoreVersionDetection Ensure = 'Present' Credential = $Credential @@ -172,6 +178,9 @@ function Get-TargetResource AccessTokens = $AccessTokens } + #region complex types + + #Categories if($null -ne $instance.Categories) { $results.Add('Categories', $instance.Categories) @@ -180,6 +189,7 @@ function Get-TargetResource $results.Add('Categories', "") } + #Assignments $resultAssignments = @() $appAssignments = Get-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $instance.Id if ($null -ne $appAssignments -and $appAssignments.count -gt 0) @@ -191,6 +201,25 @@ function Get-TargetResource $results.Add('Assignments', $resultAssignments) } + #LargeIcon + + # The large is returned only when Get cmdlet is called with Id parameter. The large icon is a base64 encoded string, so we need to convert it to a byte array. + $instanceWithLargeIcon = Get-MgBetaDeviceAppManagementMobileApp -MobileAppId $instance.Id + + + #$LargeIcon.Type = $typeLargeIconType + #$LargeIcon.Value = $base64LargeIconStringValue + + if($null -ne $instanceWithLargeIcon.LargeIcon) + { + $results.Add('LargeIcon', $instanceWithLargeIcon.LargeIcon) + } + else { + $results.Add('LargeIcon', "") + } + + #end region complex types + return [System.Collections.Hashtable] $results } catch @@ -274,6 +303,10 @@ function Set-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $Assignments, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $LargeIcon, + #endregion @@ -326,21 +359,31 @@ function Set-TargetResource $currentInstance = Get-TargetResource @PSBoundParameters $PSBoundParameters.Remove('Categories') | Out-Null $PSBoundParameters.Remove('Assignments') | Out-Null + $PSBoundParameters.Remove('LargeIcon') | Out-Null $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters $setParameters.remove('Id') | Out-Null $setParameters.remove('Ensure') | Out-Null $setParameters.remove('Categories') | Out-Null $setParameters.remove('Assignments') | Out-Null + $setParameters.remove('LargeIcon') | Out-Null $AdditionalProperties = Get-M365DSCIntuneMobileMocOSLobAppAdditionalProperties -Properties ([System.Collections.Hashtable]$PSBoundParameters) + #Categories if($null -ne $Categories) { [System.Object[]]$categoriesValue = ConvertTo-M365DSCIntuneAppCategories -Categories $Categories $setParameters.Add('Categories', $categoriesValue) } + #LargeIcon + if($null -ne $LargeIcon) + { + [System.Object]$LargeIconValue = ConvertTo-M365DSCIntuneAppLargeIcon -LargeIcon $LargeIcon + $setParameters.Add('LargeIcon', $LargeIconValue) + } + # CREATE if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { @@ -445,6 +488,10 @@ function Test-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $Assignments, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $LargeIcon, + #endregion [Parameter()] @@ -635,10 +682,7 @@ function Export-TargetResource Publisher = $config.Publisher PublishingState = $config.PublishingState.ToString() RoleScopeTagIds = $config.RoleScopeTagIds - - IgnoreVersionDetection = $config.AdditionalProperties.IgnoreVersionDetection - - # LargeIcon = $config.LargeIcon + IgnoreVersionDetection = $config.AdditionalProperties.ignoreVersionDetection # ChildApps = $config.ChildApps Ensure = 'Present' @@ -661,6 +705,7 @@ function Export-TargetResource #region complex types + #Categories if($null -eq $Results.Categories -or $Results.Categories.Count -eq 0) { $Results.Categories = $null @@ -670,6 +715,7 @@ function Export-TargetResource $Results.Categories = Get-M365DSCIntuneAppCategoriesAsString -Categories $Results.Categories } + #Assignments if ($Results.Assignments) { $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString -ComplexObject ([Array]$Results.Assignments) -CIMInstanceName DeviceManagementMobileAppAssignment @@ -684,6 +730,17 @@ function Export-TargetResource } } + #LargeIcon + if($null -eq $Results.LargeIcon) + { + $Results.LargeIcon = $null + } + else + { + $Results.LargeIcon = Get-M365DSCIntuneAppLargeIconAsString -LargeIcon $Results.LargeIcon + } + + #endregion complex types $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` @@ -819,6 +876,25 @@ function ConvertTo-M365DSCIntuneAppCategories return $result } +function ConvertTo-M365DSCIntuneAppLargeIcon #set +{ + [OutputType([System.Object])] + param( + [Parameter(Mandatory = $true)] + [System.Object] + $LargeIcon + ) + + $base64String = [System.Convert]::ToBase64String($LargeIcon.Value) + + $result = @{ + type = $LargeIcon.Type + value = $base64String + } + + return $result +} + function Get-M365DSCIntuneAppCategoriesAsString { [CmdletBinding()] @@ -854,6 +930,38 @@ function Get-M365DSCIntuneAppCategoriesAsString return $StringContent } +function Get-M365DSCIntuneAppLargeIconAsString #Get and export +{ + [CmdletBinding()] + [OutputType([System.String])] + param( + [Parameter(Mandatory = $true)] + [System.Object] + $LargeIcon + ) + + $StringContent = '@(' + $space = ' ' + $indent = ' ' + + if ($null -ne $LargeIcon) + { + $StringContent += "`r`n" + $StringContent += "$space" + } + + # [System.Convert]::ToBase64String($LargeIcon.Value) - converts byte array to base64 string, this might be needed below + $base64String = [System.Convert]::ToBase64String($LargeIcon.Value) + + $StringContent += "MSFT_DeviceManagementMimeContent { `r`n" + $StringContent += "$($space)$($indent)type = '" + $LargeIcon.Type + "'`r`n" + $StringContent += "$($space)$($indent)value = '" + $base64String + "'`r`n" + $StringContent += "$space}" + $StringContent += ')' + + return $StringContent + } + function Get-M365DSCIntuneMobileMocOSLobAppAdditionalProperties { [CmdletBinding()] diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof index 5b2f809801..79830b5199 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof @@ -15,15 +15,13 @@ class MSFT_IntuneMobileAppsMacOSLobApp : OMI_BaseResource [Write, Description("The publishing state for the app. The app cannot be assigned unless the app is published. Inherited from mobileApp."), ValueMap{"notPublished", "processing","published"}, Values{"notPublished", "processing", "published"}] String PublishingState; [Write, Description("List of Scope Tag IDs for mobile app.")] String RoleScopeTagIds[]; + [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppCategory")] String Categories[]; [Write, Description("The list of assignments for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppAssignment")] String Assignments[]; - - [Write, Description("The privacy statement Url. Inherited from mobileApp.")] String BundleId; - [Write, Description("The publisher of the app. Inherited from mobileApp.")] String BuildNumber; + [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMimeContent")] String LargeIcon; [Write, Description("Wether to ignore the version of the app or not.")] Boolean IgnoreVersionDetection; - [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] String Ensure; [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; @@ -34,6 +32,12 @@ class MSFT_IntuneMobileAppsMacOSLobApp : OMI_BaseResource [Write, Description("Access token used for authentication.")] String AccessTokens[]; }; +class MSFT_DeviceManagementMimeContent +{ + [Write, Description("Indicates the type of mime content.")] String Type; + [Write, Description("The byte array that contains the actual content.")] String Value; +}; + class MSFT_DeviceManagementMobileAppCategory { [Key, Description("The name of the app category.")] String displayName; From cf4d99fd1ae33e8dd6c9dd771f90d0035f60aca9 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Fri, 4 Oct 2024 18:56:27 -0700 Subject: [PATCH 059/252] Draft Intune DSC AndroidApp --- .../MSFT_IntuneAppCategory.schema.mof | 2 +- ...T_IntuneMobileAppsAndroidLobApp.schema.mof | 15 +++++++++ .../readme.md | 3 ++ .../settings.json | 32 +++++++++++++++++++ 4 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/MSFT_IntuneMobileAppsAndroidLobApp.schema.mof diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/MSFT_IntuneAppCategory.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/MSFT_IntuneAppCategory.schema.mof index 57c7816e7f..c9d08b3067 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/MSFT_IntuneAppCategory.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/MSFT_IntuneAppCategory.schema.mof @@ -1,5 +1,5 @@ [ClassVersion("1.0.0.0"), FriendlyName("IntuneAppCategory")] -class MSFT_IntuneMobileAppsAndroidLobApp : OMI_BaseResource +class MSFT_IntuneAppCategory : OMI_BaseResource { [Key, Description("The name of the app.")] String DisplayName; [Write, Description("The unique identifier for an entity. Read-only.")] String Id; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/MSFT_IntuneMobileAppsAndroidLobApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/MSFT_IntuneMobileAppsAndroidLobApp.schema.mof new file mode 100644 index 0000000000..f637f5d71b --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/MSFT_IntuneMobileAppsAndroidLobApp.schema.mof @@ -0,0 +1,15 @@ +[ClassVersion("1.0.0.0"), FriendlyName("IntuneMobileAppsAndroidLobApp")] +class MSFT_IntuneMobileAppsAndroidLobApp : OMI_BaseResource +{ + [Key, Description("The name of the app.")] String DisplayName; + [Write, Description("The unique identifier for an entity. Read-only.")] String Id; + + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] string Ensure; + [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Secret of the Azure Active Directory tenant used for authentication."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/readme.md index e69de29bb2..99fc165230 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/readme.md @@ -0,0 +1,3 @@ +# IntuneMobileAppsAndroidLobApp + +## Description diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/settings.json index e69de29bb2..439af65889 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName": "IntuneMobileAppsAndroidLobApp", + "description": "This resource configures an Intune mobile app.", + "permissions": { + "graph": { + "delegated": { + "read": [ + { + "name": "DeviceManagementApps.Read.All" + } + ], + "update": [ + { + "name": "DeviceManagementApps.ReadWrite.All" + } + ] + }, + "application": { + "read": [ + { + "name": "DeviceManagementApps.Read.All" + } + ], + "update": [ + { + "name": "DeviceManagementApps.ReadWrite.All" + } + ] + } + } + } +} From 59f0429f0172d780e5285d4b43a29fed3f4a30bb Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Fri, 4 Oct 2024 19:18:33 -0700 Subject: [PATCH 060/252] Draft Intune DSC IOSApps --- .../MSFT_IntuneMobileAppsIOSLobApp.psm1 | 408 ++++++++++++++++++ .../MSFT_IntuneMobileAppsIOSLobApp.schema.mof | 15 + .../MSFT_IntuneMobileAppsIOSLobApp/readme.md | 3 + .../settings.json | 32 ++ .../IntuneMobileAppsIOSLobApp/1-Create.ps1 | 32 ++ .../IntuneMobileAppsIOSLobApp/2-Update.ps1 | 32 ++ .../IntuneMobileAppsIOSLobApp/3-Remove.ps1 | 32 ++ ...365DSC.IntuneMobileAppsIOSLobApp.Tests.ps1 | 189 ++++++++ 8 files changed, 743 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/MSFT_IntuneMobileAppsIOSLobApp.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/MSFT_IntuneMobileAppsIOSLobApp.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsIOSLobApp/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsIOSLobApp/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsIOSLobApp/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsIOSLobApp.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/MSFT_IntuneMobileAppsIOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/MSFT_IntuneMobileAppsIOSLobApp.psm1 new file mode 100644 index 0000000000..e5e0c6b7da --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/MSFT_IntuneMobileAppsIOSLobApp.psm1 @@ -0,0 +1,408 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + #region Intune params + + [Parameter()] + [System.String] + $Id, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + #endregion Intune params + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters | Out-Null + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + + try + { + $instance = $null + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Id -eq $Id} + } + + if ($null -eq $instance) + { + $instance = Get-MgBetaDeviceAppManagementMobileApp -MobileAppId $Id -ErrorAction Stop + + if ($null -eq $instance) + { + Write-Verbose -Message "Could not find MobileApp by Id {$Id}." + + if (-Not [string]::IsNullOrEmpty($DisplayName)) + { + $instance = Get-MgBetaDeviceAppManagementMobileAppConfiguration ` + -Filter "DisplayName eq '$DisplayName'" ` + -ErrorAction SilentlyContinue + } + } + + if ($null -eq $instance) + { + Write-Verbose -Message "Could not find MobileApp by DisplayName {$DisplayName}." + return $nullResult + } + } + + $results = @{ + Id = $instance.Id + DisplayName = $instance.DisplayName + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ApplicationSecret = $ApplicationSecret + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + #region Intune params + + [Parameter()] + [System.String] + $Id, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + #endregion Intune params + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + $setParameters.remove('Id') | Out-Null + $setParameters.remove('Ensure') | Out-Null + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + New-MgBetaDeviceAppManagementMobileApp @SetParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id @SetParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Remove-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id -Confirm:$false + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + #region Intune params + + [Parameter()] + [System.String] + $Id, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + #endregion Intune params + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-MgBetaDeviceAppManagementMobileApp -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + $displayedKey = $config.Id + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + Id = $config.Id + DisplayName = $config.DisplayName + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ApplicationSecret = $ApplicationSecret + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/MSFT_IntuneMobileAppsIOSLobApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/MSFT_IntuneMobileAppsIOSLobApp.schema.mof new file mode 100644 index 0000000000..28add1ac2a --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/MSFT_IntuneMobileAppsIOSLobApp.schema.mof @@ -0,0 +1,15 @@ +[ClassVersion("1.0.0.0"), FriendlyName("IntuneMobileAppsIOSLobApp")] +class MSFT_IntuneMobileAppsIOSLobApp : OMI_BaseResource +{ + [Key, Description("The name of the app category.")] String DisplayName; + [Write, Description("The unique identifier for an entity. Read-only.")] String Id; + + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] string Ensure; + [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Secret of the Azure Active Directory tenant used for authentication."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/readme.md new file mode 100644 index 0000000000..b41aeb8da9 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/readme.md @@ -0,0 +1,3 @@ +# IntuneMobileAppsIOSLobApp + +## Description diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/settings.json new file mode 100644 index 0000000000..e09fcf3ab7 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName": "IntuneMobileAppsIOSLobApp", + "description": "Configures a resource for navigation property for Intune mobile app categories.", + "permissions": { + "graph": { + "delegated": { + "read": [ + { + "name": "DeviceManagementApps.Read.All" + } + ], + "update": [ + { + "name": "DeviceManagementApps.ReadWrite.All" + } + ] + }, + "application": { + "read": [ + { + "name": "DeviceManagementApps.Read.All" + } + ], + "update": [ + { + "name": "DeviceManagementApps.ReadWrite.All" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsIOSLobApp/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsIOSLobApp/1-Create.ps1 new file mode 100644 index 0000000000..af89f735c1 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsIOSLobApp/1-Create.ps1 @@ -0,0 +1,32 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + IntuneMobileAppsIOSLobApp "IntuneMobileAppsIOSLobApp-Data Management" + { + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Custom Data Management"; + Ensure = "Present"; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsIOSLobApp/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsIOSLobApp/2-Update.ps1 new file mode 100644 index 0000000000..15243d392f --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsIOSLobApp/2-Update.ps1 @@ -0,0 +1,32 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + IntuneMobileAppsIOSLobApp "IntuneMobileAppsIOSLobApp-Data Management" + { + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Custom Data Management updated"; + Ensure = "Present"; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsIOSLobApp/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsIOSLobApp/3-Remove.ps1 new file mode 100644 index 0000000000..c480aed510 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsIOSLobApp/3-Remove.ps1 @@ -0,0 +1,32 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + IntuneMobileAppsIOSLobApp "IntuneMobileAppsIOSLobApp-Data Management" + { + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Custom Data Management"; + Ensure = "Absent"; + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsIOSLobApp.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsIOSLobApp.Tests.ps1 new file mode 100644 index 0000000000..a3503a7a3d --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsIOSLobApp.Tests.ps1 @@ -0,0 +1,189 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -GenericStubModule $GenericStubPath + +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { + } + Mock -CommandName New-MgBetaDeviceAppManagementMobileApp -MockWith { + } + Mock -CommandName Update-MgBetaDeviceAppManagementMobileApp -MockWith { + } + Mock -CommandName Remove-MgBetaDeviceAppManagementMobileApp -MockWith { + } + + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + + #Test contexts + + Context -Name '1. The instance should exist but it DOES NOT' -Fixture { + BeforeAll { + $testParams = @{ + Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' + DisplayName = 'Data Management' + Ensure = 'Present' + Credential = $Credential + } + + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { + return $null + } + } + + It '1.1 Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It '1.2 Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + It '1.3 Should create a new instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-MgBetaDeviceAppManagementMobileApp -Exactly 1 + } + } + + Context -Name '2. The instance exists but it SHOULD NOT' -Fixture { + BeforeAll { + $testParams = @{ + Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' + DisplayName = 'Data Management' + Ensure = 'Absent' + Credential = $Credential + } + + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { + return @{ + Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' + DisplayName = 'Data Management' + } + } + } + + It '2.1 Should return values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + It '2.2 Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + It '2.3 Should remove the instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-MgBetaDeviceAppManagementMobileApp -Exactly 1 + } + } + + Context -Name '3. The instance exists and values are already in the desired state' -Fixture { + BeforeAll { + $testParams = @{ + Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' + DisplayName = 'Data Management' + Ensure = 'Present' + Credential = $Credential + } + + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { + return @{ + Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' + DisplayName = 'Data Management' + } + } + } + + It '3.0 Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name '4. The instance exists and values are NOT in the desired state' -Fixture { + BeforeAll { + $testParams = @{ + Id = "046e0b16-76ce-4b49-bf1b-1cc5bd94fb47" + DisplayName = "Data Management" + Ensure = 'Present' + Credential = $Credential + } + + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { + return @{ + Id = "046e0b16-76ce-4b49-bf1b-1cc5bd94fb47" + DisplayName = "Data Management 1" #drift + } + } + } + + It '4.1 Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It '4.2 Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It '4.3 Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Update-MgBetaDeviceAppManagementMobileApp -Exactly 1 + } + } + + Context -Name '5. ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { + return @{ + Id = "046e0b16-76ce-4b49-bf1b-1cc5bd94fb47" + DisplayName = "Data Management" + } + } + } + + It '5.1 Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope From 93a4ce3a99f177c5e9d37b07ccfc3ac544ecd0f3 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Fri, 4 Oct 2024 20:25:47 -0700 Subject: [PATCH 061/252] Config with Large icon compiles if quotes are removed. --- .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 index bee422f00c..e4b20c775f 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 @@ -737,9 +737,17 @@ function Export-TargetResource } else { - $Results.LargeIcon = Get-M365DSCIntuneAppLargeIconAsString -LargeIcon $Results.LargeIcon - } + #$tempicon = Get-M365DSCDRGComplexTypeToString -ComplexObject $Results.LargeIcon -CIMInstanceName DeviceManagementMimeContent -IsArray $false + if ($tempicon) + { + $Results.LargeIcon = Get-M365DSCIntuneAppLargeIconAsString -LargeIcon $Results.LargeIcon + } + else + { + $Results.Remove('LargeIcon') | Out-Null + } + } #endregion complex types @@ -867,7 +875,7 @@ function ConvertTo-M365DSCIntuneAppCategories { $currentCategory = @{ id = $category.id - displayName = $category.displayName # This 'displayName' property has to exist in microsoft.management.services.api.mobileAppCategory + displayName = $category.displayName } $result += $currentCategory @@ -885,11 +893,12 @@ function ConvertTo-M365DSCIntuneAppLargeIcon #set $LargeIcon ) - $base64String = [System.Convert]::ToBase64String($LargeIcon.Value) + #$iconValue = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($LargeIcon.Value)) => throws string to intance conversion error + #$iconValue = [System.Convert]::FromBase64String($LargeIcon.Value) => throws string to intance conversion error $result = @{ type = $LargeIcon.Type - value = $base64String + value = $iconValue } return $result @@ -927,6 +936,7 @@ function Get-M365DSCIntuneAppCategoriesAsString } $StringContent += ')' + return $StringContent } @@ -940,9 +950,9 @@ function Get-M365DSCIntuneAppLargeIconAsString #Get and export $LargeIcon ) - $StringContent = '@(' - $space = ' ' - $indent = ' ' + # $StringContent = '@(' + $space = ' ' + $indent = ' ' if ($null -ne $LargeIcon) { @@ -950,14 +960,13 @@ function Get-M365DSCIntuneAppLargeIconAsString #Get and export $StringContent += "$space" } - # [System.Convert]::ToBase64String($LargeIcon.Value) - converts byte array to base64 string, this might be needed below - $base64String = [System.Convert]::ToBase64String($LargeIcon.Value) + $base64String = [System.Convert]::ToBase64String($LargeIcon.Value) # This exports the base64 string (blob) of the byte array, same as we see in Graph API response $StringContent += "MSFT_DeviceManagementMimeContent { `r`n" $StringContent += "$($space)$($indent)type = '" + $LargeIcon.Type + "'`r`n" $StringContent += "$($space)$($indent)value = '" + $base64String + "'`r`n" $StringContent += "$space}" - $StringContent += ')' + #$StringContent += ')' return $StringContent } From 4247a60643dc018b664852e61b535db4a717bd48 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Fri, 4 Oct 2024 21:32:36 -0700 Subject: [PATCH 062/252] LargeIcon compiles but Start-dscconfiguration throws error "request size exceeded the configured MaxEnvelopeSize quota" --- .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 index e4b20c775f..0d66ba41d6 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 @@ -731,22 +731,13 @@ function Export-TargetResource } #LargeIcon - if($null -eq $Results.LargeIcon) + if($Results.LargeIcon) { - $Results.LargeIcon = $null + $Results.LargeIcon = Get-M365DSCIntuneAppLargeIconAsString -LargeIcon $Results.LargeIcon } else { - #$tempicon = Get-M365DSCDRGComplexTypeToString -ComplexObject $Results.LargeIcon -CIMInstanceName DeviceManagementMimeContent -IsArray $false - - if ($tempicon) - { - $Results.LargeIcon = Get-M365DSCIntuneAppLargeIconAsString -LargeIcon $Results.LargeIcon - } - else - { - $Results.Remove('LargeIcon') | Out-Null - } + $Results.Remove('LargeIcon') | Out-Null } #endregion complex types @@ -767,6 +758,11 @@ function Export-TargetResource $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Categories' } + if ($null -ne $Results.LargeIcon) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'LargeIcon' + } + if ($Results.Assignments) { $isCIMArray = $false @@ -898,7 +894,7 @@ function ConvertTo-M365DSCIntuneAppLargeIcon #set $result = @{ type = $LargeIcon.Type - value = $iconValue + value = $LargeIcon.Value } return $result From 8cb209d5432f0ab1fabc8077f98891c1c0165e39 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Sat, 5 Oct 2024 19:35:25 +0000 Subject: [PATCH 063/252] Updated Resources and Cmdlet documentation pages --- .../exchange/EXOMailboxFolderPermission.md | 20 +- .../resources/exchange/EXOMailboxIRMAccess.md | 23 ++- .../resources/exchange/EXOManagementScope.md | 12 +- .../exchange/EXOMigrationEndpoint.md | 189 ++++++++++++++++++ 4 files changed, 227 insertions(+), 17 deletions(-) create mode 100644 docs/docs/resources/exchange/EXOMigrationEndpoint.md diff --git a/docs/docs/resources/exchange/EXOMailboxFolderPermission.md b/docs/docs/resources/exchange/EXOMailboxFolderPermission.md index e73479bb40..41176e7e58 100644 --- a/docs/docs/resources/exchange/EXOMailboxFolderPermission.md +++ b/docs/docs/resources/exchange/EXOMailboxFolderPermission.md @@ -75,10 +75,12 @@ Configuration Example { EXOMailboxFolderPermission "EXOMailboxFolderPermission-admin:\Calendar" { - Credential = $Credscredential; - Ensure = "Present"; - Identity = "amdin:\Calendar"; - UserPermissions = @(MSFT_EXOMailboxFolderUserPermission { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Present"; + Identity = "amdin:\Calendar"; + UserPermissions = @(MSFT_EXOMailboxFolderUserPermission { User = 'Default' AccessRights = 'AvailabilityOnly' } @@ -123,10 +125,12 @@ Configuration Example { EXOMailboxFolderPermission "EXOMailboxFolderPermission-admin:\Calendar" { - Credential = $Credscredential; - Ensure = "Present"; - Identity = "admin:\Calendar"; - UserPermissions = @(MSFT_EXOMailboxFolderUserPermission { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Present"; + Identity = "admin:\Calendar"; + UserPermissions = @(MSFT_EXOMailboxFolderUserPermission { User = 'Default' AccessRights = 'AvailabilityOnly' } diff --git a/docs/docs/resources/exchange/EXOMailboxIRMAccess.md b/docs/docs/resources/exchange/EXOMailboxIRMAccess.md index d349b97793..280d5c2b7d 100644 --- a/docs/docs/resources/exchange/EXOMailboxIRMAccess.md +++ b/docs/docs/resources/exchange/EXOMailboxIRMAccess.md @@ -62,11 +62,13 @@ Configuration Example { EXOMailboxIRMAccess "EXOMailboxIRMAccess-qwe@testorg.onmicrosoft.com" { - AccessLevel = "Block"; - Credential = $Credscredential; - Ensure = "Present"; - Identity = "qwe@$OrganizationName"; - User = "admin@$OrganizationName"; + AccessLevel = "Block"; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Present"; + Identity = "qwe@$OrganizationName"; + User = "admin@$OrganizationName"; } } } @@ -96,7 +98,16 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + EXOMailboxIRMAccess "EXOMailboxIRMAccess-qwe@testorg.onmicrosoft.com" + { + AccessLevel = "Block"; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Absent"; + Identity = "qwe@$OrganizationName"; + User = "admin@$OrganizationName"; + } } } ``` diff --git a/docs/docs/resources/exchange/EXOManagementScope.md b/docs/docs/resources/exchange/EXOManagementScope.md index 873248793d..ab66d2b4c3 100644 --- a/docs/docs/resources/exchange/EXOManagementScope.md +++ b/docs/docs/resources/exchange/EXOManagementScope.md @@ -66,7 +66,9 @@ Configuration Example { EXOManagementScope "EXOManagementScope-Test New DGs" { - Credential = $Credscredential; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint Ensure = "Present"; Exclusive = $False; Identity = "Test New DGs"; @@ -103,7 +105,9 @@ Configuration Example { EXOManagementScope "EXOManagementScope-Test New DGs" { - Credential = $Credscredential; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint Ensure = "Present"; Exclusive = $False; Identity = "Test New DGs"; @@ -140,7 +144,9 @@ Configuration Example { EXOManagementScope "EXOManagementScope-Test New DGs" { - Credential = $Credscredential; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint Ensure = "Absent"; Exclusive = $False; Identity = "Test New DGs"; diff --git a/docs/docs/resources/exchange/EXOMigrationEndpoint.md b/docs/docs/resources/exchange/EXOMigrationEndpoint.md new file mode 100644 index 0000000000..e8a3134503 --- /dev/null +++ b/docs/docs/resources/exchange/EXOMigrationEndpoint.md @@ -0,0 +1,189 @@ +# EXOMigrationEndpoint + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Identity** | Key | String | Identity of the migration endpoint. | | +| **AcceptUntrustedCertificates** | Write | Boolean | Specifies whether to accept untrusted certificates. | | +| **AppID** | Write | String | The Application ID used for authentication. | | +| **AppSecretKeyVaultUrl** | Write | String | The URL of the Key Vault that stores the application secret. | | +| **Authentication** | Write | String | The authentication method for the migration endpoint. | | +| **EndpointType** | Write | String | The type of migration endpoint. | `IMAP` | +| **ExchangeServer** | Write | String | The Exchange Server address for the migration endpoint. | | +| **MailboxPermission** | Write | String | The mailbox permission for the migration endpoint. | | +| **MaxConcurrentIncrementalSyncs** | Write | String | The maximum number of concurrent incremental syncs. | | +| **MaxConcurrentMigrations** | Write | String | The maximum number of concurrent migrations. | | +| **NspiServer** | Write | String | The NSPI server for the migration endpoint. | | +| **Port** | Write | String | The port number for the migration endpoint. | | +| **RemoteServer** | Write | String | The remote server for the migration endpoint. | | +| **RemoteTenant** | Write | String | The remote tenant for the migration endpoint. | | +| **RpcProxyServer** | Write | String | The RPC proxy server for the migration endpoint. | | +| **Security** | Write | String | The security level for the migration endpoint. | `None`, `Tls`, `Ssl` | +| **SourceMailboxLegacyDN** | Write | String | The legacy distinguished name of the source mailbox. | | +| **UseAutoDiscover** | Write | Boolean | Specifies whether to use AutoDiscover. | | +| **Ensure** | Write | String | Specifies if the migration endpoint should exist or not. | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Use this resource to create and monitor migration endpoints in exchange. + +## Permissions + +### Exchange + +To authenticate with Microsoft Exchange, this resource required the following permissions: + +#### Roles + +- Recipient Policies, View-Only Recipients, Mail Recipient Creation, View-Only Configuration, Mail Recipients + +#### Role Groups + +- Organization Management + +## Examples + +### Example 1 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOMigrationEndpoint "EXOMigrationEndpoint-testIMAP" + { + AcceptUntrustedCertificates = $True; + Authentication = "Basic"; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + EndpointType = "IMAP"; + Ensure = "Present"; + Identity = "testIMAP"; + MailboxPermission = "Admin"; + MaxConcurrentIncrementalSyncs = "10"; + MaxConcurrentMigrations = "20"; + Port = 993; + RemoteServer = "gmail.com"; + Security = "Tls"; + } + } +} +``` + +### Example 2 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOMigrationEndpoint "EXOMigrationEndpoint-testIMAP" + { + AcceptUntrustedCertificates = $True; + Authentication = "Basic"; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + EndpointType = "IMAP"; + Ensure = "Present"; + Identity = "testIMAP"; + MailboxPermission = "Admin"; + MaxConcurrentIncrementalSyncs = "10"; + MaxConcurrentMigrations = "20"; + Port = 993; + RemoteServer = "gmail.com"; + # value for security updated from Tls to None + Security = "None"; + } + } +} +``` + +### Example 3 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOMigrationEndpoint "EXOMigrationEndpoint-testIMAP" + { + AcceptUntrustedCertificates = $True; + Authentication = "Basic"; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + EndpointType = "IMAP"; + Ensure = "Absent"; + Identity = "testIMAP"; + MailboxPermission = "Admin"; + MaxConcurrentIncrementalSyncs = "10"; + MaxConcurrentMigrations = "20"; + Port = 993; + RemoteServer = "gmail.com"; + Security = "None"; + } + } +} +``` + From 41aae4d7cd37d35a9183db987162b6453efd664b Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Sat, 5 Oct 2024 19:37:41 +0000 Subject: [PATCH 064/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 39930e9bbd..7bbcdaf2d8 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -12484,6 +12484,136 @@ } ] }, + { + "ClassName": "MSFT_EXOMigrationEndpoint", + "Parameters": [ + { + "CIMType": "String", + "Name": "Identity", + "Option": "Key" + }, + { + "CIMType": "Boolean", + "Name": "AcceptUntrustedCertificates", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AppID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AppSecretKeyVaultUrl", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Authentication", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "EndpointType", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ExchangeServer", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MailboxPermission", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MaxConcurrentIncrementalSyncs", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MaxConcurrentMigrations", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "NspiServer", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Port", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "RemoteServer", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "RemoteTenant", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "RpcProxyServer", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Security", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "SourceMailboxLegacyDN", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "UseAutoDiscover", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_EXOMobileDeviceMailboxPolicy", "Parameters": [ From b4d8b9be5ff50bda8375ac9b5a91dc3e44bfd7c0 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Sat, 5 Oct 2024 19:38:00 +0000 Subject: [PATCH 065/252] Updated {Create} EXO Integration Tests --- .../M365DSCIntegration.EXO.Create.Tests.ps1 | 43 ++++++++++++++----- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 index f69b8d3f89..ab1e4fab0a 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 @@ -411,10 +411,12 @@ } EXOMailboxFolderPermission 'EXOMailboxFolderPermission-admin:\Calendar' { - Credential = $Credscredential; - Ensure = "Present"; - Identity = "amdin:\Calendar"; - UserPermissions = @(MSFT_EXOMailboxFolderUserPermission { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Present"; + Identity = "amdin:\Calendar"; + UserPermissions = @(MSFT_EXOMailboxFolderUserPermission { User = 'Default' AccessRights = 'AvailabilityOnly' } @@ -431,11 +433,13 @@ } EXOMailboxIRMAccess 'EXOMailboxIRMAccess-qwe@testorg.onmicrosoft.com' { - AccessLevel = "Block"; - Credential = $Credscredential; - Ensure = "Present"; - Identity = "qwe@$OrganizationName"; - User = "admin@$OrganizationName"; + AccessLevel = "Block"; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Present"; + Identity = "qwe@$OrganizationName"; + User = "admin@$OrganizationName"; } EXOMailContact 'TestMailContact' { @@ -508,7 +512,9 @@ } EXOManagementScope 'EXOManagementScope-Test New DGs' { - Credential = $Credscredential; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint Ensure = "Present"; Exclusive = $False; Identity = "Test New DGs"; @@ -530,6 +536,23 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXOMigrationEndpoint 'EXOMigrationEndpoint-testIMAP' + { + AcceptUntrustedCertificates = $True; + Authentication = "Basic"; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + EndpointType = "IMAP"; + Ensure = "Present"; + Identity = "testIMAP"; + MailboxPermission = "Admin"; + MaxConcurrentIncrementalSyncs = "10"; + MaxConcurrentMigrations = "20"; + Port = 993; + RemoteServer = "gmail.com"; + Security = "Tls"; + } EXOMobileDeviceMailboxPolicy 'ConfigureMobileDeviceMailboxPolicy' { Name = "Default" From 82bbfa1986c258e09cc62ffbcfbd52128a08bcf5 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Sat, 5 Oct 2024 19:38:31 +0000 Subject: [PATCH 066/252] Updated {Update} EXO Integration Tests --- .../M365DSCIntegration.EXO.Update.Tests.ps1 | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 index bae977e5b8..4a382c8f63 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 @@ -679,10 +679,12 @@ } EXOMailboxFolderPermission 'EXOMailboxFolderPermission-admin:\Calendar' { - Credential = $Credscredential; - Ensure = "Present"; - Identity = "admin:\Calendar"; - UserPermissions = @(MSFT_EXOMailboxFolderUserPermission { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Present"; + Identity = "admin:\Calendar"; + UserPermissions = @(MSFT_EXOMailboxFolderUserPermission { User = 'Default' AccessRights = 'AvailabilityOnly' } @@ -825,7 +827,9 @@ } EXOManagementScope 'EXOManagementScope-Test New DGs' { - Credential = $Credscredential; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint Ensure = "Present"; Exclusive = $False; Identity = "Test New DGs"; @@ -847,6 +851,24 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXOMigrationEndpoint 'EXOMigrationEndpoint-testIMAP' + { + AcceptUntrustedCertificates = $True; + Authentication = "Basic"; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + EndpointType = "IMAP"; + Ensure = "Present"; + Identity = "testIMAP"; + MailboxPermission = "Admin"; + MaxConcurrentIncrementalSyncs = "10"; + MaxConcurrentMigrations = "20"; + Port = 993; + RemoteServer = "gmail.com"; + # value for security updated from Tls to None + Security = "None"; + } EXOMobileDeviceMailboxPolicy 'ConfigureMobileDeviceMailboxPolicy' { Name = "Default" From f81045915a0e3ef8f04fb91953671fd66f7fd340 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Sat, 5 Oct 2024 19:38:54 +0000 Subject: [PATCH 067/252] Updated {Update} EXO Integration Tests --- .../M365DSCIntegration.EXO.Remove.Tests.ps1 | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 index 331165c9c1..9e231050c0 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 @@ -340,7 +340,9 @@ } EXOManagementScope 'EXOManagementScope-Test New DGs' { - Credential = $Credscredential; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint Ensure = "Absent"; Exclusive = $False; Identity = "Test New DGs"; @@ -357,6 +359,23 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXOMigrationEndpoint 'EXOMigrationEndpoint-testIMAP' + { + AcceptUntrustedCertificates = $True; + Authentication = "Basic"; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + EndpointType = "IMAP"; + Ensure = "Absent"; + Identity = "testIMAP"; + MailboxPermission = "Admin"; + MaxConcurrentIncrementalSyncs = "10"; + MaxConcurrentMigrations = "20"; + Port = 993; + RemoteServer = "gmail.com"; + Security = "None"; + } EXOMobileDeviceMailboxPolicy 'ConfigureMobileDeviceMailboxPolicy' { Name = "Default" From 1184dcde5837c0dd594454019bb6d404b180aa5d Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Sat, 5 Oct 2024 16:53:04 -0700 Subject: [PATCH 068/252] Draft Intune DSC Derived Credential --- .../MSFT_IntuneDerivedCredential.psm1 | 364 ++++++++++++++++++ .../MSFT_IntuneDeviceCredential.schema.mof | 11 + .../MSFT_IntuneDerivedCredential/readme.md | 6 + .../settings.json | 32 ++ .../IntuneDerivedCredential/1-Create.ps1 | 36 ++ .../IntuneDerivedCredential/2-Update.ps1 | 36 ++ .../IntuneDerivedCredential/3-Remove.ps1 | 36 ++ ...ft365DSC.IntuneDerivedCredential.Tests.ps1 | 197 ++++++++++ 8 files changed, 718 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDeviceCredential.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDerivedCredential.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.psm1 new file mode 100644 index 0000000000..20481c9360 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.psm1 @@ -0,0 +1,364 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter()] + [System.String] + $Id, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $HelpUrl, + + [Parameter(Mandatory=$true)] + [ValidateSet('intercede', 'entrust', 'disa purebred')] + [System.String] + $Issuer, + + [Parameter(Mandatory=$true)] + [ValidateSet('email', 'Company Portal (iOS) Microsoft Intune (Android) app')] + [System.String] + $NotificationType, + + [Parameter()] + [System.Int32] + $ThresholdPercentage, + + [Parameter()] + [System.String] + $Header + ) + + New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters | Out-Null + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + try + { + $instance = $null + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Id -eq $Id} + } + if ($null -eq $instance) + { + $instance = Get-MgBetaDeviceManagementDerivedCredential DerivedCredentialId $Id -ErrorAction Stop + + if ($null -eq $instance) + { + Write-Verbose -Message "Could not find DerivedCredential by Id {$Id}." + + if (-Not [string]::IsNullOrEmpty($DisplayName)) + { + $instance = Get-MgBetaDeviceManagementDerivedCredential ` + -Filter "DisplayName eq '$DisplayName'" ` + -ErrorAction SilentlyContinue + } + } + } + if ($null -eq $instance) + { + Write-Verbose -Message "Could not find DerivedCredential by DisplayName {$DisplayName}." + return $nullResult + } + + $results = @{ + Ensure = 'Present' + Id = $instance.Id + DisplayName = $instance.DisplayName + HelpUrl = $HelpUrl + Issuer = $Issuer + NotificationType = $NotificationType + ThresholdPercentage = $ThresholdPercentage + Header = $Header + + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $Id, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $HelpUrl, + + [Parameter(Mandatory=$true)] + [ValidateSet('intercede', 'entrust', 'disa purebred')] + [System.String] + $Issuer, + + [Parameter(Mandatory=$true)] + [ValidateSet('email', 'Company Portal (iOS) Microsoft Intune (Android) app')] + [System.String] + $NotificationType, + + [Parameter()] + [System.Int32] + $ThresholdPercentage, + + [Parameter()] + [System.String] + $Header + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + New-MgBetaDeviceManagementDerivedCredential @SetParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Update-MgBetaDeviceManagementDerivedCredential @SetParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Remove-MgBetaDeviceManagementDerivedCredential @SetParameters + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter()] + [System.String] + $Id, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $HelpUrl, + + [Parameter(Mandatory=$true)] + [ValidateSet('intercede', 'entrust', 'disa purebred')] + [System.String] + $Issuer, + + [Parameter(Mandatory=$true)] + [ValidateSet('email', 'Company Portal (iOS) Microsoft Intune (Android) app')] + [System.String] + $NotificationType, + + [Parameter()] + [System.Int32] + $ThresholdPercentage, + + [Parameter()] + [System.String] + $Header + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.String] + $Id, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $HelpUrl, + + [Parameter(Mandatory=$true)] + [ValidateSet('Intercede', 'Entrust', 'DISA Purebred')] + [System.String] + $Issuer, + + [Parameter(Mandatory=$true)] + [ValidateSet('Email', 'Company Portal (iOS) Microsoft Intune (Android) app')] + [System.String] + $NotificationType, + + [Parameter()] + [System.Int32] + $ThresholdPercentage, + + [Parameter()] + [System.Collections.IDictionary] + $Header + + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-MgBetaDeviceManagementDerivedCredential -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + $displayedKey = $config.Id + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $results = @{ + Ensure = 'Present' + Id = $instance.Id + DisplayName = $instance.DisplayName + HelpUrl = $HelpUrl + Issuer = $Issuer + NotificationType = $NotificationType + ThresholdPercentage = $ThresholdPercentage + Header = $Header + + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDeviceCredential.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDeviceCredential.schema.mof new file mode 100644 index 0000000000..c2940b1f3a --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDeviceCredential.schema.mof @@ -0,0 +1,11 @@ +[ClassVersion("1.0.0.0"), FriendlyName("IntuneDeviceCredential")] +class MSFT_IntuneDeviceCredential : OMI_BaseResource +{ + [Key, Description("The name of the app category.")] String DisplayName; + [Write, Description("The unique identifier for an entity. Read-only.")] String Id; + [Write, Description("The URL that will be accessible to end users as they retrieve a derived credential using the Company Portal.")] String HelpUrl; + [Write, Description("Supported values for the derived credential issuer."), ValueMap{"Intercede", "Entrust", "DISA Purebred"}, Values{"Intercede", "Entrust", "DISA Purebred"}] String Issuer; + [Write, Description("Supported values for the notification type to use."), ValueMap{"Email", "Company Portal (iOS) Microsoft Intune (Android) app"}, Values{"Email", "Company Portal (iOS) Microsoft Intune (Android) app"}] String NotificationType; + [Write, Description("The nominal percentage of time before certificate renewal is initiated by the client.")] uint32 ThresholdPercentage; + [Write, Description("Optional headers that will be added to the request.")] KeyValuePair[] Header; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/readme.md new file mode 100644 index 0000000000..5fb6aed2fe --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/readme.md @@ -0,0 +1,6 @@ + +# IntuneDerivedCredential + +## Description + +##Create new navigation property to derivedCredentials for deviceManagement diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/settings.json new file mode 100644 index 0000000000..a9201e88c8 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName": "IntuneDerivedCredential", + "description": "Use this resource to create new navigation property to derivedCredentials for deviceManagement", + "roles": { + "read": [ + "Role" + ], + "update": [ + "Role" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [ + { + "name": "Permission for Monitoring and Export" + } + ], + "update": [ + { + "name": "Permission for deploying" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/1-Create.ps1 new file mode 100644 index 0000000000..aa0fbaec31 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/1-Create.ps1 @@ -0,0 +1,36 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + IntuneDerivedCredential "IntuneDerivedCredential-Data Management" + { + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Custom Data Management"; + Ensure = "Present"; + HelpUrl = "https://www.microsoft.com"; + Issuer = "DISA Purebred"; + NotificationType = "Email"; + ThresholdPercentage = 0; + } + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/2-Update.ps1 new file mode 100644 index 0000000000..aa0fbaec31 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/2-Update.ps1 @@ -0,0 +1,36 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + IntuneDerivedCredential "IntuneDerivedCredential-Data Management" + { + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Custom Data Management"; + Ensure = "Present"; + HelpUrl = "https://www.microsoft.com"; + Issuer = "DISA Purebred"; + NotificationType = "Email"; + ThresholdPercentage = 0; + } + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/3-Remove.ps1 new file mode 100644 index 0000000000..aa0fbaec31 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/3-Remove.ps1 @@ -0,0 +1,36 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + IntuneDerivedCredential "IntuneDerivedCredential-Data Management" + { + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Custom Data Management"; + Ensure = "Present"; + HelpUrl = "https://www.microsoft.com"; + Issuer = "DISA Purebred"; + NotificationType = "Email"; + ThresholdPercentage = 0; + } + + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDerivedCredential.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDerivedCredential.Tests.ps1 new file mode 100644 index 0000000000..1df65bd189 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDerivedCredential.Tests.ps1 @@ -0,0 +1,197 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -GenericStubModule $GenericStubPath + +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + + Mock -CommandName Get-MgBetaDeviceManagementDerivedCredentialy -MockWith { + } + Mock -CommandName New-MgBetaDeviceManagementDerivedCredential -MockWith { + } + Mock -CommandName Update-MgBetaDeviceManagementDerivedCredential -MockWith { + } + Mock -CommandName Remove-MgBetaDeviceManagementDerivedCredential -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + Context -Name "The instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + Ensure = 'Present' + Id = $instance.Id + DisplayName = $instance.DisplayName + HelpUrl = $HelpUrl + Issuer = $Issuer + NotificationType = $NotificationType + ThresholdPercentage = $ThresholdPercentage + Header = $Header + } + + Mock -CommandName Get-MgBetaDeviceManagementDerivedCredential -MockWith { + return $null + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should create a new instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-MgBetaDeviceManagementDerivedCredential -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + Ensure = 'Present' + Id = $instance.Id + DisplayName = $instance.DisplayName + HelpUrl = $HelpUrl + Issuer = $Issuer + NotificationType = $NotificationType + ThresholdPercentage = $ThresholdPercentage + Header = $Header + } + + Mock -CommandName Get-MgBetaDeviceManagementDerivedCredential -MockWith { + return @{ + + } + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should remove the instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-MgBetaDeviceManagementDerivedCredential -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Ensure = 'Present' + Id = $instance.Id + DisplayName = $instance.DisplayName + HelpUrl = $HelpUrl + Issuer = $Issuer + NotificationType = $NotificationType + ThresholdPercentage = $ThresholdPercentage + Header = $Header + } + + Mock -CommandName Get-MgBetaDeviceManagementDerivedCredential -MockWith { + return @{ + + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Ensure = 'Present' + Id = $instance.Id + DisplayName = $instance.DisplayName + HelpUrl = $HelpUrl + Issuer = $Issuer + NotificationType = $NotificationType + ThresholdPercentage = $ThresholdPercentage + Header = $Header + } + + Mock -CommandName Get-MgBetaDeviceManagementDerivedCredential -MockWith { + return @{ + + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Update-MgBetaDeviceManagementDerivedCredential -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDeviceManagementDerivedCredential -MockWith { + return @{ + + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope From 169384cd4942ff11659b6467d8d4bfb73316fd4f Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Sat, 5 Oct 2024 19:27:31 -0700 Subject: [PATCH 069/252] Draft Intune DSC Derived Credential --- .../settings.json | 64 ++++++++++--------- .../MSFT_IntuneDeviceCredential.schema.mof | 39 ++++++++--- .../IntuneDerivedCredential/1-Create.ps1 | 45 ++++++------- .../IntuneDerivedCredential/2-Update.ps1 | 45 ++++++------- .../IntuneDerivedCredential/3-Remove.ps1 | 46 ++++++------- 5 files changed, 126 insertions(+), 113 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMessageClassification/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMessageClassification/settings.json index 4096c4ae40..d91fe2f2da 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMessageClassification/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMessageClassification/settings.json @@ -1,34 +1,40 @@ { - "resourceName": "EXOMessageClassification", - "description": "", - "roles": { - "read": [ - "Global Reader" - ], - "update": [ - "Exchange Administrator" - ] - }, + "resourceName": "IntuneDerivedCredential", + "description": "Use this resource to create new navigation property to derivedCredentials for deviceManagement", + // "roles": { + // "read": [ + // "Global Reader" + // ], + // "update": [ + // "Intune Administrator" + // ] + // }, + "permissions": { - "graph": { - "delegated": { - "read": [], - "update": [] - }, - "application": { - "read": [], - "update": [] - } + "graph": { + "delegated": { + "read": [ + "DeviceManagementConfiguration.Read.All" + ], + "update": [ + "DeviceManagementConfiguration.ReadWrite.All" + ] }, - "exchange": { - "requiredroles": [ - "User Options", - "Data Loss Prevention", - "Transport Rules", - "View-Only Configuration", - "Mail Recipients" - ], - "requiredrolegroups": "Organization Management" + "application": { + "read": [ + "DeviceManagementConfiguration.Read.All" + ], + "update": [ + "DeviceManagementConfiguration.ReadWrite.All" + ] } + } } -} + } + +// PS C:\Windows\system32> Find-MgGraphCommand -Command “Get-MgBetaDeviceManagementDerivedCredential” | select Permissions + // OUTPUT: + // Permissions + // ----------- + // {} + // {} diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDeviceCredential.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDeviceCredential.schema.mof index c2940b1f3a..4f5994242a 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDeviceCredential.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDeviceCredential.schema.mof @@ -1,11 +1,32 @@ +[ClassVersion("1.0.0.0"), Description("Represents a key-value pair.")] +class KeyValuePair { + [Key, Description("The key of the dictionary entry.")] + string Key; + + [Description("The value of the dictionary entry.")] + string Value; +}; + [ClassVersion("1.0.0.0"), FriendlyName("IntuneDeviceCredential")] -class MSFT_IntuneDeviceCredential : OMI_BaseResource -{ - [Key, Description("The name of the app category.")] String DisplayName; - [Write, Description("The unique identifier for an entity. Read-only.")] String Id; - [Write, Description("The URL that will be accessible to end users as they retrieve a derived credential using the Company Portal.")] String HelpUrl; - [Write, Description("Supported values for the derived credential issuer."), ValueMap{"Intercede", "Entrust", "DISA Purebred"}, Values{"Intercede", "Entrust", "DISA Purebred"}] String Issuer; - [Write, Description("Supported values for the notification type to use."), ValueMap{"Email", "Company Portal (iOS) Microsoft Intune (Android) app"}, Values{"Email", "Company Portal (iOS) Microsoft Intune (Android) app"}] String NotificationType; - [Write, Description("The nominal percentage of time before certificate renewal is initiated by the client.")] uint32 ThresholdPercentage; - [Write, Description("Optional headers that will be added to the request.")] KeyValuePair[] Header; +class MSFT_IntuneDeviceCredential : OMI_BaseResource { + [Key, Description("The name of the app category.")] + string DisplayName; + + [Write, Description("The unique identifier for an entity. Read-only.")] + string Id; + + [Write, Description("The URL that will be accessible to end users as they retrieve a derived credential using the Company Portal.")] + string HelpUrl; + + [Write, Description("Supported values for the derived credential issuer."), ValueMap{"Intercede", "Entrust", "DISA Purebred"}, Values{"Intercede", "Entrust", "DISA Purebred"}] + string Issuer; + + [Write, Description("Supported values for the notification type to use."), ValueMap{"Email", "Company Portal (iOS) Microsoft Intune (Android) app"}, Values{"Email", "Company Portal (iOS) Microsoft Intune (Android) app"}] + string NotificationType; + + [Write, Description("The nominal percentage of time before certificate renewal is initiated by the client.")] + uint32 ThresholdPercentage; + + [Write, Description("Optional headers that will be added to the request.")] + KeyValuePair[] Header; }; diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/1-Create.ps1 index aa0fbaec31..07f1840e08 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/1-Create.ps1 @@ -1,36 +1,31 @@ -<# -This example is used to test new resources and showcase the usage of new resources being worked on. -It is not meant to use as a production baseline. -#> - -Configuration Example -{ +<# This example is used to test new resources and showcase the usage of new resources being worked on. It is not meant to use as a production baseline. #> +Configuration Example { param( [Parameter()] - [System.String] - $ApplicationId, + [System.String] $ApplicationId, [Parameter()] - [System.String] - $TenantId, + [System.String] $TenantId, [Parameter()] - [System.String] - $CertificateThumbprint + [System.String] $CertificateThumbprint ) + Import-DscResource -ModuleName Microsoft365DSC - node localhost - { - IntuneDerivedCredential "IntuneDerivedCredential-Data Management" - { - Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Custom Data Management"; - Ensure = "Present"; - HelpUrl = "https://www.microsoft.com"; - Issuer = "DISA Purebred"; - NotificationType = "Email"; - ThresholdPercentage = 0; - } + node localhost { + IntuneDerivedCredential "IntuneDerivedCredential-DataManagement" { + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606" + DisplayName = "Custom Data Management" + Ensure = "Present" + HelpUrl = "https://www.microsoft.com" + Issuer = "DISA Purebred" + NotificationType = "Email" + ThresholdPercentage = 0 + Header = @( + [PSCustomObject]@{ Key = 'HeaderKey1'; Value = 'HeaderValue1' } + [PSCustomObject]@{ Key = 'HeaderKey2'; Value = 'HeaderValue2' } + ) + } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/2-Update.ps1 index aa0fbaec31..07f1840e08 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/2-Update.ps1 @@ -1,36 +1,31 @@ -<# -This example is used to test new resources and showcase the usage of new resources being worked on. -It is not meant to use as a production baseline. -#> - -Configuration Example -{ +<# This example is used to test new resources and showcase the usage of new resources being worked on. It is not meant to use as a production baseline. #> +Configuration Example { param( [Parameter()] - [System.String] - $ApplicationId, + [System.String] $ApplicationId, [Parameter()] - [System.String] - $TenantId, + [System.String] $TenantId, [Parameter()] - [System.String] - $CertificateThumbprint + [System.String] $CertificateThumbprint ) + Import-DscResource -ModuleName Microsoft365DSC - node localhost - { - IntuneDerivedCredential "IntuneDerivedCredential-Data Management" - { - Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Custom Data Management"; - Ensure = "Present"; - HelpUrl = "https://www.microsoft.com"; - Issuer = "DISA Purebred"; - NotificationType = "Email"; - ThresholdPercentage = 0; - } + node localhost { + IntuneDerivedCredential "IntuneDerivedCredential-DataManagement" { + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606" + DisplayName = "Custom Data Management" + Ensure = "Present" + HelpUrl = "https://www.microsoft.com" + Issuer = "DISA Purebred" + NotificationType = "Email" + ThresholdPercentage = 0 + Header = @( + [PSCustomObject]@{ Key = 'HeaderKey1'; Value = 'HeaderValue1' } + [PSCustomObject]@{ Key = 'HeaderKey2'; Value = 'HeaderValue2' } + ) + } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/3-Remove.ps1 index aa0fbaec31..a6c927219e 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/3-Remove.ps1 @@ -1,36 +1,32 @@ -<# -This example is used to test new resources and showcase the usage of new resources being worked on. -It is not meant to use as a production baseline. -#> - -Configuration Example -{ +<# This example is used to test new resources and showcase the usage of new resources being worked on. It is not meant to use as a production baseline. #> +Configuration Example { param( [Parameter()] - [System.String] - $ApplicationId, + [System.String] $ApplicationId, [Parameter()] - [System.String] - $TenantId, + [System.String] $TenantId, [Parameter()] - [System.String] - $CertificateThumbprint + [System.String] $CertificateThumbprint ) + Import-DscResource -ModuleName Microsoft365DSC - node localhost - { - IntuneDerivedCredential "IntuneDerivedCredential-Data Management" - { - Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Custom Data Management"; - Ensure = "Present"; - HelpUrl = "https://www.microsoft.com"; - Issuer = "DISA Purebred"; - NotificationType = "Email"; - ThresholdPercentage = 0; - } + node localhost { + IntuneDerivedCredential "IntuneDerivedCredential-DataManagement" { + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606" + DisplayName = "Custom Data Management" + Ensure = "Present" + HelpUrl = "https://www.microsoft.com" + Issuer = "DISA Purebred" + NotificationType = "Email" + ThresholdPercentage = 0 + Header = @( + [PSCustomObject]@{ Key = 'HeaderKey1'; Value = 'HeaderValue1' } + [PSCustomObject]@{ Key = 'HeaderKey2'; Value = 'HeaderValue2' } + ) + } } } + From 0bc12921b89a47d2d6258eac8b8ca1bb39ea08d2 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Sat, 5 Oct 2024 20:01:31 -0700 Subject: [PATCH 070/252] Draft Intune DSC Derived Credential --- .../settings.json | 64 +++++++++---------- .../MSFT_IntuneDerivedCredential.psm1 | 6 +- .../settings.json | 60 +++++++++-------- 3 files changed, 66 insertions(+), 64 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMessageClassification/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMessageClassification/settings.json index d91fe2f2da..4096c4ae40 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMessageClassification/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMessageClassification/settings.json @@ -1,40 +1,34 @@ { - "resourceName": "IntuneDerivedCredential", - "description": "Use this resource to create new navigation property to derivedCredentials for deviceManagement", - // "roles": { - // "read": [ - // "Global Reader" - // ], - // "update": [ - // "Intune Administrator" - // ] - // }, - + "resourceName": "EXOMessageClassification", + "description": "", + "roles": { + "read": [ + "Global Reader" + ], + "update": [ + "Exchange Administrator" + ] + }, "permissions": { - "graph": { - "delegated": { - "read": [ - "DeviceManagementConfiguration.Read.All" - ], - "update": [ - "DeviceManagementConfiguration.ReadWrite.All" - ] + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } }, - "application": { - "read": [ - "DeviceManagementConfiguration.Read.All" - ], - "update": [ - "DeviceManagementConfiguration.ReadWrite.All" - ] + "exchange": { + "requiredroles": [ + "User Options", + "Data Loss Prevention", + "Transport Rules", + "View-Only Configuration", + "Mail Recipients" + ], + "requiredrolegroups": "Organization Management" } - } } - } - -// PS C:\Windows\system32> Find-MgGraphCommand -Command “Get-MgBetaDeviceManagementDerivedCredential” | select Permissions - // OUTPUT: - // Permissions - // ----------- - // {} - // {} +} diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.psm1 index 20481c9360..874df581fe 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.psm1 @@ -31,7 +31,7 @@ function Get-TargetResource $ThresholdPercentage, [Parameter()] - [System.String] + [System.Collections.IDictionary] $Header ) @@ -139,7 +139,7 @@ function Set-TargetResource $ThresholdPercentage, [Parameter()] - [System.String] + [System.Collections.IDictionary] $Header ) @@ -209,7 +209,7 @@ function Test-TargetResource $ThresholdPercentage, [Parameter()] - [System.String] + [System.Collections.IDictionary] $Header ) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/settings.json index a9201e88c8..f4606a14af 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/settings.json @@ -1,32 +1,40 @@ { "resourceName": "IntuneDerivedCredential", "description": "Use this resource to create new navigation property to derivedCredentials for deviceManagement", - "roles": { - "read": [ - "Role" - ], - "update": [ - "Role" - ] - }, + // "roles": { + // "read": [ + // "Global Reader" + // ], + // "update": [ + // "Intune Administrator" + // ] + // }, + "permissions": { - "graph": { - "delegated": { - "read": [], - "update": [] - }, - "application": { - "read": [ - { - "name": "Permission for Monitoring and Export" - } - ], - "update": [ - { - "name": "Permission for deploying" - } - ] - } + "graph": { + "delegated": { + "read": [ + "DeviceManagementConfiguration.Read.All" + ], + "update": [ + "DeviceManagementConfiguration.ReadWrite.All" + ] + }, + "application": { + "read": [ + "DeviceManagementConfiguration.Read.All" + ], + "update": [ + "DeviceManagementConfiguration.ReadWrite.All" + ] } + } } -} + } + +// PS C:\Windows\system32> Find-MgGraphCommand -Command “Get-MgBetaDeviceManagementDerivedCredential” | select Permissions + // OUTPUT: + // Permissions + // ----------- + // {} + // {} From bee771d1420f0e3151b954cf30eca9ad273b9fcb Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Sat, 5 Oct 2024 20:17:46 -0700 Subject: [PATCH 071/252] Export childApp is working, but m365config is yet to compile. --- .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 251 +++++++++--------- ...SFT_IntuneMobileAppsMacOSLobApp.schema.mof | 10 + ...5DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 | 10 +- Tests/Unit/Stubs/Microsoft365.psm1 | 24 +- 4 files changed, 158 insertions(+), 137 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 index 0d66ba41d6..efc9da67fa 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 @@ -68,8 +68,8 @@ function Get-TargetResource $Assignments, [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance] - $LargeIcon, + [Microsoft.Management.Infrastructure.CimInstance[]] + $ChildApps, #endregion @@ -128,19 +128,19 @@ function Get-TargetResource try { $instance = Get-MgBetaDeviceAppManagementMobileApp ` - -Filter "(isof('microsoft.graph.macOSLobApp') and displayName eq '$DisplayName')" ` - -ExpandProperty "categories,assignments" ` - -ErrorAction SilentlyContinue | Where-Object ` - -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.macOSLobApp' } + -Filter "(isof('microsoft.graph.macOSLobApp') and displayName eq '$DisplayName')" + # -ExpandProperty "categories,assignments" ` + # -ErrorAction SilentlyContinue | Where-Object ` + # -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.macOSLobApp' } if ($null -eq $instance) { Write-Verbose -Message "No Mobile app with DisplayName {$DisplayName} was found. Search with DisplayName." $instance = Get-MgBetaDeviceAppManagementMobileApp ` - -MobileAppId $Id ` - -ExpandProperty "categories,assignments" ` - -ErrorAction Stop | Where-Object ` - -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.macOSLobApp' } + -MobileAppId $Id + # -ExpandProperty "categories,assignments" ` + # -ErrorAction Stop | Where-Object ` + # -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.macOSLobApp' } } if ($null -eq $instance) @@ -151,7 +151,6 @@ function Get-TargetResource Write-Verbose -Message "Found Mobile app with {$DisplayName}." - $results = @{ Id = $instance.Id Description = $instance.Description @@ -165,8 +164,8 @@ function Get-TargetResource Publisher = $instance.Publisher PublishingState = $instance.PublishingState.ToString() RoleScopeTagIds = $instance.RoleScopeTagIds - # LargeIcon = $instance.LargeIcon IgnoreVersionDetection = $instance.AdditionalProperties.ignoreVersionDetection + #ChildApps = $instance.AdditionalProperties.childApps Ensure = 'Present' Credential = $Credential @@ -189,6 +188,25 @@ function Get-TargetResource $results.Add('Categories', "") } + #childApps + Write-Host ".............................." + Write-Host "Get- start childApps.............................." $instance.DisplayName + if($null -ne $instance.AdditionalProperties.childApps) + { + foreach ($childApp in $instance.AdditionalProperties.childApps) + { + Write-Host "Get- print childApps.............................." $childApp.bundleId + Write-Host "Get- print childApps.............................." $childApp.buildNumber + Write-Host "Get- print childApps.............................." $childApp.versionNumber + } + + $results.Add('ChildApps', $instance.AdditionalProperties.childApps) + } + else { + Write-Host "Get- print childApps null.............................." + $results.Add('ChildApps', "") + } + #Assignments $resultAssignments = @() $appAssignments = Get-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $instance.Id @@ -201,23 +219,6 @@ function Get-TargetResource $results.Add('Assignments', $resultAssignments) } - #LargeIcon - - # The large is returned only when Get cmdlet is called with Id parameter. The large icon is a base64 encoded string, so we need to convert it to a byte array. - $instanceWithLargeIcon = Get-MgBetaDeviceAppManagementMobileApp -MobileAppId $instance.Id - - - #$LargeIcon.Type = $typeLargeIconType - #$LargeIcon.Value = $base64LargeIconStringValue - - if($null -ne $instanceWithLargeIcon.LargeIcon) - { - $results.Add('LargeIcon', $instanceWithLargeIcon.LargeIcon) - } - else { - $results.Add('LargeIcon', "") - } - #end region complex types return [System.Collections.Hashtable] $results @@ -304,8 +305,8 @@ function Set-TargetResource $Assignments, [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance] - $LargeIcon, + [Microsoft.Management.Infrastructure.CimInstance[]] + $ChildApps, #endregion @@ -359,14 +360,14 @@ function Set-TargetResource $currentInstance = Get-TargetResource @PSBoundParameters $PSBoundParameters.Remove('Categories') | Out-Null $PSBoundParameters.Remove('Assignments') | Out-Null - $PSBoundParameters.Remove('LargeIcon') | Out-Null + $PSBoundParameters.Remove('childApps') | Out-Null $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters $setParameters.remove('Id') | Out-Null $setParameters.remove('Ensure') | Out-Null $setParameters.remove('Categories') | Out-Null $setParameters.remove('Assignments') | Out-Null - $setParameters.remove('LargeIcon') | Out-Null + $setParameters.remove('childApps') | Out-Null $AdditionalProperties = Get-M365DSCIntuneMobileMocOSLobAppAdditionalProperties -Properties ([System.Collections.Hashtable]$PSBoundParameters) @@ -377,11 +378,12 @@ function Set-TargetResource $setParameters.Add('Categories', $categoriesValue) } - #LargeIcon - if($null -ne $LargeIcon) + #childApps + if($null -ne $ChildApps) { - [System.Object]$LargeIconValue = ConvertTo-M365DSCIntuneAppLargeIcon -LargeIcon $LargeIcon - $setParameters.Add('LargeIcon', $LargeIconValue) + [System.Object[]]$childAppsValue = ConvertTo-M365DSCIntuneAppChildApps -ChildApps $ChildApps + #$setParameters.Add('ChildApps', $childApps) + $AdditionalProperties.Add('childApps', $childAppsValue) } # CREATE @@ -489,8 +491,8 @@ function Test-TargetResource $Assignments, [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance] - $LargeIcon, + [Microsoft.Management.Infrastructure.CimInstance[]] + $ChildApps, #endregion @@ -683,7 +685,7 @@ function Export-TargetResource PublishingState = $config.PublishingState.ToString() RoleScopeTagIds = $config.RoleScopeTagIds IgnoreVersionDetection = $config.AdditionalProperties.ignoreVersionDetection - # ChildApps = $config.ChildApps + #ChildApps = $config.AdditionalProperties.childApps Ensure = 'Present' Credential = $Credential @@ -715,6 +717,24 @@ function Export-TargetResource $Results.Categories = Get-M365DSCIntuneAppCategoriesAsString -Categories $Results.Categories } + #ChildApps + if($null -eq $Results.childApps -or $Results.childApps.Count -eq 0) + { + Write-Host "Export print childApps: IN IF WHERE CHILD APPS NULL.............................." + } + else + { + Write-Host "Export print childApps: IN ELSE BEFORE FOR LOOP.............................." + foreach ($childApp in $Results.childApps) + { + Write-Host "Export print childApps.............................." $childApp.bundleId + Write-Host "Export print childApps.............................." $childApp.buildNumber + Write-Host "Export print childApps.............................." $childApp.versionNumber + } + + $Results.childApps = Get-M365DSCIntuneAppChildAppsAsString -ChildApps $Results.childApps + } + #Assignments if ($Results.Assignments) { @@ -730,15 +750,6 @@ function Export-TargetResource } } - #LargeIcon - if($Results.LargeIcon) - { - $Results.LargeIcon = Get-M365DSCIntuneAppLargeIconAsString -LargeIcon $Results.LargeIcon - } - else - { - $Results.Remove('LargeIcon') | Out-Null - } #endregion complex types @@ -758,9 +769,9 @@ function Export-TargetResource $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Categories' } - if ($null -ne $Results.LargeIcon) + if ($null -ne $Results.childApps) { - $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'LargeIcon' + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'ChildApps' } if ($Results.Assignments) @@ -770,6 +781,7 @@ function Export-TargetResource { $isCIMArray = $true } + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Assignments' -IsCIMArray:$isCIMArray } @@ -800,36 +812,37 @@ function Export-TargetResource #region Helper functions -function ConvertTo-M365DSCIntuneAppAssignmentSettings +function ConvertTo-M365DSCIntuneAppCategories { [OutputType([System.Object[]])] param( [Parameter(Mandatory = $true)] [System.Collections.ArrayList] - $Settings + $Categories ) $result = @() - foreach ($setting in $Settings) + foreach ($category in $Categories) { - $currentSetting = @{ - name = $setting.odataType - value = $setting.uninstallOnDeviceRemoval + $currentCategory = @{ + id = $category.id + displayName = $category.displayName } - $result += $currentSetting + + $result += $currentCategory } return $result } -function Get-M365DSCIntuneAppAssignmentSettingsAsString +function Get-M365DSCIntuneAppCategoriesAsString { [CmdletBinding()] [OutputType([System.String])] param( [Parameter(Mandatory = $true)] [System.Object[]] - $Settings + $Categories ) $StringContent = '@(' @@ -837,77 +850,59 @@ function Get-M365DSCIntuneAppAssignmentSettingsAsString $indent = ' ' $i = 1 - foreach ($setting in $Settings) + foreach ($category in $Categories) { - if ($Settings.Count -gt 1) + if ($Categories.Count -gt 1) { $StringContent += "`r`n" $StringContent += "$space" } - $StringContent += "MSFT_DeviceManagementMobileAppAssignmentSettings { `r`n" - $StringContent += "$($space)$($indent)odataType = '" + $setting.odataType + "'`r`n" - $StringContent += "$($space)$($indent)uninstallOnDeviceRemoval = '" + $setting.uninstallOnDeviceRemoval + "'`r`n" + $StringContent += "MSFT_DeviceManagementMobileAppCategory { `r`n" + $StringContent += "$($space)$($indent)id = '" + $category.id + "'`r`n" + $StringContent += "$($space)$($indent)displayName = '" + $category.displayName + "'`r`n" $StringContent += "$space}" $i++ } $StringContent += ')' + return $StringContent } -function ConvertTo-M365DSCIntuneAppCategories +function ConvertTo-M365DSCIntuneAppChildApps { [OutputType([System.Object[]])] param( [Parameter(Mandatory = $true)] [System.Collections.ArrayList] - $Categories + $ChildApps ) $result = @() - foreach ($category in $Categories) + foreach ($childApp in $ChildApps) { - $currentCategory = @{ - id = $category.id - displayName = $category.displayName + $currentChildApp = @{ + bundleId = $childApp.bundleId + buildNumber = $childApp.buildNumber + versionNumber = $childApp.VersionNumber } - $result += $currentCategory - } - - return $result -} - -function ConvertTo-M365DSCIntuneAppLargeIcon #set -{ - [OutputType([System.Object])] - param( - [Parameter(Mandatory = $true)] - [System.Object] - $LargeIcon - ) - - #$iconValue = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($LargeIcon.Value)) => throws string to intance conversion error - #$iconValue = [System.Convert]::FromBase64String($LargeIcon.Value) => throws string to intance conversion error - - $result = @{ - type = $LargeIcon.Type - value = $LargeIcon.Value + $result += $currentChildApp } return $result } -function Get-M365DSCIntuneAppCategoriesAsString +function Get-M365DSCIntuneAppChildAppsAsString { [CmdletBinding()] [OutputType([System.String])] param( [Parameter(Mandatory = $true)] [System.Object[]] - $Categories + $ChildApps ) $StringContent = '@(' @@ -915,17 +910,18 @@ function Get-M365DSCIntuneAppCategoriesAsString $indent = ' ' $i = 1 - foreach ($category in $Categories) + foreach ($childApp in $ChildApps) { - if ($Categories.Count -gt 1) + if ($ChildApps.Count -gt 1) { $StringContent += "`r`n" $StringContent += "$space" } - $StringContent += "MSFT_DeviceManagementMobileAppCategory { `r`n" - $StringContent += "$($space)$($indent)id = '" + $category.id + "'`r`n" - $StringContent += "$($space)$($indent)displayName = '" + $category.displayName + "'`r`n" + $StringContent += "MSFT_DeviceManagementMobileAppChildApp { `r`n" + $StringContent += "$($space)$($indent)bundleId = '" + $childApp.bundleId + "'`r`n" + $StringContent += "$($space)$($indent)buildNumber = '" + $childApp.buildNumber + "'`r`n" + $StringContent += "$($space)$($indent)versionNumber = '" + $childApp.versionNumber + "'`r`n" $StringContent += "$space}" $i++ @@ -936,37 +932,6 @@ function Get-M365DSCIntuneAppCategoriesAsString return $StringContent } -function Get-M365DSCIntuneAppLargeIconAsString #Get and export -{ - [CmdletBinding()] - [OutputType([System.String])] - param( - [Parameter(Mandatory = $true)] - [System.Object] - $LargeIcon - ) - - # $StringContent = '@(' - $space = ' ' - $indent = ' ' - - if ($null -ne $LargeIcon) - { - $StringContent += "`r`n" - $StringContent += "$space" - } - - $base64String = [System.Convert]::ToBase64String($LargeIcon.Value) # This exports the base64 string (blob) of the byte array, same as we see in Graph API response - - $StringContent += "MSFT_DeviceManagementMimeContent { `r`n" - $StringContent += "$($space)$($indent)type = '" + $LargeIcon.Type + "'`r`n" - $StringContent += "$($space)$($indent)value = '" + $base64String + "'`r`n" - $StringContent += "$space}" - #$StringContent += ')' - - return $StringContent - } - function Get-M365DSCIntuneMobileMocOSLobAppAdditionalProperties { [CmdletBinding()] @@ -985,7 +950,31 @@ function Get-M365DSCIntuneMobileMocOSLobAppAdditionalProperties { $propertyName = $property[0].ToString().ToLower() + $property.Substring(1, $property.Length - 1) $propertyValue = $properties.$property - $results.Add($propertyName, $propertyValue) + # $results.Add($propertyName, $propertyValue) => handles only singular properties + + if (($propertyValue -is [System.Collections.IEnumerable] -or $propertyValue.count -gt 0) -and -not ($propertyValue -is [string])) + { + # Handle array/collection properties + $processedValues = @() + if($propertyName -eq "childApps" -and $null -ne $propertyValue -and $propertyValue.Count -gt 0) + { + $processChildAppsValues = Get-M365DSCIntuneAppChildAppsAsString -ChildApps $Results.ChildApps + $results.Add($propertyName, $processChildAppsValues) + } + else + { + foreach ($item in $propertyValue) + { + $processedValues += $item + } + + $results.Add($propertyName, $processedValues) + } + } + else { + # Handle singular properties + $results.Add($propertyName, $propertyValue) + } } } return $results diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof index 79830b5199..928dd86028 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof @@ -17,6 +17,9 @@ class MSFT_IntuneMobileAppsMacOSLobApp : OMI_BaseResource [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppCategory")] String Categories[]; + + [Write, Description("The list of child apps for this app package."), EmbeddedInstance("MSFT_DeviceManagementMobileAppChildApp")] ChildApps[]; + [Write, Description("The list of assignments for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppAssignment")] String Assignments[]; [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMimeContent")] String LargeIcon; @@ -44,6 +47,13 @@ class MSFT_DeviceManagementMobileAppCategory [Write, Description("The unique identifier for an entity. Read-only.")] String id; }; +class MSFT_DeviceManagementMobileAppChildApp +{ + [Write, Description("The bundleId of the app.")] String bundleId; + [Write, Description("The build number of the app.")] String buildNumber; + [Write, Description("The version number of the app.")], String versionNumber; +}; + class MSFT_DeviceManagementMobileAppAssignment { [Write, Description("Possible values for the install intent chosen by the admin."), diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 index 716e2c5887..1f0c71c7a5 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 @@ -35,6 +35,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { return "Credentials" } + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { + } Mock -CommandName New-MgBetaDeviceAppManagementMobileApp -MockWith { } Mock -CommandName Update-MgBetaDeviceAppManagementMobileApp -MockWith { @@ -91,7 +93,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "2. The instance exists but it SHOULD NOT" -Fixture { BeforeAll { $testParams = @{ - Id = "8d027f94-0682-431e-97c1-827d1879fa79" + Id = "ad027f94-0682-431e-97c1-827d1879fa79" Description = "TeamsForBusinessInstaller" Developer = "Contoso" DisplayName = "TeamsForBusinessInstaller" @@ -103,6 +105,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Publisher = "Contoso" PublishingState = "published" RoleScopeTagIds = @() + IgnoreVersionDetection = $True Ensure = 'Absent' Credential = $Credential @@ -110,7 +113,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { return @{ - Id = "8d027f94-0682-431e-97c1-827d1879fa79" + Id = "ad027f94-0682-431e-97c1-827d1879fa79" Description = "TeamsForBusinessInstaller" Developer = "Contoso" DisplayName = "TeamsForBusinessInstaller" @@ -122,6 +125,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Publisher = "Contoso" PublishingState = "published" RoleScopeTagIds = @() + IgnoreVersionDetection = $True + + Ensure = 'Present' } } } diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 0142b0e7b5..c52e45b4fa 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -17945,6 +17945,14 @@ function New-MgBetaDeviceAppManagementMobileApp { [Microsoft.Management.Infrastructure.CimInstance[]] $Categories, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $ChildApps, + [Parameter()] [System.String[]] $RoleScopeTagIds @@ -17978,6 +17986,10 @@ function Get-MgBetaDeviceAppManagementMobileApp { [System.Boolean] $IsFeatured, + [Parameter()] + [System.Boolean] + $IgnoreVersionDetection, + [Parameter()] [System.String] $Notes, @@ -17999,10 +18011,6 @@ function Get-MgBetaDeviceAppManagementMobileApp { [ValidateSet('notPublished', 'processing','published')] $PublishingState, - [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance[]] - $Categories, - [Parameter()] [System.String[]] $RoleScopeTagIds @@ -18060,6 +18068,14 @@ function Update-MgBetaDeviceAppManagementMobileApp { [Microsoft.Management.Infrastructure.CimInstance[]] $Categories, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $ChildApps, + [Parameter()] [System.String[]] $RoleScopeTagIds From f71eb5ca12fd666ae3e6cfd9f8dfe87b0dd6724e Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Sat, 5 Oct 2024 21:47:19 -0700 Subject: [PATCH 072/252] categories export regression fixed and added a bunch of debug prints. --- .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 54 ++++++++++++++----- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 index efc9da67fa..fdbc6775c8 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 @@ -128,19 +128,19 @@ function Get-TargetResource try { $instance = Get-MgBetaDeviceAppManagementMobileApp ` - -Filter "(isof('microsoft.graph.macOSLobApp') and displayName eq '$DisplayName')" - # -ExpandProperty "categories,assignments" ` - # -ErrorAction SilentlyContinue | Where-Object ` - # -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.macOSLobApp' } + -Filter "(isof('microsoft.graph.macOSLobApp') and displayName eq '$DisplayName')" ` + -ExpandProperty "categories,assignments" ` + -ErrorAction SilentlyContinue | Where-Object ` + -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.macOSLobApp' } if ($null -eq $instance) { Write-Verbose -Message "No Mobile app with DisplayName {$DisplayName} was found. Search with DisplayName." $instance = Get-MgBetaDeviceAppManagementMobileApp ` - -MobileAppId $Id - # -ExpandProperty "categories,assignments" ` - # -ErrorAction Stop | Where-Object ` - # -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.macOSLobApp' } + -MobileAppId $Id ` + -ExpandProperty "categories,assignments" ` + -ErrorAction Stop | Where-Object ` + -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.macOSLobApp' } } if ($null -eq $instance) @@ -389,12 +389,26 @@ function Set-TargetResource # CREATE if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { + + Write-Host "Create MacOSLobApp: $DisplayName" + + foreach ($key in $setParameters.Keys) + { + Write-Host "Create MacOSLobApp: setParameters: $key - $($setParameters.$key)" + } + foreach ($key in $AdditionalProperties.Keys) + { + Write-Host "Create MacOSLobApp: AdditionalProperties: $key - $($AdditionalProperties.$key)" + } + + $app = New-MgBetaDeviceAppManagementMobileApp @setParameters -AdditionalProperties $AdditionalProperties #region Assignments $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments if ($app.id) { + Write-host "Assignment updates for MacOSLobApp: $DisplayName" Update-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $app.id ` -Targets $assignmentsHash ` -Repository 'deviceAppManagement/mobileAppAssignments' @@ -404,11 +418,13 @@ function Set-TargetResource # UPDATE elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { + Write-Host "Update MacOSLobApp: $DisplayName" Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id @setParameters -AdditionalProperties $AdditionalProperties $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments if ($app.id) { + Write-host "Assignment updates for MacOSLobApp: $DisplayName" Update-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $app.id ` -Targets $assignmentsHash ` -Repository 'deviceAppManagement/mobileAppAssignments' @@ -417,6 +433,7 @@ function Set-TargetResource # REMOVE elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { + Write-Host "Remove MacOSLobApp: $DisplayName" Remove-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id -Confirm:$false } } @@ -766,12 +783,24 @@ function Export-TargetResource if ($null -ne $Results.Categories) { - $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Categories' + $isCIMArray = $false + if ($Results.Categories.getType().Fullname -like '*[[\]]') + { + $isCIMArray = $true + } + + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Categories' -IsCIMArray:$isCIMArray } if ($null -ne $Results.childApps) { - $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'ChildApps' + $isCIMArray = $false + if ($Results.childApps.getType().Fullname -like '*[[\]]') + { + $isCIMArray = $true + } + + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'ChildApps' -IsCIMArray:$isCIMArray } if ($Results.Assignments) @@ -958,8 +987,9 @@ function Get-M365DSCIntuneMobileMocOSLobAppAdditionalProperties $processedValues = @() if($propertyName -eq "childApps" -and $null -ne $propertyValue -and $propertyValue.Count -gt 0) { - $processChildAppsValues = Get-M365DSCIntuneAppChildAppsAsString -ChildApps $Results.ChildApps - $results.Add($propertyName, $processChildAppsValues) + $processedChildAppsValues = Get-M365DSCIntuneAppChildAppsAsString -ChildApps $Results.ChildApps + Write-Host "Get-M365DSCIntuneMobileMocOSLobAppAdditionalProperties: processedChildAppsValues" $processedChildAppsValues + $results.Add($propertyName, $processedChildAppsValues) } else { From 0750f64e525683a369e3a02b2d637b39bc051fd0 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Sun, 6 Oct 2024 00:09:24 -0700 Subject: [PATCH 073/252] ChildApps exported but .\M365TenantConfig.ps1 throwing error. --- .../ConfigurationData.psd1 | Bin 0 -> 1852 bytes .../M365TenantConfig.ps1 | Bin 0 -> 6726 bytes .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 13 +++++++--- ...SFT_IntuneMobileAppsMacOSLobApp.schema.mof | 23 ++---------------- 4 files changed, 11 insertions(+), 25 deletions(-) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/ConfigurationData.psd1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/M365TenantConfig.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/ConfigurationData.psd1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/ConfigurationData.psd1 new file mode 100644 index 0000000000000000000000000000000000000000..a88f5a721d71bff17856a8609e248b0991c9cc26 GIT binary patch literal 1852 zcmd6o?Q0W35XPU+g8#$O2FRH0v*yKc zT11c|-QC%FduE>5e*bo$&$_HjN|s+sQ@)Ne4K!4a^gh1>UE9!#+S}Gq9@prnqn>8? zi}K&C7ITk0GNo8f^_E?(0@-@5+g`dlQ5(Hf0Y#>Bb+PVgqPb3q{}CTu&N<&XJ{O=2 z2(NIn&>1@SE*ztcr`a;fOFR$pw4IwF`qLN{?1vhYbw=KaXS~3_Rj_dHd1;OnY})9J zusH*N!TA;YspCr&ax~-x5fVKhO3s}{P0&kp=#fWcFm`zl&6rIajl#7aBAdF+1p7os z?C1O}SIcuyn&pXWe(=8?qRiCyedx!YZZ5mMtK(lbJYU~98RzCd8NAB&Z+Kh*o$+T5 zvN_nUI$oQQ^%@5(6J!%^tiA(siOfjc+IqMPQRK@rsyFs16MgbJhPtmND9pxF-Bv?& z7=4Scp}VSas+eHBclR&>e+-DD$Bvpwul}X(Sl7TdCxa>zw3NBcBCVG z8|zzG70j#E$~a^58@W>!bGP^4J0MO$R|R7e zb=cHk9qLXAt6~of|EXh06fy|dRz0wa+VmJsTUX48Gi8(aYaPOTS%2+CvKOtaChLq_ zuf+e;dz)cnnY~L1HTf4D*o+ala0t&cIR9K<>1<9{3tq9uyp;R=4>;m&ufdW5-8=T1 cH`MzbZ(viev3bFLUr&%cVr^ddr3tUk528Bvf&c&j literal 0 HcmV?d00001 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/M365TenantConfig.ps1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/M365TenantConfig.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..ae1c67dba568f039f0135362fd0ea6b0b6451835 GIT binary patch literal 6726 zcmeI1Yi}Ay6o${|O8pPWu|y&j0(KJHtt!=ZO64}bD7gJpDdMum#1{zQxM`HX-u8KC zn6ir(W~nVVAF9>vEVDCb-g)QTX87yRM^>^QEwL-^k+p0>*`@Br`n;dskfz2}+@CQjJ;JBjy6{DuxtN%wQ zsf1)*w?_(JW+R50bvt6bo|D_RKPV@l5Sl}WRV;nWy`C8}i}9uFrMVwYdk$Eigf*5l z)yKxr9CQa%`>-@b)`)NSJ zlhqL433^*~Ov_Sx?zgOVLhUYVB=3{?PrSLMaXD(f)4MT!gg>*vHK7g4t+Pd9UBWAglF$TsHiKE4D(? zXZgh|nDY#ck&=IDg}$45*ZdZ<+5dbwNnMeHyZJEzJs%Vj7>k!{wrPRo; zTr267B7E0=aiwtN@pM8jMN4^x)o{uN#IK%#*%oUi>ku<-o<%wSwA7~s9r<6sXCC9f z*YC82KD3Uf{o6z6wc^b?EZTdsZb3^~uGO(Pv4;)GzIu2a#X03c!4htl4;3e}s6K$` zBX>HZyp1he)5j;N#(T>;e&UpC!|kCqh^0058H(~1vbYxaHg7vFqf?#oyA8hY&}wVC zBT?OIzDsdwu?PQ|ao=*wi*FW`ynL+#19$OY_szUw!!|sM+im7q;jY2&j$?iUP7~g= z0$bEqV13*1t~PC2ZE@GAxliVgU5wTKM;SxkWdIXmY_TyuMRTt`;-sQe$R?Iql-JOQ z$i3!Kt!`6o7*md=~Y9Z~Kzv-9lkY&F^0 zGnK6TFhY%4)(UG%5s!5@Yt3rf=dz~S%Oza0F72FtLO=ATea$t$^}gEL#MZs|ssv5C z|J9DgTICZukx`r-I&SrZ=R*l=H~_!5yDaAPFOPpMvQJ&K z%SlU`y?=h3{D3Bp(P`ywGn|XwJbuL=X@cL?#25;mc9G0%y&s`PMC}k;>*PEyTyC?) zXq!Y?`A?ijo Date: Sun, 6 Oct 2024 01:27:06 -0700 Subject: [PATCH 074/252] m365config compiled and startdsc passed. --- .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 5 ++--- .../MSFT_IntuneMobileAppsMacOSLobApp.schema.mof | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 index 9faa73fce3..3efefa8afb 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 @@ -346,8 +346,7 @@ function Set-TargetResource ) Write-Host "start Set-TargetResource.............................." - Write-Verobse "start Set-TargetResource.............................." - Write-Debug "start Set-TargetResource.............................." + #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -548,8 +547,8 @@ function Test-TargetResource [System.String[]] $AccessTokens ) + Write-Host "start test-TargetResource.............................." - Write-Verobse "start test-TargetResource.............................." Write-Debug "start Set-TargetResource.............................." #Ensure the proper dependencies are installed in the current environment. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof index f906eca867..51d02c0a12 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof @@ -17,6 +17,7 @@ class MSFT_IntuneMobileAppsMacOSLobApp : OMI_BaseResource [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppCategory")] String Categories[]; [Write, Description("The list of assignments for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppAssignment")] String Assignments[]; + [Write, Description("The list of child apps for this app package."), EmbeddedInstance("MSFT_DeviceManagementMobileAppChildApp")] String ChildApps[]; [Write, Description("Wether to ignore the version of the app or not.")] Boolean IgnoreVersionDetection; @@ -41,7 +42,7 @@ class MSFT_DeviceManagementMobileAppChildApp { [Write, Description("The bundleId of the app.")] String bundleId; [Write, Description("The build number of the app.")] String buildNumber; - [Write, Description("The version number of the app.")], String versionNumber; + [Write, Description("The version number of the app.")] String versionNumber; }; class MSFT_DeviceManagementMobileAppAssignment From 663081f1628d0a634cb2a48d0c12786b31b8de5f Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Sun, 6 Oct 2024 17:38:28 -0700 Subject: [PATCH 075/252] Existing instance got updated. --- .../ConfigurationData.psd1 | Bin 1852 -> 0 bytes .../M365TenantConfig.ps1 | Bin 6726 -> 0 bytes .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 234 +++++++++++++----- 3 files changed, 169 insertions(+), 65 deletions(-) delete mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/ConfigurationData.psd1 delete mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/M365TenantConfig.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/ConfigurationData.psd1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/ConfigurationData.psd1 deleted file mode 100644 index a88f5a721d71bff17856a8609e248b0991c9cc26..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1852 zcmd6o?Q0W35XPU+g8#$O2FRH0v*yKc zT11c|-QC%FduE>5e*bo$&$_HjN|s+sQ@)Ne4K!4a^gh1>UE9!#+S}Gq9@prnqn>8? zi}K&C7ITk0GNo8f^_E?(0@-@5+g`dlQ5(Hf0Y#>Bb+PVgqPb3q{}CTu&N<&XJ{O=2 z2(NIn&>1@SE*ztcr`a;fOFR$pw4IwF`qLN{?1vhYbw=KaXS~3_Rj_dHd1;OnY})9J zusH*N!TA;YspCr&ax~-x5fVKhO3s}{P0&kp=#fWcFm`zl&6rIajl#7aBAdF+1p7os z?C1O}SIcuyn&pXWe(=8?qRiCyedx!YZZ5mMtK(lbJYU~98RzCd8NAB&Z+Kh*o$+T5 zvN_nUI$oQQ^%@5(6J!%^tiA(siOfjc+IqMPQRK@rsyFs16MgbJhPtmND9pxF-Bv?& z7=4Scp}VSas+eHBclR&>e+-DD$Bvpwul}X(Sl7TdCxa>zw3NBcBCVG z8|zzG70j#E$~a^58@W>!bGP^4J0MO$R|R7e zb=cHk9qLXAt6~of|EXh06fy|dRz0wa+VmJsTUX48Gi8(aYaPOTS%2+CvKOtaChLq_ zuf+e;dz)cnnY~L1HTf4D*o+ala0t&cIR9K<>1<9{3tq9uyp;R=4>;m&ufdW5-8=T1 cH`MzbZ(viev3bFLUr&%cVr^ddr3tUk528Bvf&c&j diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/M365TenantConfig.ps1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/M365TenantConfig.ps1 deleted file mode 100644 index ae1c67dba568f039f0135362fd0ea6b0b6451835..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6726 zcmeI1Yi}Ay6o${|O8pPWu|y&j0(KJHtt!=ZO64}bD7gJpDdMum#1{zQxM`HX-u8KC zn6ir(W~nVVAF9>vEVDCb-g)QTX87yRM^>^QEwL-^k+p0>*`@Br`n;dskfz2}+@CQjJ;JBjy6{DuxtN%wQ zsf1)*w?_(JW+R50bvt6bo|D_RKPV@l5Sl}WRV;nWy`C8}i}9uFrMVwYdk$Eigf*5l z)yKxr9CQa%`>-@b)`)NSJ zlhqL433^*~Ov_Sx?zgOVLhUYVB=3{?PrSLMaXD(f)4MT!gg>*vHK7g4t+Pd9UBWAglF$TsHiKE4D(? zXZgh|nDY#ck&=IDg}$45*ZdZ<+5dbwNnMeHyZJEzJs%Vj7>k!{wrPRo; zTr267B7E0=aiwtN@pM8jMN4^x)o{uN#IK%#*%oUi>ku<-o<%wSwA7~s9r<6sXCC9f z*YC82KD3Uf{o6z6wc^b?EZTdsZb3^~uGO(Pv4;)GzIu2a#X03c!4htl4;3e}s6K$` zBX>HZyp1he)5j;N#(T>;e&UpC!|kCqh^0058H(~1vbYxaHg7vFqf?#oyA8hY&}wVC zBT?OIzDsdwu?PQ|ao=*wi*FW`ynL+#19$OY_szUw!!|sM+im7q;jY2&j$?iUP7~g= z0$bEqV13*1t~PC2ZE@GAxliVgU5wTKM;SxkWdIXmY_TyuMRTt`;-sQe$R?Iql-JOQ z$i3!Kt!`6o7*md=~Y9Z~Kzv-9lkY&F^0 zGnK6TFhY%4)(UG%5s!5@Yt3rf=dz~S%Oza0F72FtLO=ATea$t$^}gEL#MZs|ssv5C z|J9DgTICZukx`r-I&SrZ=R*l=H~_!5yDaAPFOPpMvQJ&K z%SlU`y?=h3{D3Bp(P`ywGn|XwJbuL=X@cL?#25;mc9G0%y&s`PMC}k;>*PEyTyC?) zXq!Y?`A?ijo handles only singular properties - - if (($propertyValue -is [System.Collections.IEnumerable] -or $propertyValue.count -gt 0) -and -not ($propertyValue -is [string])) + if ($properties.$property -and $properties.$property.getType().FullName -like '*CIMInstance*') { - # Handle array/collection properties - $processedValues = @() - if($propertyName -eq "childApps" -and $null -ne $propertyValue -and $propertyValue.Count -gt 0) + if ($properties.$property.getType().FullName -like '*[[\]]') { - $processedChildAppsValues = Get-M365DSCIntuneAppChildAppsAsString -ChildApps $Results.ChildApps - Write-Host "Get-M365DSCIntuneMobileMocOSLobAppAdditionalProperties: processedChildAppsValues" $processedChildAppsValues - $results.Add($propertyName, $processedChildAppsValues) + $array = @() + foreach ($item in $properties.$property) + { + $array += Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $item + + } + $propertyValue = $array } else { - foreach ($item in $propertyValue) - { - $processedValues += $item - } - - $results.Add($propertyName, $processedValues) + $propertyValue = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $properties.$property } + } - else { - # Handle singular properties - $results.Add($propertyName, $propertyValue) + else + { + $propertyValue = $properties.$property } + + $results.Add($propertyName, $propertyValue) } } + + if ($results.Count -eq 1) + { + return $null + } return $results } From 4777f6c7fab51225b66c95d7204dfa700a35c9f5 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Sun, 6 Oct 2024 22:11:01 -0700 Subject: [PATCH 076/252] Draft Intune DSC Derived Credential --- .../MSFT_IntuneDerivedCredential.psm1 | 292 ++++++++++++------ .../MSFT_IntuneDerivedCredential.schema..mof | 29 ++ .../MSFT_IntuneDeviceCredential.schema.mof | 32 -- 3 files changed, 227 insertions(+), 126 deletions(-) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.schema..mof delete mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDeviceCredential.schema.mof diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.psm1 index 874df581fe..fc43dfdeec 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.psm1 @@ -1,14 +1,12 @@ -function Get-TargetResource -{ +function Get-TargetResource { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] - param - ( + param ( [Parameter()] [System.String] $Id, - [Parameter(Mandatory = $true)] + [Parameter()] [System.String] $DisplayName, @@ -16,24 +14,51 @@ function Get-TargetResource [System.String] $HelpUrl, - [Parameter(Mandatory=$true)] - [ValidateSet('intercede', 'entrust', 'disa purebred')] + [Parameter()] + [ValidateSet('intercede', 'entrustData', 'purebred')] [System.String] $Issuer, - [Parameter(Mandatory=$true)] - [ValidateSet('email', 'Company Portal (iOS) Microsoft Intune (Android) app')] + [Parameter()] + [ValidateSet('none', 'email', 'companyPortal')] + [System.String] + $NotificationType = 'none', + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] [System.String] - $NotificationType, + $CertificateThumbprint, [Parameter()] - [System.Int32] - $ThresholdPercentage, + [Switch] + $ManagedIdentity, [Parameter()] - [System.Collections.IDictionary] - $Header + [System.String[]] + $AccessTokens + ) + Write-Host "Host: start of get." New-M365DSCConnection -Workload 'MicrosoftGraph' ` -InboundParameters $PSBoundParameters | Out-Null @@ -52,6 +77,7 @@ function Get-TargetResource $nullResult = $PSBoundParameters $nullResult.Ensure = 'Absent' + try { $instance = $null @@ -59,39 +85,48 @@ function Get-TargetResource { $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Id -eq $Id} } + if ($null -eq $instance) { - $instance = Get-MgBetaDeviceManagementDerivedCredential DerivedCredentialId $Id -ErrorAction Stop + $instance = Get-MgBetaDeviceManagementDerivedCredential -DeviceManagementDerivedCredentialSettingsId $Id -ErrorAction Stop if ($null -eq $instance) { - Write-Verbose -Message "Could not find DerivedCredential by Id {$Id}." + Write-Verbose -Message "Could not find Derived Credential by Id {$Id}." if (-Not [string]::IsNullOrEmpty($DisplayName)) { $instance = Get-MgBetaDeviceManagementDerivedCredential ` - -Filter "DisplayName eq '$DisplayName'" ` - -ErrorAction SilentlyContinue - } - } - } - if ($null -eq $instance) - { - Write-Verbose -Message "Could not find DerivedCredential by DisplayName {$DisplayName}." - return $nullResult - } + -Filter "DisplayName eq '$DisplayName'" ` + -ErrorAction SilentlyContinue + if ($null -eq $instance) + { + Write-Verbose -Message "Could not find Derived Credential by DisplayName {$DisplayName}." + return $nullResult + } + } + + } + } + Write-Host "Values of Instance Id: $($instance.Id), DisplayName: $($instance.DisplayName), HelpUrl: $($instance.HelpUrl), Issuer: $($instance.Issuer), NotificationType: $($instance.NotificationType)" $results = @{ Ensure = 'Present' Id = $instance.Id DisplayName = $instance.DisplayName - HelpUrl = $HelpUrl - Issuer = $Issuer - NotificationType = $NotificationType - ThresholdPercentage = $ThresholdPercentage - Header = $Header - + HelpUrl = $instance.HelpUrl + Issuer = $instance.Issuer + NotificationType = $instance.NotificationType + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ApplicationSecret = $ApplicationSecret + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens } + Write-Host "Values of Results:: Id: $($results.Id), DisplayName: $($results.DisplayName), HelpUrl: $($results.HelpUrl), Issuer: $($results.Issuer), NotificationType: $($results.NotificationType)" + return [System.Collections.Hashtable] $results } catch @@ -107,16 +142,14 @@ function Get-TargetResource } } -function Set-TargetResource -{ +function Set-TargetResource { [CmdletBinding()] - param - ( + param ( [Parameter()] [System.String] $Id, - [Parameter(Mandatory = $true)] + [Parameter()] [System.String] $DisplayName, @@ -124,23 +157,48 @@ function Set-TargetResource [System.String] $HelpUrl, - [Parameter(Mandatory=$true)] - [ValidateSet('intercede', 'entrust', 'disa purebred')] + [Parameter()] + [ValidateSet('intercede', 'entrustData', 'purebred')] [System.String] $Issuer, - [Parameter(Mandatory=$true)] - [ValidateSet('email', 'Company Portal (iOS) Microsoft Intune (Android) app')] + [Parameter()] + [ValidateSet('none', 'email', 'companyPortal')] + [System.String] + $NotificationType = 'none', + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure='Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] [System.String] - $NotificationType, + $CertificateThumbprint, [Parameter()] - [System.Int32] - $ThresholdPercentage, + [Switch] + $ManagedIdentity, [Parameter()] - [System.Collections.IDictionary] - $Header + [System.String[]] + $AccessTokens ) #Ensure the proper dependencies are installed in the current environment. @@ -158,6 +216,8 @@ function Set-TargetResource $currentInstance = Get-TargetResource @PSBoundParameters $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + $setParameters.remove('Id') | Out-Null + $setParameters.remove('Ensure') | Out-Null # CREATE if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') @@ -167,26 +227,24 @@ function Set-TargetResource # UPDATE elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { - Update-MgBetaDeviceManagementDerivedCredential @SetParameters + Update-MgBetaDeviceManagementDerivedCredential -DeviceManagementDerivedCredentialSettingsId $currentInstance.Id @SetParameters } # REMOVE elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { - Remove-MgBetaDeviceManagementDerivedCredential @SetParameters + Remove-MgBetaDeviceManagementDerivedCredential -DeviceManagementDerivedCredentialSettingsId $currentInstance.Id -Confirm:$false } } -function Test-TargetResource -{ +function Test-TargetResource { [CmdletBinding()] [OutputType([System.Boolean])] - param - ( + param ( [Parameter()] [System.String] $Id, - [Parameter(Mandatory = $true)] + [Parameter()] [System.String] $DisplayName, @@ -194,26 +252,50 @@ function Test-TargetResource [System.String] $HelpUrl, - [Parameter(Mandatory=$true)] - [ValidateSet('intercede', 'entrust', 'disa purebred')] + [Parameter()] + [ValidateSet('intercede', 'entrustData', 'purebred')] [System.String] $Issuer, - [Parameter(Mandatory=$true)] - [ValidateSet('email', 'Company Portal (iOS) Microsoft Intune (Android) app')] + [Parameter()] + [ValidateSet('none', 'email', 'companyPortal')] + [System.String] + $NotificationType = 'none', + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] [System.String] - $NotificationType, + $CertificateThumbprint, [Parameter()] - [System.Int32] - $ThresholdPercentage, + [Switch] + $ManagedIdentity, [Parameter()] - [System.Collections.IDictionary] - $Header + [System.String[]] + $AccessTokens ) - #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies #region Telemetry @@ -241,17 +323,15 @@ function Test-TargetResource return $testResult } -function Export-TargetResource -{ +function Export-TargetResource { [CmdletBinding()] [OutputType([System.String])] - param - ( + param ( [Parameter()] [System.String] $Id, - [Parameter(Mandatory = $true)] + [Parameter()] [System.String] $DisplayName, @@ -259,28 +339,52 @@ function Export-TargetResource [System.String] $HelpUrl, - [Parameter(Mandatory=$true)] - [ValidateSet('Intercede', 'Entrust', 'DISA Purebred')] + [Parameter()] + [ValidateSet('intercede', 'entrustData', 'purebred')] [System.String] $Issuer, - [Parameter(Mandatory=$true)] - [ValidateSet('Email', 'Company Portal (iOS) Microsoft Intune (Android) app')] + [Parameter()] + [ValidateSet('none', 'email', 'companyPortal')] + [System.String] + $NotificationType = 'none', + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] [System.String] - $NotificationType, + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, [Parameter()] - [System.Int32] - $ThresholdPercentage, + [System.String] + $CertificateThumbprint, [Parameter()] - [System.Collections.IDictionary] - $Header + [Switch] + $ManagedIdentity, + [Parameter()] + [System.String[]] + $AccessTokens ) + Write-Host "Host: start of export." $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` - -InboundParameters $PSBoundParameters + -InboundParameters $PSBoundParameters #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -311,24 +415,23 @@ function Export-TargetResource } foreach ($config in $Script:exportedInstances) { - if ($null -ne $Global:M365DSCExportResourceInstancesCount) - { - $Global:M365DSCExportResourceInstancesCount++ - } - $displayedKey = $config.Id Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline - $results = @{ - Ensure = 'Present' - Id = $instance.Id - DisplayName = $instance.DisplayName - HelpUrl = $HelpUrl - Issuer = $Issuer - NotificationType = $NotificationType - ThresholdPercentage = $ThresholdPercentage - Header = $Header - - } + $params = @{ + Ensure = 'Present' + Id = $config.Id + DisplayName = $config.DisplayName + HelpUrl = $config.HelpUrl + Issuer = $config.Issuer + NotificationType = $config.NotificationType + Credential = $Credential + AccessTokens = $AccessTokens + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + } $Results = Get-TargetResource @Params $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` @@ -359,6 +462,7 @@ function Export-TargetResource return '' } + } Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.schema..mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.schema..mof new file mode 100644 index 0000000000..990a94b0d6 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.schema..mof @@ -0,0 +1,29 @@ +[ClassVersion("1.0.0.0"), FriendlyName("IntuneDerivedCredential")] +class MSFT_IntuneDerivedCredential : OMI_BaseResource { + [Write, Description("The name of the app category.")] + String DisplayName; + + [Write, Description("The unique identifier for an entity. Read-only.")] + String Id; + + [Write, Description("The URL that will be accessible to end users as they retrieve a derived credential using the Company Portal.")] + String HelpUrl; + + [Write, Description("Supported values for the derived credential issuer."), ValueMap{"intercede", "entrustDatacard", "purebred"}, Values{"intercede", "entrustDatacard", "purebred"}] + String Issuer; + + [Write, Description("Supported values for the notification type to use."), ValueMap{"none", "email", "companyPortal"}, Values{"none", "email", "companyPortal"}] + String NotificationType = "none"; // Default value is set to "none" + + [Write, Description("Supported values for the notification type to use."), ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] + String Ensure = "Present"; // Default value is set to "none" + + [Write, Description("Credentials of the Intune Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com")] String TenantId; + [Write, Description("Secret of the Azure Active Directory tenant used for authentication."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; + +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDeviceCredential.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDeviceCredential.schema.mof deleted file mode 100644 index 4f5994242a..0000000000 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDeviceCredential.schema.mof +++ /dev/null @@ -1,32 +0,0 @@ -[ClassVersion("1.0.0.0"), Description("Represents a key-value pair.")] -class KeyValuePair { - [Key, Description("The key of the dictionary entry.")] - string Key; - - [Description("The value of the dictionary entry.")] - string Value; -}; - -[ClassVersion("1.0.0.0"), FriendlyName("IntuneDeviceCredential")] -class MSFT_IntuneDeviceCredential : OMI_BaseResource { - [Key, Description("The name of the app category.")] - string DisplayName; - - [Write, Description("The unique identifier for an entity. Read-only.")] - string Id; - - [Write, Description("The URL that will be accessible to end users as they retrieve a derived credential using the Company Portal.")] - string HelpUrl; - - [Write, Description("Supported values for the derived credential issuer."), ValueMap{"Intercede", "Entrust", "DISA Purebred"}, Values{"Intercede", "Entrust", "DISA Purebred"}] - string Issuer; - - [Write, Description("Supported values for the notification type to use."), ValueMap{"Email", "Company Portal (iOS) Microsoft Intune (Android) app"}, Values{"Email", "Company Portal (iOS) Microsoft Intune (Android) app"}] - string NotificationType; - - [Write, Description("The nominal percentage of time before certificate renewal is initiated by the client.")] - uint32 ThresholdPercentage; - - [Write, Description("Optional headers that will be added to the request.")] - KeyValuePair[] Header; -}; From 41cba6437485a17310fd2aefeab46f45ffcd5bec Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Mon, 7 Oct 2024 00:28:47 -0700 Subject: [PATCH 077/252] update resource working. --- .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 98 +++++++------------ ...SFT_IntuneMobileAppsMacOSLobApp.schema.mof | 25 +++-- .../Modules/M365DSCDRGUtil.psm1 | 58 +++++++++-- 3 files changed, 97 insertions(+), 84 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 index 967027d92d..84c948edb4 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 @@ -189,13 +189,6 @@ function Get-TargetResource #childApps if($null -ne $instance.AdditionalProperties.childApps) { - # foreach ($childApp in $instance.AdditionalProperties.childApps) - # { - # Write-Host "Get- print childApps.............................." $childApp.bundleId - # Write-Host "Get- print childApps.............................." $childApp.buildNumber - # Write-Host "Get- print childApps.............................." $childApp.versionNumber - # } - $results.Add('ChildApps', $instance.AdditionalProperties.childApps) } else { @@ -452,9 +445,9 @@ function Set-TargetResource $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments if ($app.id) { - Write-host "Assignment updates for MacOSLobApp: $DisplayName" + Write-host "New and update: Assignment updates for MacOSLobApp: $DisplayName, with assignmenthash:=======================" $assignmentsHash Update-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $app.id ` - -Targets $assignmentsHash ` + -Target $assignmentsHash ` -Repository 'deviceAppManagement/mobileAppAssignments' } #endregion Assignments @@ -468,34 +461,24 @@ function Set-TargetResource $UpdateParameters = ([Hashtable]$PSBoundParameters).clone() $UpdateParameters = Rename-M365DSCCimInstanceParameter -Properties $UpdateParameters - Write-Host "^^^^^^ Update Parameters............................." $UpdateParameters - $AdditionalProperties = Get-M365DSCIntuneMobileMocOSLobAppAdditionalProperties -Properties ($UpdateParameters) - - Write-Host "^^^^^^ Update AdditionalProperties............................." $AdditionalProperties - foreach ($key in $AdditionalProperties.keys) { if ($key -ne '@odata.type') { $keyName = $key.substring(0, 1).ToUpper() + $key.substring(1, $key.length - 1) - $UpdateParameters.remove($keyName) - Write-Host "^^^^^^ Removed key ............................." $keyName + #Remove additional keys, so that later they can be added as 'AdditionalProperties' + $UpdateParameters.Remove($keyName) } } $UpdateParameters.Remove('Id') | Out-Null $UpdateParameters.Remove('Verbose') | Out-Null $UpdateParameters.Remove('Categories') | Out-Null - $UpdateParameters.Remove('PublishingState') | Out-Null - - Write-Host "^^^^^^ Removed CAT ONLY ONCE ~~~~~~~~~~~~~~~~~~~~~~" + $UpdateParameters.Remove('PublishingState') | Out-Null #Not allowed to update as it's a computed property - Write-Host "^^^^^^ Updated updateParameters (removed, id, verbose, cate, CAT and other props from additionalprops) ............................." $UpdateParameters foreach ($key in ($UpdateParameters.clone()).Keys) { - Write-Host "added key-value to updateParameters .............................$key : $value" - if ($UpdateParameters[$key].getType().Fullname -like '*CimInstance*') { $value = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $UpdateParameters[$key] @@ -508,23 +491,29 @@ function Set-TargetResource $UpdateParameters.add('AdditionalProperties', $AdditionalProperties) } - Write-Host "^^^^^^ FINAL: updateParameters: right before Calling update-MgBetaDeviceAppManagementMobileApp ............................." $UpdateParameters - + Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id @UpdateParameters + Write-Host " ################# Returned Update-MgBetaDeviceAppManagementMobileApp ############################### " - $updateResult = Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id @UpdateParameters + #region Assignments - Write-Host "^^^^^^ Update result............................." $updateResult + $Assignments | ForEach-Object { + Write-Host "INPUT: $_" + } + $Assignments | ForEach-Object { + Write-Host "INPUT Assignment string: $Assignments" + } - #region Assignments $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments - if ($app.id) - { - Write-host "Assignment updates for MacOSLobApp: $DisplayName" - Update-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $app.id ` - -Targets $assignmentsHash ` - -Repository 'deviceAppManagement/mobileAppAssignments' - } + $assignmentsHash.GetEnumerator() | ForEach-Object { + Write-Host "Converted assignmentsHash key:value: $($_.Key): $($_.Value)" } + + Write-Host " ############### Calling Update-MgBetaDeviceAppManagementMobileAppAssignment now ############################# " + + Update-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $currentInstance.id ` + -Target $assignmentsHash ` + -Repository 'deviceAppManagement/mobileAppAssignments' + #endregion Assignments } # REMOVE @@ -768,7 +757,7 @@ function Export-TargetResource try { $Script:ExportMode = $true - [array] $Script:exportedInstances = Get-MgBetaDeviceAppManagementMobileApp ` + [array] $Script:getInstances = Get-MgBetaDeviceAppManagementMobileApp ` -Filter "isof('microsoft.graph.macOSLobApp')" ` -ExpandProperty "categories,assignments" ` -ErrorAction Stop | Where-Object ` @@ -776,7 +765,7 @@ function Export-TargetResource $i = 1 $dscContent = '' - if ($Script:exportedInstances.Length -eq 0) + if ($Script:getInstances.Length -eq 0) { Write-Host $Global:M365DSCEmojiGreenCheckMark } @@ -784,10 +773,16 @@ function Export-TargetResource { Write-Host "`r`n" -NoNewline } - foreach ($config in $Script:exportedInstances) + foreach ($config in $Script:getInstances) { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + $displayedKey = $config.Id - Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + Write-Host " |---[$i/$($Script:getInstances.Count)] $displayedKey" -NoNewline + $params = @{ Id = $config.Id Description = $config.Description @@ -802,7 +797,6 @@ function Export-TargetResource PublishingState = $config.PublishingState.ToString() RoleScopeTagIds = $config.RoleScopeTagIds IgnoreVersionDetection = $config.AdditionalProperties.ignoreVersionDetection - #ChildApps = $config.AdditionalProperties.childApps Ensure = 'Present' Credential = $Credential @@ -815,6 +809,8 @@ function Export-TargetResource } $Results = Get-TargetResource @params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results if (-not (Test-M365DSCAuthenticationParameter -BoundParameters $Results)) { @@ -825,30 +821,14 @@ function Export-TargetResource #region complex types #Categories - if($null -eq $Results.Categories -or $Results.Categories.Count -eq 0) - { - $Results.Categories = $null - } - else + if($null -ne $Results.Categories -or $Results.Categories.Count -gt 0) { $Results.Categories = Get-M365DSCIntuneAppCategoriesAsString -Categories $Results.Categories } #ChildApps - if($null -eq $Results.childApps -or $Results.childApps.Count -eq 0) + if($null -ne $Results.childApps -or $Results.childApps.Count -gt 0) { - Write-Host "Export print childApps: IN IF WHERE CHILD APPS NULL.............................." - } - else - { - Write-Host "Export print childApps: IN ELSE BEFORE FOR LOOP.............................." - foreach ($childApp in $Results.childApps) - { - Write-Host "Export print childApps.............................." $childApp.bundleId - Write-Host "Export print childApps.............................." $childApp.buildNumber - Write-Host "Export print childApps.............................." $childApp.versionNumber - } - $Results.childApps = Get-M365DSCIntuneAppChildAppsAsString -ChildApps $Results.childApps } @@ -867,12 +847,8 @@ function Export-TargetResource } } - #endregion complex types - $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` - -Results $Results - $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` -ConnectionMode $ConnectionMode ` -ModulePath $PSScriptRoot ` diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof index 51d02c0a12..222f5f14e8 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof @@ -47,18 +47,9 @@ class MSFT_DeviceManagementMobileAppChildApp class MSFT_DeviceManagementMobileAppAssignment { - [Write, Description("Possible values for the install intent chosen by the admin."), - ValueMap{"available", "required", "uninstall", "availableWithoutEnrollment"}, - Values{"available", "required", "uninstall", "availableWithoutEnrollment"}] - String intent; - - [Write, Description("The source of this assignment.")] String source; - - [Write, Description("The group Id that is the target of the assignment.")] String groupId; - [Write, Description("The group Display Name that is the target of the assignment.")] String groupDisplayName; - [Write, Description("The type of the target assignment."), - ValueMap{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget"}, - Values{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget"}] + [Write, Description("The type of the target assignment."), + ValueMap{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget", "#microsoft.graph.mobileAppAssignment"}, + Values{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget", "#microsoft.graph.mobileAppAssignment"}] String dataType; [Write, Description("The Id of the filter for the target assignment.")] String deviceAndAppManagementAssignmentFilterId; @@ -67,5 +58,13 @@ class MSFT_DeviceManagementMobileAppAssignment Values{"none", "include", "exclude"}] String deviceAndAppManagementAssignmentFilterType; - [Write, Description("The list of settings used with this app assignemnt."), EmbeddedInstance("MSFT_DeviceManagementMobileAppAssignmentSetting")] String settings[]; + [Write, Description("The group Id that is the target of the assignment.")] String groupId; + [Write, Description("The group Display Name that is the target of the assignment.")] String groupDisplayName; + + [Write, Description("Possible values for the install intent chosen by the admin."), + ValueMap{"available", "required", "uninstall", "availableWithoutEnrollment"}, + Values{"available", "required", "uninstall", "availableWithoutEnrollment"}] + String intent; + + [Write, Description("The source of this assignment.")] String source; }; diff --git a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 index f722b123ce..2c3a1fadfb 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 @@ -285,6 +285,7 @@ function Get-M365DSCDRGComplexTypeToString { $indent += ' ' } + #If ComplexObject is an Array if ($ComplexObject.GetType().FullName -like '*[[\]]') { @@ -305,7 +306,7 @@ function Get-M365DSCDRGComplexTypeToString $currentProperty += Get-M365DSCDRGComplexTypeToString -IsArray @splat } - # PowerShell returns all non-captured stream output, not just the argument of the return statement. + #PowerShell returns all non-captured stream output, not just the argument of the return statement. #An empty array is mangled into $null in the process. #However, an array can be preserved on return by prepending it with the array construction operator (,) return , $currentProperty @@ -1181,6 +1182,7 @@ function ConvertTo-IntunePolicyAssignment [Parameter(Mandatory = $true)] [AllowNull()] $Assignments, + [Parameter()] [System.Boolean] $IncludeDeviceFilter = $true @@ -1320,7 +1322,6 @@ function ConvertFrom-IntuneMobileAppAssignment # $concatenatedSettings = $assignment.settings.ToString() -join ',' # $hashAssignment.Add('settings', $concatenatedSettings) - # $hashSettings = @{} # foreach ($setting in $assignment.Settings) # { @@ -1355,6 +1356,7 @@ function ConvertTo-IntuneMobileAppAssignment [Parameter(Mandatory = $true)] [AllowNull()] $Assignments, + [Parameter()] [System.Boolean] $IncludeDeviceFilter = $true @@ -1375,20 +1377,42 @@ function ConvertTo-IntuneMobileAppAssignment { $target.Add('deviceAndAppManagementAssignmentFilterType', $assignment.DeviceAndAppManagementAssignmentFilterType) $target.Add('deviceAndAppManagementAssignmentFilterId', $assignment.DeviceAndAppManagementAssignmentFilterId) + + $target.GetEnumerator() | ForEach-Object { + Write-Host "target key:value: $($_.Key): $($_.Value)" } } } - $assignmentResult += $assignment.intent; - $assignmentResult += $assignment.source; - $assignmentResult += $assignment.settings; + #TODOK: Uncomment it + # $assignmentResult += $assignment.intent; + # $assignmentResult += $assignment.source; + + # if($assignment.settings) + # { + # $assignmentResult += $assignment.settings; + # } - if ($assignment.dataType -like '*GroupAssignmentTarget') + + if ($assignment.dataType -like '*groupAssignmentTarget' ` + -or $assignment.dataType -like '*allDevicesAssignmentTarget' ` + -or $assignment.dataType -like '*allLicensedUsersAssignmentTarget') { - $group = Get-MgGroup -GroupId ($assignment.groupId) -ErrorAction SilentlyContinue + Write-Host "Befgore group call assignment.groupId: " $assignment.groupId + Write-Host "After group call assignment.groupId: `"$($assignment.groupId)`" -----------------------------------------" + + $group = Get-MgGroup -GroupId ($assignment.groupId) -ErrorAction SilentlyContinue #TODOK: SilentlyContinue later + + Write-Host "After group call assignment.group: " $group + if ($null -eq $group) { + Write-Host "After group call group is null: " $group + + Write-Host "After group call assignment.group: " $assignment.groupDisplayName + if ($assignment.groupDisplayName) { + Write-Host "Befpre group call with NAME assignment.group.NAME: " $assignment.groupDisplayName $group = Get-MgGroup -Filter "DisplayName eq '$($assignment.groupDisplayName)'" -ErrorAction SilentlyContinue if ($null -eq $group) { @@ -1414,17 +1438,31 @@ function ConvertTo-IntuneMobileAppAssignment $target = $null } } - #Skipping assignment if group not found from either groupId or groupDisplayName - if ($null -ne $group) - { + else { + #Skipping assignment if group not found from either groupId or groupDisplayName + + Write-Host "target group:::::::::::::::::::::: " $group + $target.Add('groupId', $group.Id) + + Write-Host "groupId added to target." + + + $target.GetEnumerator() | ForEach-Object { + Write-Host "target key:value with groupId: $($_.Key): $($_.Value)" } } } + Write-Host "1456 target: " $target if ($target) { + Write-Host "target assigned to final assignmentResult." + $assignmentResult += @{target = $target} } + + $assignmentResult.GetEnumerator() | ForEach-Object { + Write-Host "AssignmentResult key:value AFTER all targets added: $($_.Key): $($_.Value)" } } return ,$assignmentResult From 3f6b10ec4600a2bc6c1f410a9dfd27504f669a6a Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 7 Oct 2024 11:33:17 +0000 Subject: [PATCH 078/252] Updated Resources and Cmdlet documentation pages --- .../IntuneEndpointDetectionAndResponsePolicyWindows10.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/docs/resources/intune/IntuneEndpointDetectionAndResponsePolicyWindows10.md b/docs/docs/resources/intune/IntuneEndpointDetectionAndResponsePolicyWindows10.md index 9893c32f98..92a2428a6d 100644 --- a/docs/docs/resources/intune/IntuneEndpointDetectionAndResponsePolicyWindows10.md +++ b/docs/docs/resources/intune/IntuneEndpointDetectionAndResponsePolicyWindows10.md @@ -6,6 +6,7 @@ | --- | --- | --- | --- | --- | | **Identity** | Write | String | Identity of the endpoint detection and response policy for Windows 10. | | | **DisplayName** | Key | String | Display name of the endpoint detection and response policy for Windows 10. | | +| **RoleScopeTagIds** | Write | StringArray[] | List of Scope Tags for this Entity instance. | | | **Description** | Write | String | Description of the endpoint detection and response policy for Windows 10. | | | **Assignments** | Write | MSFT_DeviceManagementConfigurationPolicyAssignments[] | Assignments of the endpoint detection and response policy for Windows 10. | | | **SampleSharing** | Write | String | Return or set Windows Defender Advanced Threat Protection Sample Sharing configuration parameter: 0 - none, 1 - All | `0`, `1` | @@ -100,6 +101,9 @@ Configuration Example ApplicationId = $ApplicationId; TenantId = $TenantId; CertificateThumbprint = $CertificateThumbprint; + ConfigurationBlob = "Blob" + ConfigurationType = "onboard" + SampleSharing = 1 } } } @@ -139,6 +143,9 @@ Configuration Example ApplicationId = $ApplicationId; TenantId = $TenantId; CertificateThumbprint = $CertificateThumbprint; + ConfigurationBlob = "Blob" + ConfigurationType = "onboard" + SampleSharing = 1 } } } From b8fb472ec4c44a4367debf21166256ef367d6582 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 7 Oct 2024 11:35:13 +0000 Subject: [PATCH 079/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 7bbcdaf2d8..68ed19e390 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -33907,6 +33907,11 @@ "Name": "DisplayName", "Option": "Key" }, + { + "CIMType": "String[]", + "Name": "RoleScopeTagIds", + "Option": "Write" + }, { "CIMType": "String", "Name": "Description", From 0d95496fb39917f914cbb29a13dcf86dbdb9cc4c Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 7 Oct 2024 11:35:43 +0000 Subject: [PATCH 080/252] Updated {Create} Intune Integration Tests --- .../Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 index f60efd6f58..d61fd36960 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 @@ -2288,6 +2288,9 @@ ApplicationId = $ApplicationId; TenantId = $TenantId; CertificateThumbprint = $CertificateThumbprint; + ConfigurationBlob = "Blob" + ConfigurationType = "onboard" + SampleSharing = 1 } IntuneExploitProtectionPolicyWindows10SettingCatalog 'myWindows10ExploitProtectionPolicy' { From 5619252e6da45850640ef81bb049123c4f2882da Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 7 Oct 2024 12:16:32 +0000 Subject: [PATCH 081/252] Updated Resources and Cmdlet documentation pages --- ...neAppAndBrowserIsolationPolicyWindows10.md | 230 ++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 docs/docs/resources/intune/IntuneAppAndBrowserIsolationPolicyWindows10.md diff --git a/docs/docs/resources/intune/IntuneAppAndBrowserIsolationPolicyWindows10.md b/docs/docs/resources/intune/IntuneAppAndBrowserIsolationPolicyWindows10.md new file mode 100644 index 0000000000..31b41d628a --- /dev/null +++ b/docs/docs/resources/intune/IntuneAppAndBrowserIsolationPolicyWindows10.md @@ -0,0 +1,230 @@ +# IntuneAppAndBrowserIsolationPolicyWindows10 + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Description** | Write | String | Policy description | | +| **DisplayName** | Key | String | Policy name | | +| **RoleScopeTagIds** | Write | StringArray[] | List of Scope Tags for this Entity instance. | | +| **Id** | Write | String | The unique identifier for an entity. Read-only. | | +| **AllowWindowsDefenderApplicationGuard** | Write | String | Turn on Microsoft Defender Application Guard (0: Disable Microsoft Defender Application Guard, 1: Enable Microsoft Defender Application Guard for Microsoft Edge ONLY, 2: Enable Microsoft Defender Application Guard for isolated Windows environments ONLY, 3: Enable Microsoft Defender Application Guard for Microsoft Edge AND isolated Windows environments) | `0`, `1`, `2`, `3` | +| **ClipboardSettings** | Write | String | Clipboard behavior settings (0: Completely turns Off the clipboard functionality for the Application Guard., 1: Turns On clipboard operation from an isolated session to the host., 2: Turns On clipboard operation from the host to an isolated session., 3: Turns On clipboard operation in both the directions.) | `0`, `1`, `2`, `3` | +| **SaveFilesToHost** | Write | String | Allow files to download and save to the host operating system (0: The user cannot download files from Edge in the container to the host file system. When the policy is not configured, it is the same as disabled (0)., 1: Turns on the functionality to allow users to download files from Edge in the container to the host file system.) | `0`, `1` | +| **InstallWindowsDefenderApplicationGuard** | Write | String | Install Windows defender application guard (install: Install) | `install` | +| **ClipboardFileType** | Write | String | Clipboard content options (1: Allow text copying., 2: Allow image copying., 3: Allow text and image copying.) | `1`, `2`, `3` | +| **AllowPersistence** | Write | String | Allow data persistence (0: Application Guard discards user-downloaded files and other items (such as, cookies, Favorites, and so on) during machine restart or user log-off., 1: Application Guard saves user-downloaded files and other items (such as, cookies, Favorites, and so on) for use in future Application Guard sessions.) | `0`, `1` | +| **AllowVirtualGPU** | Write | String | Allow hardware-accelerated rendering (0: Cannot access the vGPU and uses the CPU to support rendering graphics. When the policy is not configured, it is the same as disabled (0)., 1: Turns on the functionality to access the vGPU offloading graphics rendering from the CPU. This can create a faster experience when working with graphics intense websites or watching video within the container.) | `0`, `1` | +| **PrintingSettings** | Write | SInt32Array[] | Print Settings (0: Disables all print functionality., 1: Enables only XPS printing., 2: Enables only PDF printing., 4: Enables only local printing., 8: Enables only network printing.) | `0`, `1`, `2`, `4`, `8` | +| **AllowCameraMicrophoneRedirection** | Write | String | Allow camera and microphone access (0: Microsoft Defender Application Guard cannot access the device's camera and microphone. When the policy is not configured, it is the same as disabled (0)., 1: Turns on the functionality to allow Microsoft Defender Application Guard to access the device's camera and microphone.) | `0`, `1` | +| **AuditApplicationGuard** | Write | String | Audit Application Guard (0: Audit event logs aren't collected for Application Guard., 1: Application Guard inherits its auditing policies from system and starts to audit security events for Application Guard container.) | `0`, `1` | +| **CertificateThumbprints** | Write | StringArray[] | Certificate Thumbprints | | +| **EnterpriseIPRange** | Write | StringArray[] | Enterprise IP Range | | +| **EnterpriseCloudResources** | Write | StringArray[] | Enterprise Cloud Resources | | +| **EnterpriseNetworkDomainNames** | Write | StringArray[] | Enterprise Network Domain Names | | +| **EnterpriseProxyServers** | Write | StringArray[] | Enterprise Proxy Servers | | +| **EnterpriseInternalProxyServers** | Write | StringArray[] | Enterprise Internal Proxy Servers | | +| **NeutralResources** | Write | StringArray[] | Neutral Resources | | +| **EnterpriseProxyServersAreAuthoritative** | Write | String | Enterprise Proxy Servers Are Authoritative (1: Enable, 0: Disable) | `1`, `0` | +| **EnterpriseIPRangesAreAuthoritative** | Write | String | Enterprise IP Ranges Are Authoritative (1: Enable, 0: Disable) | `1`, `0` | +| **Assignments** | Write | MSFT_DeviceManagementConfigurationPolicyAssignments[] | Represents the assignment to the Intune policy. | | +| **Ensure** | Write | String | Present ensures the policy exists, absent ensures it is removed. | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials of the Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **ApplicationSecret** | Write | PSCredential | Secret of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + +### MSFT_DeviceManagementConfigurationPolicyAssignments + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **dataType** | Write | String | The type of the target assignment. | `#microsoft.graph.groupAssignmentTarget`, `#microsoft.graph.allLicensedUsersAssignmentTarget`, `#microsoft.graph.allDevicesAssignmentTarget`, `#microsoft.graph.exclusionGroupAssignmentTarget`, `#microsoft.graph.configurationManagerCollectionAssignmentTarget` | +| **deviceAndAppManagementAssignmentFilterType** | Write | String | The type of filter of the target assignment i.e. Exclude or Include. Possible values are:none, include, exclude. | `none`, `include`, `exclude` | +| **deviceAndAppManagementAssignmentFilterId** | Write | String | The Id of the filter for the target assignment. | | +| **groupId** | Write | String | The group Id that is the target of the assignment. | | +| **groupDisplayName** | Write | String | The group Display Name that is the target of the assignment. | | +| **collectionId** | Write | String | The collection Id that is the target of the assignment.(ConfigMgr) | | + + +## Description + +Intune App And Browser Isolation Policy for Windows10 + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - DeviceManagementConfiguration.Read.All + +- **Update** + + - DeviceManagementConfiguration.ReadWrite.All + +#### Application permissions + +- **Read** + + - DeviceManagementConfiguration.Read.All + +- **Update** + + - DeviceManagementConfiguration.ReadWrite.All + +## Examples + +### Example 1 + +This example creates a new Device Remediation. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneAppAndBrowserIsolationPolicyWindows10 'ConfigureAppAndBrowserIsolationPolicyWindows10' + { + Assignments = @( + MSFT_DeviceManagementConfigurationPolicyAssignments{ + deviceAndAppManagementAssignmentFilterType = 'none' + dataType = '#microsoft.graph.groupAssignmentTarget' + groupId = '11111111-1111-1111-1111-111111111111' + } + ); + AllowCameraMicrophoneRedirection = "1"; + AllowPersistence = "0"; + AllowVirtualGPU = "0"; + AllowWindowsDefenderApplicationGuard = "1"; + ClipboardFileType = "1"; + ClipboardSettings = "0"; + Description = 'Description' + DisplayName = "App and Browser Isolation"; + Ensure = "Present"; + Id = '00000000-0000-0000-0000-000000000000' + InstallWindowsDefenderApplicationGuard = "install"; + SaveFilesToHost = "0"; + RoleScopeTagIds = @("0"); + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} +``` + +### Example 2 + +This example updates a new Device Remediation. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneAppAndBrowserIsolationPolicyWindows10 'ConfigureAppAndBrowserIsolationPolicyWindows10' + { + Assignments = @( + MSFT_DeviceManagementConfigurationPolicyAssignments{ + deviceAndAppManagementAssignmentFilterType = 'none' + dataType = '#microsoft.graph.groupAssignmentTarget' + groupId = '11111111-1111-1111-1111-111111111111' + } + ); + AllowCameraMicrophoneRedirection = "0"; # Updated property + AllowPersistence = "0"; + AllowVirtualGPU = "0"; + AllowWindowsDefenderApplicationGuard = "1"; + ClipboardFileType = "1"; + ClipboardSettings = "0"; + Description = 'Description' + DisplayName = "App and Browser Isolation"; + Ensure = "Present"; + Id = '00000000-0000-0000-0000-000000000000' + InstallWindowsDefenderApplicationGuard = "install"; + SaveFilesToHost = "0"; + RoleScopeTagIds = @("0"); + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} +``` + +### Example 3 + +This example removes a Device Remediation. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneAppAndBrowserIsolationPolicyWindows10 'ConfigureAppAndBrowserIsolationPolicyWindows10' + { + Id = '00000000-0000-0000-0000-000000000000' + DisplayName = 'App and Browser Isolation' + Ensure = 'Absent' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} +``` + From f6207f3fa3d3f6c691189288b29038820ebb1a1f Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 7 Oct 2024 12:18:48 +0000 Subject: [PATCH 082/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 68ed19e390..3945eb3cd8 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -19429,6 +19429,171 @@ } ] }, + { + "ClassName": "MSFT_IntuneAppAndBrowserIsolationPolicyWindows10", + "Parameters": [ + { + "CIMType": "String", + "Name": "Description", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Key" + }, + { + "CIMType": "String[]", + "Name": "RoleScopeTagIds", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Id", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AllowWindowsDefenderApplicationGuard", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ClipboardSettings", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "SaveFilesToHost", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "InstallWindowsDefenderApplicationGuard", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ClipboardFileType", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AllowPersistence", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AllowVirtualGPU", + "Option": "Write" + }, + { + "CIMType": "SInt32[]", + "Name": "PrintingSettings", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AllowCameraMicrophoneRedirection", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AuditApplicationGuard", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "CertificateThumbprints", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "EnterpriseIPRange", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "EnterpriseCloudResources", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "EnterpriseNetworkDomainNames", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "EnterpriseProxyServers", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "EnterpriseInternalProxyServers", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "NeutralResources", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "EnterpriseProxyServersAreAuthoritative", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "EnterpriseIPRangesAreAuthoritative", + "Option": "Write" + }, + { + "CIMType": "MSFT_DeviceManagementConfigurationPolicyAssignments[]", + "Name": "Assignments", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "ApplicationSecret", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_IntuneAppCategory", "Parameters": [ From 9fd4baceabd093874ddda74ef9f716c211dd3340 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 7 Oct 2024 12:19:24 +0000 Subject: [PATCH 083/252] Updated {Create} Intune Integration Tests --- ...M365DSCIntegration.INTUNE.Create.Tests.ps1 | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 index d61fd36960..4a7a92a437 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 @@ -106,6 +106,32 @@ TenantId = $TenantId; CertificateThumbprint = $CertificateThumbprint; } + IntuneAppAndBrowserIsolationPolicyWindows10 'ConfigureAppAndBrowserIsolationPolicyWindows10' + { + Assignments = @( + MSFT_DeviceManagementConfigurationPolicyAssignments{ + deviceAndAppManagementAssignmentFilterType = 'none' + dataType = '#microsoft.graph.groupAssignmentTarget' + groupId = '11111111-1111-1111-1111-111111111111' + } + ); + AllowCameraMicrophoneRedirection = "1"; + AllowPersistence = "0"; + AllowVirtualGPU = "0"; + AllowWindowsDefenderApplicationGuard = "1"; + ClipboardFileType = "1"; + ClipboardSettings = "0"; + Description = 'Description' + DisplayName = "App and Browser Isolation"; + Ensure = "Present"; + Id = '00000000-0000-0000-0000-000000000000' + InstallWindowsDefenderApplicationGuard = "install"; + SaveFilesToHost = "0"; + RoleScopeTagIds = @("0"); + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } IntuneAppCategory 'IntuneAppCategory-Data Management' { Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; From 6889a1ad9bff67e9da3d656f5cba5b55bd684196 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 7 Oct 2024 12:19:42 +0000 Subject: [PATCH 084/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index b836530747..121abd66c4 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -19489,6 +19489,171 @@ } ] }, + { + "ClassName": "MSFT_IntuneAppAndBrowserIsolationPolicyWindows10", + "Parameters": [ + { + "CIMType": "String", + "Name": "Description", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Key" + }, + { + "CIMType": "String[]", + "Name": "RoleScopeTagIds", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Id", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AllowWindowsDefenderApplicationGuard", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ClipboardSettings", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "SaveFilesToHost", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "InstallWindowsDefenderApplicationGuard", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ClipboardFileType", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AllowPersistence", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AllowVirtualGPU", + "Option": "Write" + }, + { + "CIMType": "SInt32[]", + "Name": "PrintingSettings", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AllowCameraMicrophoneRedirection", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AuditApplicationGuard", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "CertificateThumbprints", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "EnterpriseIPRange", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "EnterpriseCloudResources", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "EnterpriseNetworkDomainNames", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "EnterpriseProxyServers", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "EnterpriseInternalProxyServers", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "NeutralResources", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "EnterpriseProxyServersAreAuthoritative", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "EnterpriseIPRangesAreAuthoritative", + "Option": "Write" + }, + { + "CIMType": "MSFT_DeviceManagementConfigurationPolicyAssignments[]", + "Name": "Assignments", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "ApplicationSecret", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_IntuneAppCategory", "Parameters": [ From 74982dff7cc44a937a5af7999e7b5894986905a6 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 7 Oct 2024 08:30:45 -0400 Subject: [PATCH 085/252] Check-in --- CHANGELOG.md | 3 +++ Modules/Microsoft365DSC/Dependencies/Manifest.psd1 | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9de9e3fec9..8e1b7d6bcd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ * M365DSCDRGUtil * Fixes an issue for the handling of skipped one-property elements in the Settings Catalog. FIXES [#5086](https://github.com/microsoft/Microsoft365DSC/issues/5086) +* DEPENDENCIES + * Updated DSCParser to version 2.0.0.11 + * Updated ReverseDSC to version 2.0.0.21 # 1.24.1002.1 diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index d2d088cc8d..12b67f090a 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -22,7 +22,7 @@ }, @{ ModuleName = 'DSCParser' - RequiredVersion = '2.0.0.10' + RequiredVersion = '2.0.0.11' }, @{ ModuleName = 'ExchangeOnlineManagement' @@ -137,7 +137,7 @@ }, @{ ModuleName = 'ReverseDSC' - RequiredVersion = '2.0.0.20' + RequiredVersion = '2.0.0.21' } ) } From 1349fc61b117b319973cfca7ffbf065945d5eeff Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Mon, 7 Oct 2024 14:32:00 +0200 Subject: [PATCH 086/252] Revert a6fd1ef - Changes to Generate Permission List --- .../Scheduled - Generate Permission List.yml | 286 +++--------------- 1 file changed, 49 insertions(+), 237 deletions(-) diff --git a/.github/workflows/Scheduled - Generate Permission List.yml b/.github/workflows/Scheduled - Generate Permission List.yml index 9a918fa9fa..55965360ac 100644 --- a/.github/workflows/Scheduled - Generate Permission List.yml +++ b/.github/workflows/Scheduled - Generate Permission List.yml @@ -1,237 +1,49 @@ -function Invoke-TestHarness -{ - [CmdletBinding()] - param - ( - [Parameter()] - [System.String] - $TestResultsFile, - - [Parameter()] - [System.String] - $DscTestsPath, - - [Parameter()] - [Switch] - $IgnoreCodeCoverage - ) - - $sw = [System.Diagnostics.StopWatch]::startnew() - - $MaximumFunctionCount = 32767 - Write-Host -Object 'Running all Microsoft365DSC Unit Tests' - - $repoDir = Join-Path -Path $PSScriptRoot -ChildPath '..\' -Resolve - - $oldModPath = $env:PSModulePath - $env:PSModulePath = $env:PSModulePath + [System.IO.Path]::PathSeparator + (Join-Path -Path $repoDir -ChildPath 'Modules\Microsoft365DSC') - - $testCoverageFiles = @() - if ($IgnoreCodeCoverage.IsPresent -eq $false) - { - Get-ChildItem -Path "$repoDir\Modules\Microsoft365DSC\DSCResources\**\*.psm1" -Recurse | ForEach-Object { - if ($_.FullName -notlike '*\DSCResource.Tests\*') - { - $testCoverageFiles += $_.FullName - } - } - } - - Import-Module -Name "$repoDir/Modules/Microsoft365DSC/Microsoft365DSC.psd1" - Import-Module -Name PSDesiredStateConfiguration -Global -Prefix 'Pwsh' -Force - $testsToRun = @() - - # Run Unit Tests - $versionsPath = Join-Path -Path $repoDir -ChildPath '\Tests\Unit\Stubs\' - # Import the first stub found so that there is a base module loaded before the tests start - $firstStub = Join-Path -Path $repoDir ` - -ChildPath '\Tests\Unit\Stubs\Microsoft365.psm1' - Import-Module $firstStub -WarningAction SilentlyContinue - - $stubPath = Join-Path -Path $repoDir ` - -ChildPath '\Tests\Unit\Stubs\Microsoft365.psm1' - - # DSC Common Tests - $getChildItemParameters = @{ - Path = (Join-Path -Path $repoDir -ChildPath '\Tests\Unit') - Recurse = $true - Filter = '*.Tests.ps1' - } - - # Get all tests '*.Tests.ps1'. - $commonTestFiles = Get-ChildItem @getChildItemParameters - - # Remove DscResource.Tests unit tests. - $commonTestFiles = $commonTestFiles | Where-Object -FilterScript { - $_.FullName -notmatch 'DSCResource.Tests\\Tests' - } - - $testsToRun += @( $commonTestFiles.FullName ) - - $filesToExecute = @() - if ($DscTestsPath -ne '') - { - $filesToExecute += $DscTestsPath - } - else - { - foreach ($testToRun in $testsToRun) - { - $filesToExecute += $testToRun - } - } - - $Params = [ordered]@{ - Path = $filesToExecute - } - - $Container = New-PesterContainer @Params - - $Configuration = [PesterConfiguration]@{ - Run = @{ - Container = $Container - PassThru = $true - } - Output = @{ - Verbosity = 'Normal' - } - Should = @{ - ErrorAction = 'Continue' - } - } - - if ([String]::IsNullOrEmpty($TestResultsFile) -eq $false) - { - $Configuration.Output.Enabled = $true - $Configuration.Output.OutputFormat = 'NUnitXml' - $Configuration.Output.OutputFile = $TestResultsFile - } - - if ($IgnoreCodeCoverage.IsPresent -eq $false) - { - $Configuration.CodeCoverage.Enabled = $true - $Configuration.CodeCoverage.Path = $testCoverageFiles - $Configuration.CodeCoverage.OutputPath = 'CodeCov.xml' - $Configuration.CodeCoverage.OutputFormat = 'JaCoCo' - $Configuration.CodeCoverage.UseBreakpoints = $false - } - - $results = Invoke-Pester -Configuration $Configuration - - $message = 'Running the tests took {0} hours, {1} minutes, {2} seconds' -f $sw.Elapsed.Hours, $sw.Elapsed.Minutes, $sw.Elapsed.Seconds - Write-Host -Object $message - - $env:PSModulePath = $oldModPath - Write-Host -Object 'Completed running all Microsoft365DSC Unit Tests' - - return $results -} - -function Get-M365DSCAllGraphPermissionsList -{ - [CmdletBinding()] - [OutputType([System.String[]])] - param() - - $allModules = Get-module Microsoft.graph.* -ListAvailable - $allPermissions = @() - foreach ($module in $allModules) - { - $cmds = Get-Command -Module $module.Name - foreach ($cmd in $cmds) - { - $graphInfo = Find-MgGraphCommand -Command $cmd.Name -ErrorAction SilentlyContinue - if ($null -ne $graphInfo) - { - $permissions = $graphInfo.Permissions | Where-Object -FilterScript {$_.PermissionType -eq 'Application'} - $allPermissions += $permissions.Name - } - } - } - - $allPermissions+= @('OrgSettings-Microsoft365Install.Read.All', ` - 'OrgSettings-Forms.Read.All', ` - 'OrgSettings-Todo.Read.All', ` - 'OrgSettings-AppsAndServices.Read.All', ` - 'OrgSettings-DynamicsVoice.Read.All', ` - 'ReportSettings.Read.All', ` - 'RoleManagementPolicy.Read.Directory', ` - 'RoleEligibilitySchedule.Read.Directory', ` - 'Agreement.Read.All', ` - 'Policy.ReadWrite.ConditionalAccess', ` - 'Policy.Read.ConditionalAccess', ` - 'Policy.ReadWrite.AuthenticationMethod', ` - 'SharePointTenantSettings.Read.All', ` - 'AppCatalog.ReadWrite.All', ` - 'TeamSettings.ReadWrite.All', ` - 'Channel.Delete.All', ` - 'ChannelSettings.ReadWrite.All', ` - 'ChannelMember.ReadWrite.All', ` - 'ChannelSettings.Read.All', - 'EntitlementManagement.Read.All', - 'ExternalConnection.Read.All') - $roles = $allPermissions | Select-Object -Unique | Sort-Object -Descending:$false - return $roles -} - -function Invoke-QualityChecksHarness -{ - [CmdletBinding()] - param () - - $sw = [System.Diagnostics.StopWatch]::startnew() - - Write-Host -Object 'Running all Quality Check Tests' - - $repoDir = Join-Path -Path $PSScriptRoot -ChildPath '..\' -Resolve - - $oldModPath = $env:PSModulePath - $env:PSModulePath = $env:PSModulePath + [System.IO.Path]::PathSeparator + (Join-Path -Path $repoDir -ChildPath 'modules\Microsoft365DSC') - - # DSC Common Tests - $getChildItemParameters = @{ - Path = (Join-Path -Path $repoDir -ChildPath '\Tests\QA') - Filter = '*.Tests.ps1' - } - - # Get all tests '*.Tests.ps1'. - $commonTestFiles = Get-ChildItem @getChildItemParameters - - $testsToRun = @() - $testsToRun += @( $commonTestFiles.FullName ) - - $filesToExecute = @() - foreach ($testToRun in $testsToRun) - { - $filesToExecute += $testToRun - } - - $Params = [ordered]@{ - Path = $filesToExecute - } - - $Container = New-PesterContainer @Params - - $Configuration = [PesterConfiguration]@{ - Run = @{ - Container = $Container - PassThru = $true - } - Output = @{ - Verbosity = 'Detailed' - } - Should = @{ - ErrorAction = 'Continue' - } - } - - $results = Invoke-Pester -Configuration $Configuration - - $message = 'Running the tests took {0} hours, {1} minutes, {2} seconds' -f $sw.Hours, $sw.Minutes, $sw.Seconds - Write-Host -Object $message - - $env:PSModulePath = $oldModPath - Write-Host -Object 'Completed running all Quality Check Tests' - - return $results -} +name: Generate Permissions List +on: + push: + branches: + - Master + - Dev + schedule: + - cron: "0 0 * * *" + +jobs: + # This workflow contains a single job called "build" + GeneratePermissionsList: + # The type of runner that the job will run on + runs-on: windows-latest + + permissions: write-all + + # Only when run from the main repo + if: github.repository == 'microsoft/Microsoft365DSC' + # Steps represent a sequence of tasks that will be executed as part of the job + + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - name: Checkout Repository + uses: actions/checkout@v3 + + - name: Install Dependencies + shell: powershell + run: | + Import-Module './Modules/Microsoft365DSC/Microsoft365DSC.psd1' -Force; + Import-Module './Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1' -Force; + Update-M365DSCModule + - name: Get Permissions List + shell: powershell + run: | + Import-Module './Tests/TestHarness.psm1' -Force; + $permissions = Get-M365DSCAllGraphPermissionsList + $permissions -join ',' | Out-File '.\Tests\QA\Graph.PermissionList.txt' + - name: Commit Permissions List + shell: powershell + run: | + git config --local user.email "nicharl@microsoft.com" + git config --local user.name "NikCharlebois" + git add D:/a/Microsoft365DSC/Microsoft365DSC/Tests/QA/* + git pull + git commit -m "Updated Graph Permissions List" + git push + $SHA = git rev-parse HEAD + echo "commitid=$SHA" >> $env:GITHUB_OUTPUT From b4e6a222fb0d82119f63aaeb67450eb5de96ea60 Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Mon, 7 Oct 2024 14:56:12 +0200 Subject: [PATCH 087/252] Add execution policy to prereqs documentation --- docs/docs/user-guide/get-started/prerequisites.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/docs/user-guide/get-started/prerequisites.md b/docs/docs/user-guide/get-started/prerequisites.md index 243cd7322f..89c6079a8c 100644 --- a/docs/docs/user-guide/get-started/prerequisites.md +++ b/docs/docs/user-guide/get-started/prerequisites.md @@ -6,6 +6,10 @@ For Microsoft365DSC to function, you need to arrange the following components: Microsoft365DSC is supported for PowerShell version 5.1 and 7.3+. For additional details on how to leverage it with PowerShell 7, please refer to our [PowerShell 7+ Guide for Microsoft365DSC](https://microsoft365dsc.com/user-guide/get-started/powershell7-support/). +### PowerShell Execution Policy + +Microsoft365DSC consists of its own module and various PowerShell submodules. Allowing scripts to run is necessary for the successful execution of the functions. The command `Get-ExecutionPolicy` retrieves the current execution policy. Usually, it is enough if the value is set to RemoteSigned. If you encounter issues while loading scripts, set it to Unrestricted: `Set-ExecutionPolicy -ExecutionPolicy Unrestricted` + ### Windows Remote Management (WinRM) Microsoft365DSC uses the Local Configuration Manager (LCM). This requires PowerShell Remoting to be enabled. Please run either `winrm quickconfig -force` or `Enable-PSRemoting -Force -SkipNetworkProfileCheck` to enable it. From 3ed8681ea8b902c07c0b98f03b86ff36a1048f6b Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 7 Oct 2024 09:51:57 -0400 Subject: [PATCH 088/252] AADApplication FIxes --- CHANGELOG.md | 2 ++ .../MSFT_AADApplication/MSFT_AADApplication.psm1 | 16 ++++++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3fd1ff83a..13d684d8a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ # UNRELEASED +* AADApplication + * Fixed an issue trying to retrieve the beta instance. * AADDeviceRegistrationPolicy * Initial release. * AADEntitlementManagementSettings diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index d8c5b97231..3101f97fd7 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -189,8 +189,8 @@ function Get-TargetResource Write-Verbose -Message 'An instance of Azure AD App was retrieved.' - $AADBetaApp= Get-MgBetaApplication -Property "id,displayName,appId,authenticationBehaviors" -ApplicationId $ObjectID -ErrorAction SilentlyContinue - $AADAppKeyCredentials = Get-MgApplication -Property "keyCredentials" -ApplicationId $ObjectID -ErrorAction SilentlyContinue + $AADBetaApp= Get-MgBetaApplication -Property "id,displayName,appId,authenticationBehaviors" -ApplicationId $AADApp.Id -ErrorAction SilentlyContinue + $AADAppKeyCredentials = Get-MgApplication -Property "keyCredentials" -ApplicationId $AADApp.Id -ErrorAction SilentlyContinue $complexAuthenticationBehaviors = @{} if ($null -ne $AADBetaApp.authenticationBehaviors.blockAzureADGraphAccess) @@ -291,7 +291,7 @@ function Get-TargetResource $mykeyCredentials.Add('KeyId', $currentkeyCredentials.keyId) - if($null -ne $currentkeyCredentials.Key) + if($null -ne $currentkeyCredentials.Key) { $mykeyCredentials.Add('Key', [convert]::ToBase64String($currentkeyCredentials.key)) } @@ -629,7 +629,7 @@ function Set-TargetResource if ($PasswordCredentials) { Write-Warning -Message "PasswordCredentials is a readonly property and cannot be configured." - + } if ($currentParameters.AvailableToOtherTenants) @@ -934,7 +934,7 @@ function Set-TargetResource if($needToUpdateKeyCredentials -and $KeyCredentials) { Write-Verbose -Message "Updating for Azure AD Application {$($currentAADApp.DisplayName)} with KeyCredentials:`r`n$($KeyCredentials| Out-String)" - + if((currentAADApp.KeyCredentials.Length -eq 0 -and $KeyCredentials.Length -eq 1) -or (currentAADApp.KeyCredentials.Length -eq 1 -and $KeyCredentials.Length -eq 0)) { Update-MgApplication -ApplicationId $currentAADApp.Id -KeyCredentials $KeyCredentials | Out-Null @@ -1121,7 +1121,7 @@ function Test-TargetResource } $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() - + $testTargetResource = $true #Compare Cim instances @@ -1134,13 +1134,13 @@ function Test-TargetResource $testResult = Compare-M365DSCComplexObject ` -Source ($source) ` -Target ($target) - + if (-not $testResult) { Write-Verbose "TestResult returned False for $source" $testTargetResource = $false } - else { + else { $ValuesToCheck.Remove($key) | Out-Null } } From b7357ef3cbf268d53fe4b5e57dc524f3a9441181 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 7 Oct 2024 11:07:59 -0400 Subject: [PATCH 089/252] AADAminCOnsentRequestPolicy Initial Release --- .../MSFT_AADAdminConsentRequestPolicy.psm1 | 493 ++++++++++++++++++ ...FT_AADAdminConsentRequestPolicy.schema.mof | 25 + .../readme.md | 6 + .../settings.json | 32 ++ .../AADAdminConsentRequestPolicy/2-Update.ps1 | 26 + ...DSC.AADAdminConsentRequestPolicy.Tests.ps1 | 178 +++++++ 6 files changed, 760 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/MSFT_AADAdminConsentRequestPolicy.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/MSFT_AADAdminConsentRequestPolicy.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADAdminConsentRequestPolicy/2-Update.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAdminConsentRequestPolicy.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/MSFT_AADAdminConsentRequestPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/MSFT_AADAdminConsentRequestPolicy.psm1 new file mode 100644 index 0000000000..bf7568c04d --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/MSFT_AADAdminConsentRequestPolicy.psm1 @@ -0,0 +1,493 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $IsSingleInstance, + + [Parameter()] + [System.Boolean] + $IsEnabled, + + [Parameter()] + [System.Boolean] + $NotifyReviewers, + + [Parameter()] + [System.Boolean] + $RemindersEnabled, + + [Parameter()] + [System.UInt32] + $RequestDurationInDays, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Reviewers, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters | Out-Null + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + try + { + $instance = Get-MgBetaPolicyAdminConsentRequestPolicy -ErrorAction Stop + if ($null -eq $instance) + { + throw 'Could not retrieve the Admin Consent Request Policy' + } + + $reviewersValue = @() + foreach ($reviewer in $instance.Reviewers) + { + if ($reviewer.Query.Contains('/users/')) + { + $userId = $reviewer.Query.Split('/')[3] + $userInfo = Get-MgUser -UserId $userId + + $entry = @{ + ReviewerType = 'User' + ReviewerId = $userInfo.UserPrincipalName + QueryRoot = $reviewer.QueryRoot + } + } + elseif ($reviewer.Query.Contains('/groups/')) + { + $groupId = $reviewer.Query.Split('/')[3] + $groupInfo = Get-MgGroup -GroupId $groupId + $entry = @{ + ReviewerType = 'Group' + ReviewerId = $groupInfo.DisplayName + QueryRoot = $reviewer.QueryRoot + } + } + elseif ($reviewer.Query.Contains('directory/roleAssignments?$')) + { + $roleId = $reviewer.Query.Replace("/beta/roleManagement/directory/roleAssignments?`$filter=roleDefinitionId eq ", "").Replace("'", '') + $roleInfo = Get-MgBetaRoleManagementDirectoryRoleDefinition -UnifiedRoleDefinitionId $roleId + $entry = @{ + ReviewerType = 'Role' + ReviewerId = $roleInfo.DisplayName + QueryRoot = $roleInfo.QueryRoot + } + } + $reviewersValue += $entry + } + + $results = @{ + IsSingleInstance = 'Yes' + IsEnabled = $instance.IsEnabled + NotifyReviewers = $instance.NotifyReviewers + RemindersEnabled = $instance.RemindersEnabled + RequestDurationInDays = $instance.RequestDurationInDays + Reviewers = $reviewersValue + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $IsSingleInstance, + + [Parameter()] + [System.Boolean] + $IsEnabled, + + [Parameter()] + [System.Boolean] + $NotifyReviewers, + + [Parameter()] + [System.Boolean] + $RemindersEnabled, + + [Parameter()] + [System.UInt32] + $RequestDurationInDays, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Reviewers, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters | Out-Null + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + Write-Verbose -Message 'Updating the Entra Id Admin Consent Request Policy' + $reviewerValues = @() + foreach ($reviewer in $Reviewers) + { + if ($reviewer.ReviewerType -eq 'User') + { + $userInfo = Get-MgUser -Filter "UserPrincipalName eq '$($reviewer.ReviewerId)'" + $entry = @{ + Query = "/v1.0/users/$($userInfo.Id)" + QueryType = 'MicrosoftGraph' + QueryRoot = $reviewer.QueryRoot + } + $reviewerValues += $entry + } + elseif ($reviewer.ReviewerType -eq 'Group') + { + $groupInfo = Get-MgGroup -Filter "DisplayName eq '$($reviewer.ReviewerId)'" + $entry = @{ + Query = "/v1.0/groups/$($groupInfo.Id)/transitiveMembers/microsoft.graph.user" + QueryType = 'MicrosoftGraph' + QueryRoot = $reviewer.QueryRoot + } + $reviewerValues += $entry + } + elseif ($reviewer.ReviewerType -eq 'Role') + { + $roleInfo = Get-MgBetaRoleManagementDirectoryRoleDefinition -Filter "DisplayName eq '$($reviewer.ReviewerId)'" + $entry = @{ + Query = "/beta/roleManagement/directory/roleAssignments?`$filter=roleDefinitionId eq '$($roleInfo.Id)'" + QueryType = 'MicrosoftGraph' + QueryRoot = $reviewer.QueryRoot + } + $reviewerValues += $entry + } + } + + $updateParameters = @{ + IsEnabled = $IsEnabled + Reviewers = $reviewerValues + NotifyReviewers = $NotifyReviewers + RemindersEnabled = $RemindersEnabled + RequestDurationInDays = $RequestDurationInDays + } + + Update-MgBetaPolicyAdminConsentRequestPolicy -BodyParameter $updateParameters | Out-Null +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $IsSingleInstance, + + [Parameter()] + [System.Boolean] + $IsEnabled, + + [Parameter()] + [System.Boolean] + $NotifyReviewers, + + [Parameter()] + [System.Boolean] + $RemindersEnabled, + + [Parameter()] + [System.UInt32] + $RequestDurationInDays, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Reviewers, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-MgBetaPolicyAdminConsentRequestPolicy -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + $displayedKey = 'Policy' + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + IsSingleInstance = 'Yes' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + if ($Results.Reviewers.Count -gt 0) + { + $Results.Reviewers = Get-M365DSCAzureADAAdminConsentPolicyReviewerAsString $Results.Reviewers + } + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + + if ($Results.Reviewers) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "Reviewers" -IsCIMArray:$true + } + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +function Get-M365DSCAzureADAAdminConsentPolicyReviewerAsString +{ + [CmdletBinding()] + [OutputType([System.String])] + param( + [Parameter(Mandatory = $true)] + [Array] + $Reviewers + ) + + $result = " @(`r`n" + foreach ($reviewer in $reviewers) + { + $result += " MSFT_AADAdminConsentRequestPolicyReviewer {`r`n" + $result += " ReviewerType = '$($reviewer.ReviewerType)'`r`n" + $result += " ReviewerId = '$($reviewer.ReviewerId)'`r`n" + $result += " QueryRoot = '$($reviewer.QueryRoot)'`r`n" + $result += " }`r`n" + } + $result += ' )' + return $result +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/MSFT_AADAdminConsentRequestPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/MSFT_AADAdminConsentRequestPolicy.schema.mof new file mode 100644 index 0000000000..db26c3a5fa --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/MSFT_AADAdminConsentRequestPolicy.schema.mof @@ -0,0 +1,25 @@ +[ClassVersion("1.0.0")] +class MSFT_AADAdminConsentRequestPolicyReviewer +{ + [Write, Description("Type of reviewwer. Can be User, Group or Role")] String ReviewerType; + [Write, Description("Identifier for the reviewer instance.")] String ReviewerId; + [Write, Description("Indicates the relative source of the query.")] String QueryRoot; +}; + +[ClassVersion("1.0.0.0"), FriendlyName("AADAdminConsentRequestPolicy")] +class MSFT_AADAdminConsentRequestPolicy : OMI_BaseResource +{ + [Key, Description("Only valid value is 'Yes'."), ValueMap{"Yes"}, Values{"Yes"}] String IsSingleInstance; + [Write, Description("")] Boolean IsEnabled; + [Write, Description("")] Boolean NotifyReviewers; + [Write, Description("")] Boolean RemindersEnabled; + [Write, Description("")] UInt32 RequestDurationInDays; + [Write, Description(""), EmbeddedInstance("MSFT_AADAdminConsentRequestPolicyReviewer")] String Reviewers[]; + + [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/readme.md new file mode 100644 index 0000000000..32e0e7fb27 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/readme.md @@ -0,0 +1,6 @@ + +# ResourceName + +## Description + +##TODO - Provide a short description of what the resource is set to configure. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/settings.json new file mode 100644 index 0000000000..edf14b05e4 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName": "ResourceName", + "description": "Description of what the resource is about.", + "roles": { + "read": [ + "Role" + ], + "update": [ + "Role" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [ + { + "name": "Permission for Monitoring and Export" + } + ], + "update": [ + { + "name": "Permission for deploying" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADAdminConsentRequestPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADAdminConsentRequestPolicy/2-Update.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADAdminConsentRequestPolicy/2-Update.ps1 @@ -0,0 +1,26 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAdminConsentRequestPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAdminConsentRequestPolicy.Tests.ps1 new file mode 100644 index 0000000000..780e0f343d --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAdminConsentRequestPolicy.Tests.ps1 @@ -0,0 +1,178 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -GenericStubModule $GenericStubPath + +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + ##TODO - Mock any Remove/Set/New cmdlets + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + Context -Name "The instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return $null + Mock -CommandName Get-Cmdlet -MockWith { + return $null + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should create a new instance from the Set method' { + ##TODO - Replace the New-Cmdlet by the appropriate one + Set-TargetResource @testParams + Should -Invoke -CommandName New-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Absent' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should remove the instance from the Set method' { + Set-TargetResource @testParams + ##TODO - Replace the Remove-Cmdlet by the appropriate one + Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return the desired values + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return a drift + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + ##TODO - Replace the Update-Cmdlet by the appropriate one + Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope From 470af46cbf26f327db66c10877d57bac20ed7f25 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 7 Oct 2024 12:09:53 -0400 Subject: [PATCH 090/252] Ready for merge --- CHANGELOG.md | 2 + .../MSFT_AADAdminConsentRequestPolicy.psm1 | 58 ++++-- ...FT_AADAdminConsentRequestPolicy.schema.mof | 1 - .../AADAdminConsentRequestPolicy/2-Update.ps1 | 34 ++- ...DSC.AADAdminConsentRequestPolicy.Tests.ps1 | 197 +++++++++++------- Tests/Unit/Stubs/Microsoft365.psm1 | 6 + 6 files changed, 201 insertions(+), 97 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3fd1ff83a..9a36a9e306 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ # UNRELEASED +* AADAdminConsentRequestPolicy + * Initial release. * AADDeviceRegistrationPolicy * Initial release. * AADEntitlementManagementSettings diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/MSFT_AADAdminConsentRequestPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/MSFT_AADAdminConsentRequestPolicy.psm1 index bf7568c04d..317ea07cd2 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/MSFT_AADAdminConsentRequestPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/MSFT_AADAdminConsentRequestPolicy.psm1 @@ -88,7 +88,6 @@ function Get-TargetResource $entry = @{ ReviewerType = 'User' ReviewerId = $userInfo.UserPrincipalName - QueryRoot = $reviewer.QueryRoot } } elseif ($reviewer.Query.Contains('/groups/')) @@ -98,7 +97,6 @@ function Get-TargetResource $entry = @{ ReviewerType = 'Group' ReviewerId = $groupInfo.DisplayName - QueryRoot = $reviewer.QueryRoot } } elseif ($reviewer.Query.Contains('directory/roleAssignments?$')) @@ -108,7 +106,6 @@ function Get-TargetResource $entry = @{ ReviewerType = 'Role' ReviewerId = $roleInfo.DisplayName - QueryRoot = $roleInfo.QueryRoot } } $reviewersValue += $entry @@ -212,7 +209,6 @@ function Set-TargetResource Add-M365DSCTelemetryEvent -Data $data #endregion - Write-Verbose -Message 'Updating the Entra Id Admin Consent Request Policy' $reviewerValues = @() foreach ($reviewer in $Reviewers) { @@ -220,9 +216,8 @@ function Set-TargetResource { $userInfo = Get-MgUser -Filter "UserPrincipalName eq '$($reviewer.ReviewerId)'" $entry = @{ - Query = "/v1.0/users/$($userInfo.Id)" - QueryType = 'MicrosoftGraph' - QueryRoot = $reviewer.QueryRoot + query = "/users/$($userInfo.Id)" + queryType = 'MicrosoftGraph' } $reviewerValues += $entry } @@ -230,9 +225,8 @@ function Set-TargetResource { $groupInfo = Get-MgGroup -Filter "DisplayName eq '$($reviewer.ReviewerId)'" $entry = @{ - Query = "/v1.0/groups/$($groupInfo.Id)/transitiveMembers/microsoft.graph.user" - QueryType = 'MicrosoftGraph' - QueryRoot = $reviewer.QueryRoot + query = "/groups/$($groupInfo.Id)/transitiveMembers/microsoft.graph.user" + queryType = 'MicrosoftGraph' } $reviewerValues += $entry } @@ -240,23 +234,26 @@ function Set-TargetResource { $roleInfo = Get-MgBetaRoleManagementDirectoryRoleDefinition -Filter "DisplayName eq '$($reviewer.ReviewerId)'" $entry = @{ - Query = "/beta/roleManagement/directory/roleAssignments?`$filter=roleDefinitionId eq '$($roleInfo.Id)'" - QueryType = 'MicrosoftGraph' - QueryRoot = $reviewer.QueryRoot + query = "/roleManagement/directory/roleAssignments?`$filter=roleDefinitionId eq '$($roleInfo.Id.Replace('\u0027', ''))'" + queryType = 'MicrosoftGraph' } $reviewerValues += $entry } } $updateParameters = @{ - IsEnabled = $IsEnabled - Reviewers = $reviewerValues - NotifyReviewers = $NotifyReviewers - RemindersEnabled = $RemindersEnabled - RequestDurationInDays = $RequestDurationInDays + isEnabled = $IsEnabled + reviewers = $reviewerValues + notifyReviewers = $NotifyReviewers + remindersEnabled = $RemindersEnabled + requestDurationInDays = $RequestDurationInDays } - Update-MgBetaPolicyAdminConsentRequestPolicy -BodyParameter $updateParameters | Out-Null + $updateJSON = ConvertTo-Json $updateParameters + Write-Verbose -Message "Updating the Entra Id Admin Consent Request Policy with values: $updateJSON" + Invoke-MgGraphRequest -Method 'PUT' ` + -Uri 'https://graph.microsoft.com/beta/policies/adminConsentRequestPolicy' ` + -Body $updateJSON | Out-Null } function Test-TargetResource @@ -332,10 +329,25 @@ function Test-TargetResource Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" - $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` - -Source $($MyInvocation.MyCommand.Source) ` - -DesiredValues $PSBoundParameters ` - -ValuesToCheck $ValuesToCheck.Keys + $testResult = $true + foreach ($reviewer in $Reviewers) + { + $currentEquivalent = $CurrentValues.Reviewers | Where-Object -FilterScript {$_.ReviewerId -eq $reviewer.ReviewerId -and $_.ReviewerType -eq $reviewer.ReviewerType} + if ($null -eq $currentEquivalent) + { + $testResult = $false + Write-Verbose -Message "Couldn't find current reviewer {$($reviewer.ReviewerId)}" + } + } + + if ($testResult) + { + $ValuesToCheck.Remove('Reviewers') | Out-Null + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + } Write-Verbose -Message "Test-TargetResource returned $testResult" diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/MSFT_AADAdminConsentRequestPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/MSFT_AADAdminConsentRequestPolicy.schema.mof index db26c3a5fa..857e661017 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/MSFT_AADAdminConsentRequestPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/MSFT_AADAdminConsentRequestPolicy.schema.mof @@ -3,7 +3,6 @@ class MSFT_AADAdminConsentRequestPolicyReviewer { [Write, Description("Type of reviewwer. Can be User, Group or Role")] String ReviewerType; [Write, Description("Identifier for the reviewer instance.")] String ReviewerId; - [Write, Description("Indicates the relative source of the query.")] String QueryRoot; }; [ClassVersion("1.0.0.0"), FriendlyName("AADAdminConsentRequestPolicy")] diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADAdminConsentRequestPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADAdminConsentRequestPolicy/2-Update.ps1 index b516274848..55c72a48ec 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/AADAdminConsentRequestPolicy/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/AADAdminConsentRequestPolicy/2-Update.ps1 @@ -21,6 +21,38 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + AADAdminConsentRequestPolicy "AADAdminConsentRequestPolicy" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + IsEnabled = $True; + IsSingleInstance = "Yes"; + NotifyReviewers = $False; + RemindersEnabled = $True; + RequestDurationInDays = 30; + Reviewers = @( + MSFT_AADAdminConsentRequestPolicyReviewer { + ReviewerType = 'User' + ReviewerId = "AlexW@$TenantId" + QueryRoot = '' + } + MSFT_AADAdminConsentRequestPolicyReviewer { + ReviewerType = 'Group' + ReviewerId = 'Communications' + QueryRoot = '' + } + MSFT_AADAdminConsentRequestPolicyReviewer { + ReviewerType = 'Role' + ReviewerId = 'Attack Payload Author' + QueryRoot = '' + } + MSFT_AADAdminConsentRequestPolicyReviewer { + ReviewerType = 'Role' + ReviewerId = 'Attack Simulation Administrator' + QueryRoot = '' + } + ); + TenantId = $TenantId; + } } } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAdminConsentRequestPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAdminConsentRequestPolicy.Tests.ps1 index 780e0f343d..0e517729de 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAdminConsentRequestPolicy.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAdminConsentRequestPolicy.Tests.ps1 @@ -35,83 +35,86 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { return "Credentials" } - ##TODO - Mock any Remove/Set/New cmdlets - - # Mock Write-Host to hide output during the tests - Mock -CommandName Write-Host -MockWith { - } - $Script:exportedInstances =$null - $Script:ExportMode = $false - } - # Test contexts - Context -Name "The instance should exist but it DOES NOT" -Fixture { - BeforeAll { - $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; + Mock -Command Get-MgUser -MockWith { + return @{ + Id = '12345-12345-12345-12345-12345' + UserPrincipalName = 'John.Smith@contoso.com' } - - ##TODO - Mock the Get-Cmdlet to return $null - Mock -CommandName Get-Cmdlet -MockWith { - return $null - } - } - It 'Should return Values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' - } - It 'Should return false from the Test method' { - Test-TargetResource @testParams | Should -Be $false } - It 'Should create a new instance from the Set method' { - ##TODO - Replace the New-Cmdlet by the appropriate one - Set-TargetResource @testParams - Should -Invoke -CommandName New-Cmdlet -Exactly 1 - } - } - - Context -Name "The instance exists but it SHOULD NOT" -Fixture { - BeforeAll { - $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Absent' - Credential = $Credential; + Mock -Command Get-MgGroup -MockWith { + return @{ + Id = '12345-12345-12345-12345-12345' + DisplayName = 'Communications' } + } - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { - return @{ - - } + Mock -Command Get-MgBetaRoleManagementDirectoryRoleDefinition -MockWith { + return @{ + Id = '12345-12345-12345-12345-12345' + DisplayName = 'Attack Payload Author' } } - It 'Should return Values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Present' - } - It 'Should return false from the Test method' { - Test-TargetResource @testParams | Should -Be $false + + Mock -CommandName Invoke-MgGraphRequest -MockWith { } - It 'Should remove the instance from the Set method' { - Set-TargetResource @testParams - ##TODO - Replace the Remove-Cmdlet by the appropriate one - Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { } + $Script:exportedInstances =$null + $Script:ExportMode = $false } + # Test contexts Context -Name "The instance exists and values are already in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' + IsSingleInstance = 'Yes' + IsEnabled = $True; + NotifyReviewers = $False; + RemindersEnabled = $True; + RequestDurationInDays = 30; + Reviewers = @( + (New-CimInstance -ClassName MSFT_AADAdminConsentRequestPolicyReviewer -Property @{ + ReviewerType = 'User' + ReviewerId = 'John.Smith@contoso.com' + } -ClientOnly) + (New-CimInstance -ClassName MSFT_AADAdminConsentRequestPolicyReviewer -Property @{ + ReviewerType = 'Group' + ReviewerId = 'Communications' + } -ClientOnly) + (New-CimInstance -ClassName MSFT_AADAdminConsentRequestPolicyReviewer -Property @{ + ReviewerType = 'Role' + ReviewerId = 'Attack Payload Author' + } -ClientOnly) + ); Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return the desired values - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-MgBetaPolicyAdminConsentRequestPolicy -MockWith { return @{ - + IsEnabled = $true + NotifyReviewers = $False; + RemindersEnabled = $True; + RequestDurationInDays = 30; + Reviewers = @( + @{ + Query = "/v1.0/users/e362df2b-8f61-4e5a-9e5e-c6069f3ed2ee" + QueryType = 'MicrosoftGraph' + QueryRoot = '' + }, + @{ + Query = "/v1.0/groups/1bb47df7-d3fa-4ba8-bdbd-e9fc7541fa18/transitiveMembers/microsoft.graph.user" + QueryType = 'MicrosoftGraph' + QueryRoot = '' + } + @{ + Query = "/beta/roleManagement/directory/roleAssignments?`$filter=roleDefinitionId eq '9c6df0f2-1e7c-4dc3-b195-66dfbd24aa8f'" + QueryType = 'MicrosoftGraph' + QueryRoot = '' + } + ); } } } @@ -124,31 +127,62 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance exists and values are NOT in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' + IsSingleInstance = 'Yes' + IsEnabled = $True; + NotifyReviewers = $False; + RemindersEnabled = $True; + RequestDurationInDays = 30; + Reviewers = @( + (New-CimInstance -ClassName MSFT_AADAdminConsentRequestPolicyReviewer -Property @{ + ReviewerType = 'User' + ReviewerId = 'AlexW@contoso.com' # Drift + } -ClientOnly) + (New-CimInstance -ClassName MSFT_AADAdminConsentRequestPolicyReviewer -Property @{ + ReviewerType = 'Group' + ReviewerId = 'Communications' + } -ClientOnly) + (New-CimInstance -ClassName MSFT_AADAdminConsentRequestPolicyReviewer -Property @{ + ReviewerType = 'Role' + ReviewerId = 'Attack Payload Author' + } -ClientOnly) + ); Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return a drift - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-MgBetaPolicyAdminConsentRequestPolicy -MockWith { return @{ - + IsEnabled = $true + NotifyReviewers = $False; + RemindersEnabled = $True; + RequestDurationInDays = 30; + Reviewers = @( + @{ + Query = "/v1.0/users/e362df2b-8f61-4e5a-9e5e-c6069f3ed2ee" + QueryType = 'MicrosoftGraph' + QueryRoot = '' + }, + @{ + Query = "/v1.0/groups/1bb47df7-d3fa-4ba8-bdbd-e9fc7541fa18/transitiveMembers/microsoft.graph.user" + QueryType = 'MicrosoftGraph' + QueryRoot = '' + } + @{ + Query = "/beta/roleManagement/directory/roleAssignments?`$filter=roleDefinitionId eq '9c6df0f2-1e7c-4dc3-b195-66dfbd24aa8f'" + QueryType = 'MicrosoftGraph' + QueryRoot = '' + } + ); } } } - It 'Should return Values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Present' - } - It 'Should return false from the Test method' { Test-TargetResource @testParams | Should -Be $false } It 'Should call the Set method' { Set-TargetResource @testParams - ##TODO - Replace the Update-Cmdlet by the appropriate one - Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + Should -Invoke -CommandName Invoke-MgGraphRequest -Exactly 1 } } @@ -160,10 +194,29 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-MgBetaPolicyAdminConsentRequestPolicy -MockWith { return @{ - + IsEnabled = $true + NotifyReviewers = $False; + RemindersEnabled = $True; + RequestDurationInDays = 30; + Reviewers = @( + @{ + Query = "/v1.0/users/e362df2b-8f61-4e5a-9e5e-c6069f3ed2ee" + QueryType = 'MicrosoftGraph' + QueryRoot = '' + }, + @{ + Query = "/v1.0/groups/1bb47df7-d3fa-4ba8-bdbd-e9fc7541fa18/transitiveMembers/microsoft.graph.user" + QueryType = 'MicrosoftGraph' + QueryRoot = '' + } + @{ + Query = "/beta/roleManagement/directory/roleAssignments?`$filter=roleDefinitionId eq '9c6df0f2-1e7c-4dc3-b195-66dfbd24aa8f'" + QueryType = 'MicrosoftGraph' + QueryRoot = '' + } + ); } } } diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 94dc03f82e..fa8243de08 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -24,6 +24,12 @@ function Get-MgBetaPolicyDeviceRegistrationPolicy param() } +function Get-MgBetaPolicyAdminConsentRequestPolicy +{ + [CmdletBinding()] + param() +} + #region Microsoft.Graph.Beta.Applications function Get-MgBetaApplication { From 37bbb4bdb7642ec49e2a072a9551a2ef2ed442d6 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 7 Oct 2024 12:27:52 -0400 Subject: [PATCH 091/252] Updates --- .../MSFT_AADAdminConsentRequestPolicy.schema.mof | 10 +++++----- .../MSFT_AADAdminConsentRequestPolicy/readme.md | 4 ++-- .../settings.json | 16 ++++++---------- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/MSFT_AADAdminConsentRequestPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/MSFT_AADAdminConsentRequestPolicy.schema.mof index 857e661017..f06f5c010f 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/MSFT_AADAdminConsentRequestPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/MSFT_AADAdminConsentRequestPolicy.schema.mof @@ -9,11 +9,11 @@ class MSFT_AADAdminConsentRequestPolicyReviewer class MSFT_AADAdminConsentRequestPolicy : OMI_BaseResource { [Key, Description("Only valid value is 'Yes'."), ValueMap{"Yes"}, Values{"Yes"}] String IsSingleInstance; - [Write, Description("")] Boolean IsEnabled; - [Write, Description("")] Boolean NotifyReviewers; - [Write, Description("")] Boolean RemindersEnabled; - [Write, Description("")] UInt32 RequestDurationInDays; - [Write, Description(""), EmbeddedInstance("MSFT_AADAdminConsentRequestPolicyReviewer")] String Reviewers[]; + [Write, Description("Determines if the policy is enabled or not.")] Boolean IsEnabled; + [Write, Description("Specifies whether reviewers will receive notifications.")] Boolean NotifyReviewers; + [Write, Description("Specifies whether reviewers will receive reminder emails.")] Boolean RemindersEnabled; + [Write, Description("Specifies the duration the request is active before it automatically expires if no decision is applied.")] UInt32 RequestDurationInDays; + [Write, Description("The list of reviewers for the admin consent."), EmbeddedInstance("MSFT_AADAdminConsentRequestPolicyReviewer")] String Reviewers[]; [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/readme.md index 32e0e7fb27..bf9bf28b72 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/readme.md @@ -1,6 +1,6 @@ -# ResourceName +# AADAdminConsentRequestPolicy ## Description -##TODO - Provide a short description of what the resource is set to configure. +Configures the Admin Consent Request Policy in Entra Id. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/settings.json index edf14b05e4..ccd7e87b95 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/settings.json @@ -1,13 +1,9 @@ { - "resourceName": "ResourceName", - "description": "Description of what the resource is about.", + "resourceName": "AADAdminConsentRequestPolicy", + "description": "Configures the Admin Consent Request Policy in Entra Id.", "roles": { - "read": [ - "Role" - ], - "update": [ - "Role" - ] + "read": [], + "update": [] }, "permissions": { "graph": { @@ -18,12 +14,12 @@ "application": { "read": [ { - "name": "Permission for Monitoring and Export" + "name": "Policy.Read.All" } ], "update": [ { - "name": "Permission for deploying" + "name": "Policy.ReadWrite.ConsentRequest" } ] } From e88597e6570fe8f5310d6ecb9bec3f52f35663b3 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 7 Oct 2024 12:43:52 -0400 Subject: [PATCH 092/252] Update 2-Update.ps1 --- .../Resources/AADAdminConsentRequestPolicy/2-Update.ps1 | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADAdminConsentRequestPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADAdminConsentRequestPolicy/2-Update.ps1 index 55c72a48ec..9f032afb5c 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/AADAdminConsentRequestPolicy/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/AADAdminConsentRequestPolicy/2-Update.ps1 @@ -34,22 +34,18 @@ Configuration Example MSFT_AADAdminConsentRequestPolicyReviewer { ReviewerType = 'User' ReviewerId = "AlexW@$TenantId" - QueryRoot = '' } MSFT_AADAdminConsentRequestPolicyReviewer { ReviewerType = 'Group' ReviewerId = 'Communications' - QueryRoot = '' } MSFT_AADAdminConsentRequestPolicyReviewer { ReviewerType = 'Role' ReviewerId = 'Attack Payload Author' - QueryRoot = '' } MSFT_AADAdminConsentRequestPolicyReviewer { ReviewerType = 'Role' ReviewerId = 'Attack Simulation Administrator' - QueryRoot = '' } ); TenantId = $TenantId; From bf22d090b8442e4f58de66ddc3f77fd9b89d442b Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 7 Oct 2024 16:59:30 +0000 Subject: [PATCH 093/252] Updated Resources and Cmdlet documentation pages --- .../azure-ad/AADAdminConsentRequestPolicy.md | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 docs/docs/resources/azure-ad/AADAdminConsentRequestPolicy.md diff --git a/docs/docs/resources/azure-ad/AADAdminConsentRequestPolicy.md b/docs/docs/resources/azure-ad/AADAdminConsentRequestPolicy.md new file mode 100644 index 0000000000..2962d501f8 --- /dev/null +++ b/docs/docs/resources/azure-ad/AADAdminConsentRequestPolicy.md @@ -0,0 +1,118 @@ +# AADAdminConsentRequestPolicy + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **IsSingleInstance** | Key | String | Only valid value is 'Yes'. | `Yes` | +| **IsEnabled** | Write | Boolean | Determines if the policy is enabled or not. | | +| **NotifyReviewers** | Write | Boolean | Specifies whether reviewers will receive notifications. | | +| **RemindersEnabled** | Write | Boolean | Specifies whether reviewers will receive reminder emails. | | +| **RequestDurationInDays** | Write | UInt32 | Specifies the duration the request is active before it automatically expires if no decision is applied. | | +| **Reviewers** | Write | MSFT_AADAdminConsentRequestPolicyReviewer[] | The list of reviewers for the admin consent. | | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + +### MSFT_AADAdminConsentRequestPolicyReviewer + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **ReviewerType** | Write | String | Type of reviewwer. Can be User, Group or Role | | +| **ReviewerId** | Write | String | Identifier for the reviewer instance. | | + + +## Description + +Configures the Admin Consent Request Policy in Entra Id. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - Policy.Read.All + +- **Update** + + - Policy.ReadWrite.ConsentRequest + +## Examples + +### Example 1 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADAdminConsentRequestPolicy "AADAdminConsentRequestPolicy" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + IsEnabled = $True; + IsSingleInstance = "Yes"; + NotifyReviewers = $False; + RemindersEnabled = $True; + RequestDurationInDays = 30; + Reviewers = @( + MSFT_AADAdminConsentRequestPolicyReviewer { + ReviewerType = 'User' + ReviewerId = "AlexW@$TenantId" + } + MSFT_AADAdminConsentRequestPolicyReviewer { + ReviewerType = 'Group' + ReviewerId = 'Communications' + } + MSFT_AADAdminConsentRequestPolicyReviewer { + ReviewerType = 'Role' + ReviewerId = 'Attack Payload Author' + } + MSFT_AADAdminConsentRequestPolicyReviewer { + ReviewerType = 'Role' + ReviewerId = 'Attack Simulation Administrator' + } + ); + TenantId = $TenantId; + } + } +} +``` + From 183bebe0a3e9b9693748287cd90e44ebbb93bafc Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 7 Oct 2024 16:59:45 +0000 Subject: [PATCH 094/252] Updated {Update} AAD Integration Tests --- .../M365DSCIntegration.AAD.Update.Tests.ps1 | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 index cbb9f05169..e017945966 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 @@ -34,6 +34,35 @@ $Domain = $TenantId Node Localhost { + AADAdminConsentRequestPolicy 'AADAdminConsentRequestPolicy' + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + IsEnabled = $True; + IsSingleInstance = "Yes"; + NotifyReviewers = $False; + RemindersEnabled = $True; + RequestDurationInDays = 30; + Reviewers = @( + MSFT_AADAdminConsentRequestPolicyReviewer { + ReviewerType = 'User' + ReviewerId = "AlexW@$TenantId" + } + MSFT_AADAdminConsentRequestPolicyReviewer { + ReviewerType = 'Group' + ReviewerId = 'Communications' + } + MSFT_AADAdminConsentRequestPolicyReviewer { + ReviewerType = 'Role' + ReviewerId = 'Attack Payload Author' + } + MSFT_AADAdminConsentRequestPolicyReviewer { + ReviewerType = 'Role' + ReviewerId = 'Attack Simulation Administrator' + } + ); + TenantId = $TenantId; + } AADAdministrativeUnit 'TestUnit' { DisplayName = 'Test-Unit' From ae5813840e7eb0e86d628700c82484a21a8344e1 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 7 Oct 2024 17:01:37 +0000 Subject: [PATCH 095/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 3945eb3cd8..7fc131b48e 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -59,6 +59,86 @@ } ] }, + { + "ClassName": "MSFT_AADAdminConsentRequestPolicyReviewer", + "Parameters": [ + { + "CIMType": "String", + "Name": "ReviewerType", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ReviewerId", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_AADAdminConsentRequestPolicy", + "Parameters": [ + { + "CIMType": "String", + "Name": "IsSingleInstance", + "Option": "Key" + }, + { + "CIMType": "Boolean", + "Name": "IsEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "NotifyReviewers", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "RemindersEnabled", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "RequestDurationInDays", + "Option": "Write" + }, + { + "CIMType": "MSFT_AADAdminConsentRequestPolicyReviewer[]", + "Name": "Reviewers", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_MicrosoftGraphMember", "Parameters": [ From 47c59824f06b8829942063a00e9404f05c855cb3 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 7 Oct 2024 17:47:22 +0000 Subject: [PATCH 096/252] Updated Graph Permissions List --- Tests/QA/Graph.PermissionList.txt | Bin 3154 -> 5826 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Tests/QA/Graph.PermissionList.txt b/Tests/QA/Graph.PermissionList.txt index bb13a7818db8c6ffd065710276586ec7dd78da6f..826113f235a6a0d9238e46bc09b5d42a131a610f 100644 GIT binary patch literal 5826 zcmb_gU2hsO5ZvcV{U;y zTCKo7eX{Uz=Jd=G^jPLrzGKaE`0qk~swZi$=X_`C^EGTnuU+EV%QyVJQEvoG2HV9P zAxelngwzTM6)^T{|Jv}mC4T`wZJ_TS(mNSF#n4CmGFJDd=kjGNMn)QStzn-DIAe~U z#$jso0`s}LDQtQSC9rbdJ)~;&#|o>Vor&MxDeYM|7+=dBzIW0318Uf#ZMl)+a&Onz z0r9#{m$2EmJ0D=T0oE1bB1X4o*l6@T<7EuJYqe5?jN~F=pmD*yOlytQip(%vna%ui zG+RrTTQ=|r?K?$`H~3JOJJ`bS9cs!9OY5iheg7#>m1C7^=&bn&-59^r@0caKSKN(f zY3gHt0bkQ@j3dT4tCPzc)a(P^aL2^eB8A2kO@U!W1lbP9yO3^_dx9v7tJVlC^!OH9 z+50MHI}M{mqY9dA3pF{EEz#h#TH9rv9JCTGV^7R9_xgw^^I{%eiKau;>MD^{yR3I8 zTcQE8+wR|vi9OP_yJD;OPA><|)^Z6gm}l9E?9jj1?CDu~sO)#AU|8ehdjX%jQ?c=! zGZ(|wh};v+!}bcTaSQ26b0sSeE2X!;z|WC8&TRK(q5BD3_Dl=?8dZ?-$JlES?V+;recb;A zo_raL@fN78!0Z8jby%-^?kNoHyV<*wd!~_Z_i`!LFP+AHqfD+p-r#)P$QyYl zZ{->q@svfo@@(SwUx>7n9%JY+!(+*?r{fvY_3dqome04mI{=S6)!J1eJ#L+c`K|wrexde`9J!!F?lw*hZZik#CH%Sc@U31%ZaJN~E?JW>_WAuEVTP#D&WdvVoge|b{J3NdwW@(-W zXxkYo9%sb}mzcA|yU@Y({@st{R%OrLHNOw`a3as=d5Ml!@E^F+SGQDGj z@)g7=r>!NG1uR|sjm2DZ2P+D1D!ChJx4ak}Y0Y4yG2(OTb*@Bgg9f&U480H7KXG#zw!7nGMS%r1;&eN!7Gn#QB|}ouX1{*4r(5sj{1tmGA+=Ui>h|(**V^cJ3#Pyi_=Qom;c-z-FwB?)#hLLI$@sWt zR+JN2Z<=H^Qwrp20}_TmA4L9-C+-ir0-O`7BHqOm#5t)?JkP>oG9n-_qpdxFV#>W> z5OSlBLPAk9gO?HGPho@-vqd)rl&Nz@yq>z>Iby<&6DRu&b&n9;JPV77ICgSIIl~3g zF8UR7z;iH-z}(R4(O?uN(cfULM40I0!>1%S z?J~ha)lQk_uw_dB2<|EFco)GflkV3kN!6))H|;V(0jB!{(g6BqI%S%}2&FJkI&CiG zw@0D~bPuI&u&408v(ac=En^5mq#GtkJKcnH0Bw~MPWG8aGUzr-meqmc(dbjV$_!w} zC;o7=5621q0i$`wnKS9yJ$|m67?WPs|3q&^gaQ75G+v3E_`wg5k5Nm=b>{ z?#-le118s4?tIihsOdyMBEh&gR+0&dhS&c5&{bus_>gHNB`9cfQLGWA{jEpcg+hL6 z(=1r;M2Y=aAKkYf-=CDl(Je#JD91r_9W*)U7JK__kVNF+xw*zsOG;vN4s&?aK@ti= z4extDlYZ-=+Tou6;2Dr7S9jUsH;Em%TJs1WqO=(@W3G;PM7q1DFC zL)k4FTPZ5>DkP?KQP#jua+n{RYfnfzSge#|@?maAZSFH}KT2FRDu|i-r`+N8fV&rX z$igi&1p-UASU|3Ya(?HSN3gi4vNkx`r*$1ugbz6|`$nqe01P(}vM~i@x8{VJxSaxE qxu5opZ2RHBC?+wB6wZs$HoTw<+}(9)B!`1Tqqz0U$GEh Date: Mon, 7 Oct 2024 15:48:25 -0700 Subject: [PATCH 097/252] Cleaned up the code. --- .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 289 ++++++++++-------- ...SFT_IntuneMobileAppsMacOSLobApp.schema.mof | 15 +- .../Modules/M365DSCDRGUtil.psm1 | 43 +-- 3 files changed, 179 insertions(+), 168 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 index 84c948edb4..664ccca695 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 @@ -59,6 +59,18 @@ function Get-TargetResource [System.String[]] $RoleScopeTagIds, + [Parameter()] + [System.String] + $BundleId, + + [Parameter()] + [System.String] + $BuildNumber, + + [Parameter()] + [System.String] + $VersionNumber, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] $Categories, @@ -71,6 +83,9 @@ function Get-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $ChildApps, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $LargeIcon, #endregion @@ -162,8 +177,10 @@ function Get-TargetResource Publisher = $instance.Publisher PublishingState = $instance.PublishingState.ToString() RoleScopeTagIds = $instance.RoleScopeTagIds + BundleId = $instance.BundleId + BuildNumber = $instance.BuildNumber + VersionNumber = $instance.VersionNumber IgnoreVersionDetection = $instance.AdditionalProperties.ignoreVersionDetection - #ChildApps = $instance.AdditionalProperties.childApps Ensure = 'Present' Credential = $Credential @@ -192,7 +209,6 @@ function Get-TargetResource $results.Add('ChildApps', $instance.AdditionalProperties.childApps) } else { - Write-Host "Get- print childApps null.............................." $results.Add('ChildApps', "") } @@ -208,6 +224,17 @@ function Get-TargetResource $results.Add('Assignments', $resultAssignments) } + #LargeIcon + # The large is returned only when Get cmdlet is called with Id parameter. The large icon is a base64 encoded string, so we need to convert it to a byte array. + $instanceWithLargeIcon = Get-MgBetaDeviceAppManagementMobileApp -MobileAppId $instance.Id + if($null -ne $instanceWithLargeIcon.LargeIcon) + { + $results.Add('LargeIcon', $instanceWithLargeIcon.LargeIcon) + } + else { + $results.Add('LargeIcon', "") + } + #end region complex types return [System.Collections.Hashtable] $results @@ -285,6 +312,18 @@ function Set-TargetResource [System.String[]] $RoleScopeTagIds, + [Parameter()] + [System.String] + $BundleId, + + [Parameter()] + [System.String] + $BuildNumber, + + [Parameter()] + [System.String] + $VersionNumber, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] $Categories, @@ -297,6 +336,9 @@ function Set-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $ChildApps, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $LargeIcon, #endregion @@ -355,55 +397,13 @@ function Set-TargetResource $PSBoundParameters.Remove('CertificateThumbprint') | Out-Null $PSBoundParameters.Remove('ManagedIdentity') | Out-Null $PSBoundParameters.Remove('AccessTokens') | Out-Null - # $PSBoundParameters.Remove('Categories') | Out-Null - # $PSBoundParameters.Remove('Assignments') | Out-Null - # $PSBoundParameters.Remove('childApps') | Out-Null - # $PSBoundParameters.Remove('IgnoreVersionDetection') | Out-Null $CreateParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters - - # $AdditionalProperties = Get-M365DSCIntuneMobileMocOSLobAppAdditionalProperties -Properties ([System.Collections.Hashtable]$PSBoundParameters) - - # Write-Host "Before adding cat and chap @setparameters............................." @setParameters - # Write-Host "Before adding cat and chap @AdditionalProperties............................." @AdditionalProperties - - # #Categories - # if($null -ne $Categories) - # { - # [System.Object[]]$categoriesValue = ConvertTo-M365DSCIntuneAppCategories -Categories $Categories - # $setParameters.Add('Categories', $categoriesValue) - # } - # else { - # Write-Host "^^^^^^^^^^ Set- categories is null:" $Categories - # } - - # #childApps - # if($null -ne $ChildApps) - # { - # foreach ($childApp in $ChildApps) - # { - # Write-Host "^^^^^^^^^^ Set- childApps.............................." $childApp.bundleId - # Write-Host "^^^^^^^^^^^ Set- childApps.............................." $childApp.buildNumber - # Write-Host "^^^^^^^^ Set- childApps.............................." $childApp.versionNumber - # } - - # [System.Object[]]$childAppsValue = ConvertTo-M365DSCIntuneAppChildApps -ChildApps $ChildApps - # $AdditionalProperties.Add('childApps', $childAppsValue) - # } - # else - # { - # Write-Host "^^^^^^^^^^ Set- $ChildApps is null:" $ChildApps - # } - - # Write-Host "After adding cat and chap @setparameters............................." @setParameters - # Write-Host "After adding cat and chap @AdditionalProperties............................." @AdditionalProperties - - # CREATE if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { - Write-Host "Create MacOSLobApp: $DisplayName" + Write-Host "Create MacOS app: $DisplayName" $CreateParameters = ([Hashtable]$PSBoundParameters).clone() $CreateParameters = Rename-M365DSCCimInstanceParameter -Properties $CreateParameters @@ -425,6 +425,8 @@ function Set-TargetResource $CreateParameters.remove('childApps') | Out-Null $CreateParameters.remove('IgnoreVersionDetection') | Out-Null $CreateParameters.Remove('Verbose') | Out-Null + $CreateParameters.Remove('PublishingState') | Out-Null #Not allowed to update as it's a computed property + $CreateParameters.Remove('LargeIcon') | Out-Null foreach ($key in ($CreateParameters.clone()).Keys) { @@ -439,23 +441,28 @@ function Set-TargetResource $CreateParameters.add('AdditionalProperties', $AdditionalProperties) } - $app = New-MgBetaDeviceAppManagementMobileApp @CreateParameters -AdditionalProperties $AdditionalProperties + #LargeIcon + if($LargeIcon) + { + [System.Object]$LargeIconValue = ConvertTo-M365DSCIntuneAppLargeIcon -LargeIcon $LargeIcon + $CreateParameters.Add('LargeIcon', $LargeIconValue) + } - #region Assignments + $app = New-MgBetaDeviceAppManagementMobileApp @CreateParameters + + #Assignments $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments if ($app.id) { - Write-host "New and update: Assignment updates for MacOSLobApp: $DisplayName, with assignmenthash:=======================" $assignmentsHash Update-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $app.id ` -Target $assignmentsHash ` -Repository 'deviceAppManagement/mobileAppAssignments' } - #endregion Assignments } # UPDATE elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { - Write-Host "Update MacOSLobApp: $DisplayName" + Write-Host "Update MacOS app: $DisplayName" $PSBoundParameters.Remove('Assignments') | Out-Null $UpdateParameters = ([Hashtable]$PSBoundParameters).clone() @@ -488,38 +495,29 @@ function Set-TargetResource if ($AdditionalProperties) { - $UpdateParameters.add('AdditionalProperties', $AdditionalProperties) + $UpdateParameters.Add('AdditionalProperties', $AdditionalProperties) } - Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id @UpdateParameters - Write-Host " ################# Returned Update-MgBetaDeviceAppManagementMobileApp ############################### " - - #region Assignments - - $Assignments | ForEach-Object { - Write-Host "INPUT: $_" - } + #LargeIcon + if($LargeIcon) + { + [System.Object]$LargeIconValue = ConvertTo-M365DSCIntuneAppLargeIcon -LargeIcon $LargeIcon + $UpdateParameters.Add('LargeIcon', $LargeIconValue) + } - $Assignments | ForEach-Object { - Write-Host "INPUT Assignment string: $Assignments" - } + Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id @UpdateParameters + Write-Host "Updated MacOS App: $DisplayName." + #Assignments $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments - $assignmentsHash.GetEnumerator() | ForEach-Object { - Write-Host "Converted assignmentsHash key:value: $($_.Key): $($_.Value)" } - - Write-Host " ############### Calling Update-MgBetaDeviceAppManagementMobileAppAssignment now ############################# " - Update-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $currentInstance.id ` -Target $assignmentsHash ` -Repository 'deviceAppManagement/mobileAppAssignments' - - #endregion Assignments } # REMOVE elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { - Write-Host "Remove MacOSLobApp: $DisplayName" + Write-Host "Remove MacOS app: $DisplayName" Remove-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id -Confirm:$false } } @@ -585,6 +583,18 @@ function Test-TargetResource [System.String[]] $RoleScopeTagIds, + [Parameter()] + [System.String] + $BundleId, + + [Parameter()] + [System.String] + $BuildNumber, + + [Parameter()] + [System.String] + $VersionNumber, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] $Categories, @@ -597,6 +607,10 @@ function Test-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $ChildApps, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $LargeIcon, + #endregion [Parameter()] @@ -633,9 +647,6 @@ function Test-TargetResource $AccessTokens ) - Write-Host "start test-TargetResource.............................." - Write-Debug "start Set-TargetResource.............................." - #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -773,6 +784,7 @@ function Export-TargetResource { Write-Host "`r`n" -NoNewline } + foreach ($config in $Script:getInstances) { if ($null -ne $Global:M365DSCExportResourceInstancesCount) @@ -796,6 +808,9 @@ function Export-TargetResource Publisher = $config.Publisher PublishingState = $config.PublishingState.ToString() RoleScopeTagIds = $config.RoleScopeTagIds + BundleId = $config.BundleId + BuildNumber = $config.BuildNumber + VersionNumber = $config.VersionNumber IgnoreVersionDetection = $config.AdditionalProperties.ignoreVersionDetection Ensure = 'Present' @@ -821,19 +836,25 @@ function Export-TargetResource #region complex types #Categories - if($null -ne $Results.Categories -or $Results.Categories.Count -gt 0) + if($null -ne $Results.Categories) { $Results.Categories = Get-M365DSCIntuneAppCategoriesAsString -Categories $Results.Categories } + else { + $Results.Remove('Categories') | Out-Null + } #ChildApps - if($null -ne $Results.childApps -or $Results.childApps.Count -gt 0) + if($null -ne $Results.childApps) { $Results.childApps = Get-M365DSCIntuneAppChildAppsAsString -ChildApps $Results.childApps } + else { + $Results.Remove('childApps') | Out-Null + } #Assignments - if ($Results.Assignments) + if ($null -ne $Results.Assignments) { $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString -ComplexObject ([Array]$Results.Assignments) -CIMInstanceName DeviceManagementMobileAppAssignment @@ -847,6 +868,16 @@ function Export-TargetResource } } + #LargeIcon + if($null -ne $Results.LargeIcon) + { + $Results.LargeIcon = Get-M365DSCIntuneAppLargeIconAsString -LargeIcon $Results.LargeIcon + } + else + { + $Results.Remove('LargeIcon') | Out-Null + } + #endregion complex types $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` @@ -857,6 +888,7 @@ function Export-TargetResource #region complex types + #Categories if ($null -ne $Results.Categories) { $isCIMArray = $false @@ -868,6 +900,7 @@ function Export-TargetResource $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Categories' -IsCIMArray:$isCIMArray } + #ChildApps if ($null -ne $Results.childApps) { $isCIMArray = $false @@ -879,7 +912,8 @@ function Export-TargetResource $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'ChildApps' -IsCIMArray:$isCIMArray } - if ($Results.Assignments) + #Assignments + if ($null -ne $Results.Assignments) { $isCIMArray = $false if ($Results.Assignments.getType().Fullname -like '*[[\]]') @@ -890,6 +924,12 @@ function Export-TargetResource $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Assignments' -IsCIMArray:$isCIMArray } + #LargeIcon + if ($null -ne $Results.LargeIcon) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'LargeIcon' -IsCIMArray:$false + } + #endregion complex types $dscContent += $currentDSCBlock @@ -917,29 +957,6 @@ function Export-TargetResource #region Helper functions -function ConvertTo-M365DSCIntuneAppCategories -{ - [OutputType([System.Object[]])] - param( - [Parameter(Mandatory = $true)] - [System.Collections.ArrayList] - $Categories - ) - - $result = @() - foreach ($category in $Categories) - { - $currentCategory = @{ - id = $category.id - displayName = $category.displayName - } - - $result += $currentCategory - } - - return $result -} - function Get-M365DSCIntuneAppCategoriesAsString { [CmdletBinding()] @@ -963,8 +980,8 @@ function Get-M365DSCIntuneAppCategoriesAsString $StringContent += "$space" } + #Only export the displayName, not Id $StringContent += "MSFT_DeviceManagementMobileAppCategory { `r`n" - $StringContent += "$($space)$($indent)id = '" + $category.id + "'`r`n" $StringContent += "$($space)$($indent)displayName = '" + $category.displayName + "'`r`n" $StringContent += "$space}" @@ -976,30 +993,6 @@ function Get-M365DSCIntuneAppCategoriesAsString return $StringContent } -function ConvertTo-M365DSCIntuneAppChildApps -{ - [OutputType([System.Object[]])] - param( - [Parameter(Mandatory = $true)] - [System.Collections.ArrayList] - $ChildApps - ) - - $result = @() - foreach ($childApp in $ChildApps) - { - $currentChildApp = @{ - bundleId = $childApp.bundleId - buildNumber = $childApp.buildNumber - versionNumber = $childApp.VersionNumber - } - - $result += $currentChildApp - } - - return $result -} - function Get-M365DSCIntuneAppChildAppsAsString { [CmdletBinding()] @@ -1094,6 +1087,52 @@ function Get-M365DSCIntuneMobileMocOSLobAppAdditionalProperties return $results } +function Get-M365DSCIntuneAppLargeIconAsString #Get and Export +{ + [CmdletBinding()] + [OutputType([System.String])] + param( + [Parameter(Mandatory = $true)] + [System.Object] + $LargeIcon + ) + + $space = ' ' + $indent = ' ' + + if ($null -ne $LargeIcon.Value) + { + $StringContent += "`r`n" + $StringContent += "$space" + + $base64String = [System.Convert]::ToBase64String($LargeIcon.Value) # This exports the base64 string (blob) of the byte array, same as we see in Graph API response + + $StringContent += "MSFT_DeviceManagementMimeContent { `r`n" + $StringContent += "$($space)$($indent)type = '" + $LargeIcon.Type + "'`r`n" + $StringContent += "$($space)$($indent)value = '" + $base64String + "'`r`n" + $StringContent += "$space}" + } + + return $StringContent + } + +function ConvertTo-M365DSCIntuneAppLargeIcon #set +{ + [OutputType([System.Object])] + param( + [Parameter(Mandatory = $true)] + [System.Object] + $LargeIcon + ) + + $result = @{ + type = $LargeIcon.Type + value = $iconValue + } + + return $result +} + #endregion Helper functions Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof index 222f5f14e8..88248b6460 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof @@ -13,15 +13,16 @@ class MSFT_IntuneMobileAppsMacOSLobApp : OMI_BaseResource [Write, Description("The privacy statement Url. Inherited from mobileApp.")] String PrivacyInformationUrl; [Write, Description("The publisher of the app. Inherited from mobileApp.")] String Publisher; [Write, Description("The publishing state for the app. The app cannot be assigned unless the app is published. Inherited from mobileApp."), ValueMap{"notPublished", "processing","published"}, Values{"notPublished", "processing", "published"}] String PublishingState; + [Write, Description("The bundleId of the app.")] String BundleId; + [Write, Description("The build number of the app.")] String BuildNumber; + [Write, Description("The version number of the app.")] String VersionNumber; [Write, Description("List of Scope Tag IDs for mobile app.")] String RoleScopeTagIds[]; - + [Write, Description("Wether to ignore the version of the app or not.")] Boolean IgnoreVersionDetection; + [Write, Description("The icon for this app."), EmbeddedInstance("MSFT_DeviceManagementMimeContent")] String LargeIcon; [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppCategory")] String Categories[]; [Write, Description("The list of assignments for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppAssignment")] String Assignments[]; - [Write, Description("The list of child apps for this app package."), EmbeddedInstance("MSFT_DeviceManagementMobileAppChildApp")] String ChildApps[]; - [Write, Description("Wether to ignore the version of the app or not.")] Boolean IgnoreVersionDetection; - [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] String Ensure; [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] String Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; @@ -32,6 +33,12 @@ class MSFT_IntuneMobileAppsMacOSLobApp : OMI_BaseResource [Write, Description("Access token used for authentication.")] String AccessTokens[]; }; +class MSFT_DeviceManagementMimeContent +{ + [Write, Description("Indicates the type of content mime.")] String type; + [Write, Description("The byte array that contains the actual content.")] String value[]; +}; + class MSFT_DeviceManagementMobileAppCategory { [Key, Description("The name of the app category.")] String displayName; diff --git a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 index 2c3a1fadfb..42b929aa37 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 @@ -1383,36 +1383,16 @@ function ConvertTo-IntuneMobileAppAssignment } } - #TODOK: Uncomment it - # $assignmentResult += $assignment.intent; - # $assignmentResult += $assignment.source; + $assignmentResult += $assignment.intent; + $assignmentResult += $assignment.source; - # if($assignment.settings) - # { - # $assignmentResult += $assignment.settings; - # } - - - if ($assignment.dataType -like '*groupAssignmentTarget' ` - -or $assignment.dataType -like '*allDevicesAssignmentTarget' ` - -or $assignment.dataType -like '*allLicensedUsersAssignmentTarget') + if ($assignment.dataType -like '*groupAssignmentTarget') { - Write-Host "Befgore group call assignment.groupId: " $assignment.groupId - Write-Host "After group call assignment.groupId: `"$($assignment.groupId)`" -----------------------------------------" - - $group = Get-MgGroup -GroupId ($assignment.groupId) -ErrorAction SilentlyContinue #TODOK: SilentlyContinue later - - Write-Host "After group call assignment.group: " $group - + $group = Get-MgGroup -GroupId ($assignment.groupId) -ErrorAction SilentlyContinue if ($null -eq $group) { - Write-Host "After group call group is null: " $group - - Write-Host "After group call assignment.group: " $assignment.groupDisplayName - if ($assignment.groupDisplayName) { - Write-Host "Befpre group call with NAME assignment.group.NAME: " $assignment.groupDisplayName $group = Get-MgGroup -Filter "DisplayName eq '$($assignment.groupDisplayName)'" -ErrorAction SilentlyContinue if ($null -eq $group) { @@ -1440,29 +1420,14 @@ function ConvertTo-IntuneMobileAppAssignment } else { #Skipping assignment if group not found from either groupId or groupDisplayName - - Write-Host "target group:::::::::::::::::::::: " $group - $target.Add('groupId', $group.Id) - - Write-Host "groupId added to target." - - - $target.GetEnumerator() | ForEach-Object { - Write-Host "target key:value with groupId: $($_.Key): $($_.Value)" } } } - Write-Host "1456 target: " $target if ($target) { - Write-Host "target assigned to final assignmentResult." - $assignmentResult += @{target = $target} } - - $assignmentResult.GetEnumerator() | ForEach-Object { - Write-Host "AssignmentResult key:value AFTER all targets added: $($_.Key): $($_.Value)" } } return ,$assignmentResult From b4c565af3f12eb9289c9612a9f662b7d26356ba3 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 7 Oct 2024 23:26:05 +0000 Subject: [PATCH 098/252] Updated Resources and Cmdlet documentation pages --- .../intune/IntuneMobileAppsMacOSLobApp.md | 280 ++++++++++++++++++ 1 file changed, 280 insertions(+) create mode 100644 docs/docs/resources/intune/IntuneMobileAppsMacOSLobApp.md diff --git a/docs/docs/resources/intune/IntuneMobileAppsMacOSLobApp.md b/docs/docs/resources/intune/IntuneMobileAppsMacOSLobApp.md new file mode 100644 index 0000000000..412b83d61a --- /dev/null +++ b/docs/docs/resources/intune/IntuneMobileAppsMacOSLobApp.md @@ -0,0 +1,280 @@ +# IntuneMobileAppsMacOSLobApp + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **DisplayName** | Key | String | The admin provided or imported title of the app. Inherited from mobileApp. | | +| **Id** | Write | String | The unique identifier for an entity. Read-only. Inherited from mobileApp object. | | +| **Description** | Write | String | The description of the app. Inherited from mobileApp. | | +| **Developer** | Write | String | The dewveloper of the app. Inherited from mobileApp. | | +| **InformationUrl** | Write | String | The InformationUrl of the app. Inherited from mobileApp. | | +| **IsFeatured** | Write | Boolean | The value indicating whether the app is marked as featured by the admin. Inherited from mobileApp. | | +| **Notes** | Write | String | Notes for the app. Inherited from mobileApp. | | +| **Owner** | Write | String | The owner of the app. Inherited from mobileApp. | | +| **PrivacyInformationUrl** | Write | String | The privacy statement Url. Inherited from mobileApp. | | +| **Publisher** | Write | String | The publisher of the app. Inherited from mobileApp. | | +| **PublishingState** | Write | String | The publishing state for the app. The app cannot be assigned unless the app is published. Inherited from mobileApp. | `notPublished`, `processing`, `published` | +| **BundleId** | Write | String | The bundleId of the app. | | +| **BuildNumber** | Write | String | The build number of the app. | | +| **VersionNumber** | Write | String | The version number of the app. | | +| **RoleScopeTagIds** | Write | StringArray[] | List of Scope Tag IDs for mobile app. | | +| **IgnoreVersionDetection** | Write | Boolean | Wether to ignore the version of the app or not. | | +| **LargeIcon** | Write | MSFT_DeviceManagementMimeContent | The icon for this app. | | +| **Categories** | Write | MSFT_DeviceManagementMobileAppCategory[] | The list of categories for this app. | | +| **Assignments** | Write | MSFT_DeviceManagementMobileAppAssignment[] | The list of assignments for this app. | | +| **ChildApps** | Write | MSFT_DeviceManagementMobileAppChildApp[] | The list of child apps for this app package. | | +| **Ensure** | Write | String | Present ensures the policy exists, absent ensures it is removed. | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials of the Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **ApplicationSecret** | Write | PSCredential | Secret of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + +### MSFT_DeviceManagementMimeContent + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **type** | Write | String | Indicates the type of content mime. | | +| **value** | Write | StringArray[] | The byte array that contains the actual content. | | + +### MSFT_DeviceManagementMobileAppCategory + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **displayName** | Key | String | The name of the app category. | | +| **id** | Write | String | The unique identifier for an entity. Read-only. | | + +### MSFT_DeviceManagementMobileAppChildApp + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **bundleId** | Write | String | The bundleId of the app. | | +| **buildNumber** | Write | String | The build number of the app. | | +| **versionNumber** | Write | String | The version number of the app. | | + +### MSFT_DeviceManagementMobileAppAssignment + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **dataType** | Write | String | The type of the target assignment. | `#microsoft.graph.groupAssignmentTarget`, `#microsoft.graph.allLicensedUsersAssignmentTarget`, `#microsoft.graph.allDevicesAssignmentTarget`, `#microsoft.graph.exclusionGroupAssignmentTarget`, `#microsoft.graph.mobileAppAssignment` | +| **deviceAndAppManagementAssignmentFilterId** | Write | String | The Id of the filter for the target assignment. | | +| **deviceAndAppManagementAssignmentFilterType** | Write | String | The type of filter of the target assignment i.e. Exclude or Include. Possible values are: none, include, exclude. | `none`, `include`, `exclude` | +| **groupId** | Write | String | The group Id that is the target of the assignment. | | +| **groupDisplayName** | Write | String | The group Display Name that is the target of the assignment. | | +| **intent** | Write | String | Possible values for the install intent chosen by the admin. | `available`, `required`, `uninstall`, `availableWithoutEnrollment` | +| **source** | Write | String | The source of this assignment. | | + + +## Description + +This resource configures an Intune mobile app of MacOSLobApp type for MacOS devices. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - DeviceManagementApps.Read.All + +- **Update** + + - DeviceManagementApps.ReadWrite.All + +#### Application permissions + +- **Read** + + - DeviceManagementApps.Read.All + +- **Update** + + - DeviceManagementApps.ReadWrite.All + +## Examples + +### Example 1 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + IntuneMobileAppsMacOSLobApp "IntuneMobileAppsMacOSLobApp-TeamsForBusinessInstaller" + { + Id = "8d027f94-0682-431e-97c1-827d1879fa79"; + Description = "TeamsForBusinessInstaller"; + Developer = "Contoso"; + DisplayName = "TeamsForBusinessInstaller"; + Ensure = "Present"; + InformationUrl = ""; + IsFeatured = $False; + Notes = ""; + Owner = ""; + PrivacyInformationUrl = ""; + Publisher = "Contoso"; + PublishingState = "published"; + Assignments = @( + MSFT_DeviceManagementMobileAppAssignment{ + groupDisplayName = 'All devices' + source = 'direct' + deviceAndAppManagementAssignmentFilterType = 'none' + dataType = '#microsoft.graph.allDevicesAssignmentTarget' + intent = 'required' + MSFT_DeviceManagementMobileAppAssignment{ + deviceAndAppManagementAssignmentFilterType = 'none' + source = 'direct' + dataType = '#microsoft.graph.groupAssignmentTarget' + groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' + intent = 'required' + } + }); + Categories = @(MSFT_DeviceManagementMobileAppCategory { + id = '1bff2652-03ec-4a48-941c-152e93736515' + displayName = 'Kajal 3' + }); + } + } +} +``` + +### Example 2 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + IntuneMobileAppsMacOSLobApp "IntuneMobileAppsMacOSLobApp-TeamsForBusinessInstaller" + { + Id = "8d027f94-0682-431e-97c1-827d1879fa79"; + Description = "TeamsForBusinessInstaller"; + Developer = "Contoso drift"; #drift + DisplayName = "TeamsForBusinessInstaller"; + Ensure = "Present"; + InformationUrl = ""; + IsFeatured = $False; + Notes = ""; + Owner = ""; + PrivacyInformationUrl = ""; + Publisher = "Contoso"; + PublishingState = "published"; + Assignments = @( + MSFT_DeviceManagementMobileAppAssignment{ + groupDisplayName = 'All devices' + source = 'direct' + deviceAndAppManagementAssignmentFilterType = 'none' + dataType = '#microsoft.graph.allDevicesAssignmentTarget' + intent = 'required' + MSFT_DeviceManagementMobileAppAssignment{ + deviceAndAppManagementAssignmentFilterType = 'none' + source = 'direct' + dataType = '#microsoft.graph.groupAssignmentTarget' + groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' + intent = 'required' + } + }); + Categories = @(MSFT_DeviceManagementMobileAppCategory { + id = '1bff2652-03ec-4a48-941c-152e93736515' + displayName = 'Kajal 3' + }); + } + } +} +``` + +### Example 3 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + IntuneMobileAppsMacOSLobApp "IntuneMobileAppsMacOSLobApp-TeamsForBusinessInstaller" + { + Id = "8d027f94-0682-431e-97c1-827d1879fa79"; + Description = "TeamsForBusinessInstaller"; + Developer = "Contoso"; + DisplayName = "TeamsForBusinessInstaller"; + Ensure = "Absent"; + InformationUrl = ""; + IsFeatured = $False; + Notes = ""; + Owner = ""; + PrivacyInformationUrl = ""; + Publisher = "Contoso"; + PublishingState = "published"; + } + } +} +``` + From 8f7a4da5e2d2b40fddc4f643e03bc040e4ad8c9b Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 7 Oct 2024 23:28:11 +0000 Subject: [PATCH 099/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 235 ++++++++++++++++++ 1 file changed, 235 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 7fc131b48e..1fa6103618 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -34754,6 +34754,241 @@ } ] }, + { + "ClassName": "MSFT_IntuneMobileAppsMacOSLobApp", + "Parameters": [ + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "Id", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Description", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Developer", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "InformationUrl", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "IsFeatured", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Notes", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Owner", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PrivacyInformationUrl", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Publisher", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PublishingState", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "BundleId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "BuildNumber", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "VersionNumber", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "RoleScopeTagIds", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "IgnoreVersionDetection", + "Option": "Write" + }, + { + "CIMType": "MSFT_DeviceManagementMimeContent", + "Name": "LargeIcon", + "Option": "Write" + }, + { + "CIMType": "MSFT_DeviceManagementMobileAppCategory[]", + "Name": "Categories", + "Option": "Write" + }, + { + "CIMType": "MSFT_DeviceManagementMobileAppAssignment[]", + "Name": "Assignments", + "Option": "Write" + }, + { + "CIMType": "MSFT_DeviceManagementMobileAppChildApp[]", + "Name": "ChildApps", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "ApplicationSecret", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_DeviceManagementMimeContent", + "Parameters": [ + { + "CIMType": "String", + "Name": "type", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "value", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_DeviceManagementMobileAppCategory", + "Parameters": [ + { + "CIMType": "String", + "Name": "displayName", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "id", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_DeviceManagementMobileAppChildApp", + "Parameters": [ + { + "CIMType": "String", + "Name": "bundleId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "buildNumber", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "versionNumber", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_DeviceManagementMobileAppAssignment", + "Parameters": [ + { + "CIMType": "String", + "Name": "dataType", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "deviceAndAppManagementAssignmentFilterId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "deviceAndAppManagementAssignmentFilterType", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "groupId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "groupDisplayName", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "intent", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "source", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_DeviceManagementConfigurationPolicyItems", "Parameters": [ From 7584a7e507a95766f86403bd63cf686b07c7ae37 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 7 Oct 2024 23:28:29 +0000 Subject: [PATCH 100/252] Updated {Create} Intune Integration Tests --- ...M365DSCIntegration.INTUNE.Create.Tests.ps1 | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 index 4a7a92a437..a3e123f77e 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 @@ -2507,6 +2507,40 @@ TenantId = $TenantId; CertificateThumbprint = $CertificateThumbprint; } + IntuneMobileAppsMacOSLobApp 'IntuneMobileAppsMacOSLobApp-TeamsForBusinessInstaller' + { + Id = "8d027f94-0682-431e-97c1-827d1879fa79"; + Description = "TeamsForBusinessInstaller"; + Developer = "Contoso"; + DisplayName = "TeamsForBusinessInstaller"; + Ensure = "Present"; + InformationUrl = ""; + IsFeatured = $False; + Notes = ""; + Owner = ""; + PrivacyInformationUrl = ""; + Publisher = "Contoso"; + PublishingState = "published"; + Assignments = @( + MSFT_DeviceManagementMobileAppAssignment{ + groupDisplayName = 'All devices' + source = 'direct' + deviceAndAppManagementAssignmentFilterType = 'none' + dataType = '#microsoft.graph.allDevicesAssignmentTarget' + intent = 'required' + MSFT_DeviceManagementMobileAppAssignment{ + deviceAndAppManagementAssignmentFilterType = 'none' + source = 'direct' + dataType = '#microsoft.graph.groupAssignmentTarget' + groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' + intent = 'required' + } + }); + Categories = @(MSFT_DeviceManagementMobileAppCategory { + id = '1bff2652-03ec-4a48-941c-152e93736515' + displayName = 'Kajal 3' + }); + } IntunePolicySets 'Example' { Assignments = @( From efc4ac9a499e674a48819daba5cee4496795e742 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 7 Oct 2024 20:30:02 -0400 Subject: [PATCH 101/252] Added Support for OnPremisesPublishing --- CHANGELOG.md | 1 + .../MSFT_AADApplication.psm1 | 199 +++++++++++++++++- .../MSFT_AADApplication.schema.mof | 53 +++++ 3 files changed, 252 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a42713a14c..0fa9247d31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * Initial release. * AADApplication * Fixed an issue trying to retrieve the beta instance. + * Added support for OnPremisesPublishing. * AADDeviceRegistrationPolicy * Initial release. * AADEntitlementManagementSettings diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index 3101f97fd7..e2834628f8 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -88,6 +88,10 @@ function Get-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $Permissions, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $OnPremisesPublishing, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -274,7 +278,6 @@ function Get-TargetResource $complexApi = $null } - $complexKeyCredentials = @() foreach ($currentkeyCredentials in $AADAppKeyCredentials.keyCredentials) { @@ -379,6 +382,77 @@ function Get-TargetResource $IsFallbackPublicClientValue = $AADApp.IsFallbackPublicClient } + #region OnPremisesPublishing + $onPremisesPublishingValue = @{} + $oppInfo = $null + + try + { + $oppInfo = Invoke-MgGraphRequest -Method GET ` + -Uri "https://graph.microsoft.com/beta/applications/$($AADBetaApp.Id)/onPremisesPublishing" ` + -ErrorAction SilentlyContinue + } + catch + { + Write-Verbose -Message "On-premises publishing is not enabled for App {$($AADBetaApp.DisplayName)}" + } + + if ($null -ne $oppInfo) + { + $onPremisesPublishingValue = @{ + alternateUrl = $oppInfo.alternateUrl + applicationServerTimeout = $oppInfo.applicationServerTimeout + externalAuthenticationType = $oppInfo.externalAuthenticationType + externalUrl = $oppInfo.externalUrl + internalUrl = $oppInfo.internalUrl + isBackendCertificateValidationEnabled = $oppInfo.isBackendCertificateValidationEnabled + isHttpOnlyCookieEnabled = $oppInfo.isHttpOnlyCookieEnabled + isPersistentCookieEnabled = $oppInfo.isPersistentCookieEnabled + isSecureCookieEnabled = $oppInfo.isSecureCookieEnabled + isStateSessionEnabled = $oppInfo.isStateSessionEnabled + isTranslateHostHeaderEnabled = $oppInfo.isTranslateHostHeaderEnabled + isTranslateLinksInBodyEnabled = $oppInfo.isTranslateLinksInBodyEnabled + } + + # onPremisesApplicationSegments + $segmentValues = @() + foreach ($segment in $oppInfo.onPremisesApplicationSegments) + { + $entry = @{ + alternateUrl = $segment.AlternateUrl + externalUrl = $segment.externalUrl + internalUrl = $segment.internalUrl + } + + $corsConfigurationValues = @() + foreach ($cors in $segment.corsConfigurations) + { + $corsEntry = @{ + allowedHeaders = [Array]($cors.allowedHeaders) + allowedMethods = [Array]($cors.allowedMethods) + allowedOrigins = [Array]($cors.allowedOrigins) + maxAgeInSeconds = $cors.maxAgeInSeconds + resource = $cors.resource + } + $corsConfigurationValues += $corsEntry + } + $entry.Add('corsConfigurations', $corsConfigurationValues) + $segmentValues += $entry + } + $onPremisesPublishingValue.Add('onPremisesApplicationSegments', $segmentValues) + + # singleSignOnSettings + $singleSignOnValues = @{ + kerberosSignOnSettings = @{ + kerberosServicePrincipalName = $oppInfo.singleSignOnSettings.kerberosSignOnSettings.kerberosServicePrincipalName + kerberosSignOnMappingAttributeType = $oppInfo.singleSignOnSettings.kerberosSignOnSettings.kerberosSignOnMappingAttributeType + } + singleSignOnMode = $oppInfo.singleSignOnSettings.singleSignOnMode + } + $onPremisesPublishingValue.Add('singleSignOnSettings', $singleSignOnValues) + } + #endregion + $result = @{ DisplayName = $AADApp.DisplayName AvailableToOtherTenants = $AvailableToOtherTenantsValue @@ -401,6 +475,7 @@ function Get-TargetResource PasswordCredentials = $complexPasswordCredentials AppRoles = $complexAppRoles Permissions = $permissionsObj + OnPremisesPublishing = $onPremisesPublishingValue Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId @@ -522,6 +597,10 @@ function Set-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $Permissions, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $OnPremisesPublishing, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -678,6 +757,7 @@ function Set-TargetResource $currentParameters.Remove('ReplyURLs') | Out-Null $currentParameters.Remove('LogoutURL') | Out-Null $currentParameters.Remove('Homepage') | Out-Null + $currentParameters.Remove('OnPremisesPublishing') | Out-Null $keys = (([Hashtable]$currentParameters).clone()).Keys @@ -944,6 +1024,74 @@ function Set-TargetResource Write-Warning -Message "KeyCredentials cannot be updated for AAD Applications with more than one KeyCredentials due to technical limitation of Update-MgApplication Cmdlet. Learn more at: https://learn.microsoft.com/en-us/graph/api/application-addkey" } } + + #region OnPremisesPublishing + if ($null -ne $OnPremisesPublishing) + { + $oppInfo = $OnPremisesPublishing + $onPremisesPublishingValue = @{ + alternateUrl = $oppInfo.alternateUrl + applicationServerTimeout = $oppInfo.applicationServerTimeout + externalAuthenticationType = $oppInfo.externalAuthenticationType + #externalUrl = $oppInfo.externalUrl + internalUrl = $oppInfo.internalUrl + isBackendCertificateValidationEnabled = $oppInfo.isBackendCertificateValidationEnabled + isHttpOnlyCookieEnabled = $oppInfo.isHttpOnlyCookieEnabled + isPersistentCookieEnabled = $oppInfo.isPersistentCookieEnabled + isSecureCookieEnabled = $oppInfo.isSecureCookieEnabled + isStateSessionEnabled = $oppInfo.isStateSessionEnabled + isTranslateHostHeaderEnabled = $oppInfo.isTranslateHostHeaderEnabled + isTranslateLinksInBodyEnabled = $oppInfo.isTranslateLinksInBodyEnabled + } + + # onPremisesApplicationSegments + $segmentValues = @() + foreach ($segment in $oppInfo.onPremisesApplicationSegments) + { + $entry = @{ + alternateUrl = $segment.AlternateUrl + externalUrl = $segment.externalUrl + internalUrl = $segment.internalUrl + } + + $corsConfigurationValues = @() + foreach ($cors in $segment.corsConfigurations) + { + $corsEntry = @{ + allowedHeaders = [Array]($cors.allowedHeaders) + allowedMethods = [Array]($cors.allowedMethods) + allowedOrigins = [Array]($cors.allowedOrigins) + maxAgeInSeconds = $cors.maxAgeInSeconds + resource = $cors.resource + } + $corsConfigurationValues += $corsEntry + } + $entry.Add('corsConfigurations', $corsConfigurationValues) + $segmentValues += $entry + } + $onPremisesPublishingValue.Add('onPremisesApplicationSegments', $segmentValues) + + # singleSignOnSettings + $singleSignOnValues = @{ + kerberosSignOnSettings = @{ + kerberosServicePrincipalName = $oppInfo.singleSignOnSettings.kerberosSignOnSettings.kerberosServicePrincipalName + kerberosSignOnMappingAttributeType = $oppInfo.singleSignOnSettings.kerberosSignOnSettings.kerberosSignOnMappingAttributeType + } + singleSignOnMode = $oppInfo.singleSignOnSettings.singleSignOnMode + } + if ($null -eq $singleSignOnValues.kerberosSignOnSettings.kerberosServicePrincipalName) + { + $singleSignOnValues.Remove('kerberosSignOnSettings') | Out-Null + } + + $onPremisesPublishingValue.Add('singleSignOnSettings', $singleSignOnValues) + $onPremisesPayload = ConvertTo-Json $onPremisesPublishingValue -Depth 10 -Compress + Write-Verbose -Message "Updating the OnPremisesPublishing settings for application {$($currentAADApp.DisplayName)} with payload: $onPremisesPayload" + Invoke-MgGraphRequest -Method 'PATCH' ` + -Uri "https://graph.microsoft.com/beta/applications/$($currentAADApp.Id)/onPremisesPublishing" ` + -Body $onPremisesPayload + } + #endregion } function Test-TargetResource @@ -1036,6 +1184,10 @@ function Test-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $Permissions, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $OnPremisesPublishing, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -1309,6 +1461,47 @@ function Export-TargetResource } } + if ($null -ne $Results.OnPremisesPublishing.singleSignOnSettings) + { + $complexMapping = @( + @{ + Name = 'singleSignOnSettings' + CimInstanceName = 'AADApplicationOnPremisesPublishingSingleSignOnSetting' + IsRequired = $False + }, + @{ + Name = 'onPremisesApplicationSegments' + CimInstanceName = 'AADApplicationOnPremisesPublishingSegment' + IsRequired = $False + }, + @{ + Name = 'kerberosSignOnSettings' + CimInstanceName = 'AADApplicationOnPremisesPublishingSingleSignOnSettingKerberos' + IsRequired = $False + }, + @{ + Name = 'corsConfigurations' + CimInstanceName = 'AADApplicationOnPremisesPublishingSegmentCORS' + IsRequired = $False + } + ) + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.OnPremisesPublishing ` + -CIMInstanceName 'AADApplicationOnPremisesPublishing' ` + -ComplexTypeMapping $complexMapping + if (-not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.OnPremisesPublishing = $complexTypeStringResult + } + else + { + $Results.Remove('OnPremisesPublishing') | Out-Null + } + } + else + { + $Results.Remove('OnPremisesPublishing') | Out-Null + } if ($null -ne $Results.OptionalClaims) { @@ -1415,6 +1608,10 @@ function Export-TargetResource { $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "OptionalClaims" -IsCIMArray:$False } + if ($Results.OnPremisesPublishing) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "OnPremisesPublishing" -IsCIMArray:$False + } if ($Results.AuthenticationBehaviors) { $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "AuthenticationBehaviors" -IsCIMArray:$False diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof index c78c43016d..ae3c0625d2 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof @@ -1,3 +1,55 @@ +[ClassVersion("1.0.0")] +class MSFT_AADApplicationOnPremisesPublishingSegmentCORS +{ + [Write, Description("The request headers that the origin domain may specify on the CORS request. The wildcard character * indicates that any header beginning with the specified prefix is allowed.")] String allowedHeaders[]; + [Write, Description("The maximum amount of time that a browser should cache the response to the preflight OPTIONS request.")] UInt32 maxAgeInSeconds; + [Write, Description("Resource within the application segment for which CORS permissions are granted. / grants permission for whole app segment.")] String resource; + [Write, Description("The HTTP request methods that the origin domain may use for a CORS request.")] String allowedMethods[]; + [Write, Description("The origin domains that are permitted to make a request against the service via CORS. The origin domain is the domain from which the request originates. The origin must be an exact case-sensitive match with the origin that the user age sends to the service.")] String allowedOrigins[]; +}; + +[ClassVersion("1.0.0")] +class MSFT_AADApplicationOnPremisesPublishingSegment +{ + [Write, Description("If you're configuring a traffic manager in front of multiple App Proxy application segments, contains the user-friendly URL that will point to the traffic manager.")] String alternateUrl; + [Write, Description("CORS Rule definition for a particular application segment."), EmbeddedInstance("MSFT_AADApplicationOnPremisesPublishingSegmentCORS")] String corsConfigurations[]; + [Write, Description("The published external URL for the application segment; for example, https://intranet.contoso.com./")] String externalUrl; + [Write, Description("The internal URL of the application segment; for example, https://intranet/.")] String internalUrl; +}; + +[ClassVersion("1.0.0")] +class MSFT_AADApplicationOnPremisesPublishingSingleSignOnSettingKerberos +{ + [Write, Description("The Internal Application SPN of the application server. This SPN needs to be in the list of services to which the connector can present delegated credentials.")] String kerberosServicePrincipalName; + [Write, Description("The Delegated Login Identity for the connector to use on behalf of your users. For more information, see Working with different on-premises and cloud identities . Possible values are: userPrincipalName, onPremisesUserPrincipalName, userPrincipalUsername, onPremisesUserPrincipalUsername, onPremisesSAMAccountName.")] String kerberosSignOnMappingAttributeType; +}; + +[ClassVersion("1.0.0")] +class MSFT_AADApplicationOnPremisesPublishingSingleSignOnSetting +{ + [Write, Description("The preferred single-sign on mode for the application. Possible values are: none, onPremisesKerberos, aadHeaderBased,pingHeaderBased, oAuthToken.")] String singleSignOnMode; + [Write, Description("The Kerberos Constrained Delegation settings for applications that use Integrated Window Authentication."), EmbeddedInstance("MSFT_AADApplicationOnPremisesPublishingSingleSignOnSettingKerberos")] String kerberosSignOnSettings; +}; + +[ClassVersion("1.0.0")] +class MSFT_AADApplicationOnPremisesPublishing +{ + [Write, Description("If you're configuring a traffic manager in front of multiple App Proxy applications, the alternateUrl is the user-friendly URL that points to the traffic manager.")] String alternateUrl; + [Write, Description("The duration the connector waits for a response from the backend application before closing the connection. Possible values are default, long.")] String applicationServerTimeout; + [Write, Description("Details the pre-authentication setting for the application. Pre-authentication enforces that users must authenticate before accessing the app. Pass through doesn't require authentication. Possible values are: passthru, aadPreAuthentication.")] String externalAuthenticationType; + [Write, Description("The published external url for the application. For example, https://intranet-contoso.msappproxy.net/.")] String externalUrl; + [Write, Description("The internal url of the application. For example, https://intranet/.")] String internalUrl; + [Write, Description("Indicates whether backend SSL certificate validation is enabled for the application. For all new Application Proxy apps, the property is set to true by default. For all existing apps, the property is set to false.")] Boolean isBackendCertificateValidationEnabled; + [Write, Description("Indicates if the HTTPOnly cookie flag should be set in the HTTP response headers. Set this value to true to have Application Proxy cookies include the HTTPOnly flag in the HTTP response headers. If using Remote Desktop Services, set this value to False. Default value is false.")] Boolean isHttpOnlyCookieEnabled; + [Write, Description("Indicates if the Persistent cookie flag should be set in the HTTP response headers. Keep this value set to false. Only use this setting for applications that can't share cookies between processes. For more information about cookie settings, see Cookie settings for accessing on-premises applications in Microsoft Entra ID. Default value is false.")] Boolean isPersistentCookieEnabled; + [Write, Description("Indicates if the Secure cookie flag should be set in the HTTP response headers. Set this value to true to transmit cookies over a secure channel such as an encrypted HTTPS request. Default value is true.")] Boolean isSecureCookieEnabled; + [Write, Description("Indicates whether validation of the state parameter when the client uses the OAuth 2.0 authorization code grant flow is enabled. This setting allows admins to specify whether they want to enable CSRF protection for their apps.")] Boolean isStateSessionEnabled; + [Write, Description("Indicates if the application should translate urls in the response headers. Keep this value as true unless your application required the original host header in the authentication request. Default value is true.")] Boolean isTranslateHostHeaderEnabled; + [Write, Description("Indicates if the application should translate urls in the application body. Keep this value as false unless you have hardcoded HTML links to other on-premises applications and don't use custom domains. For more information, see Link translation with Application Proxy. Default value is false.")] Boolean isTranslateLinksInBodyEnabled; + [Write, Description("Represents the collection of application segments for an on-premises wildcard application that's published through Microsoft Entra application proxy."), EmbeddedInstance("MSFT_AADApplicationOnPremisesPublishingSegment")] String onPremisesApplicationSegments[]; + [Write, Description("Represents the single sign-on configuration for the on-premises application."), EmbeddedInstance("MSFT_AADApplicationOnPremisesPublishingSingleSignOnSetting")] String singleSignOnSettings; +}; + [ClassVersion("1.0.0")] class MSFT_AADApplicationPermission { @@ -102,6 +154,7 @@ class MSFT_AADApplication : OMI_BaseResource [Write, Description("Specifies whether this application is a public client (such as an installed application running on a mobile device). Default is false.")] Boolean PublicClient; [Write, Description("Specifies the URLs that user tokens are sent to for sign in, or the redirect URIs that OAuth 2.0 authorization codes and access tokens are sent to.")] String ReplyURLs[]; [Write, Description("UPN or ObjectID values of the app's owners.")] String Owners[]; + [Write, Description("Represents the set of properties required for configuring Application Proxy for this application. Configuring these properties allows you to publish your on-premises application for secure remote access."), EmbeddedInstance("MSFT_AADApplicationOnPremisesPublishing")] String OnPremisesPublishing; [Write, Description("Specify if the Azure AD App should exist or not."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; [Write, Description("Credentials for the Microsoft Graph delegated permissions."), EmbeddedInstance("MSFT_Credential")] string Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; From 95b797d382f437f295d79dfa7ff8f9ef49d5a150 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 7 Oct 2024 20:46:17 -0400 Subject: [PATCH 102/252] Update Graph.PermissionList.txt --- Tests/QA/Graph.PermissionList.txt | Bin 5826 -> 6016 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Tests/QA/Graph.PermissionList.txt b/Tests/QA/Graph.PermissionList.txt index 826113f235a6a0d9238e46bc09b5d42a131a610f..be62932022eaf3d89da4e4db939bb3d45f97f4e0 100644 GIT binary patch delta 80 zcmX@4+n~Q;pV;IF+$@q63?&Sy3`Goi42cXm49*PsKvo`5BzdwTpX}s20uszF45^d# gxkM-1G4gThFoZG`gVay{E~q)Vh(m;hmw}4`0D9IF$p8QV delta 12 TcmZqBKcu^1pBM`-0~Z4T9Lxhg From dd8d573a38aaa639b0be5d5f8d6c646e9fb70ae7 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 7 Oct 2024 20:48:03 -0400 Subject: [PATCH 103/252] Fixes UT --- .../Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 | 3 ++- .../Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 index 1998735068..fce902352a 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 @@ -43,6 +43,7 @@ Configuration Example deviceAndAppManagementAssignmentFilterType = 'none' dataType = '#microsoft.graph.allDevicesAssignmentTarget' intent = 'required' + } MSFT_DeviceManagementMobileAppAssignment{ deviceAndAppManagementAssignmentFilterType = 'none' source = 'direct' @@ -50,7 +51,7 @@ Configuration Example groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' intent = 'required' } - }); + ); Categories = @(MSFT_DeviceManagementMobileAppCategory { id = '1bff2652-03ec-4a48-941c-152e93736515' displayName = 'Kajal 3' diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 index dccf286c8b..5687dfcd83 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 @@ -43,6 +43,7 @@ Configuration Example deviceAndAppManagementAssignmentFilterType = 'none' dataType = '#microsoft.graph.allDevicesAssignmentTarget' intent = 'required' + } MSFT_DeviceManagementMobileAppAssignment{ deviceAndAppManagementAssignmentFilterType = 'none' source = 'direct' @@ -50,7 +51,7 @@ Configuration Example groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' intent = 'required' } - }); + ); Categories = @(MSFT_DeviceManagementMobileAppCategory { id = '1bff2652-03ec-4a48-941c-152e93736515' displayName = 'Kajal 3' From 06146dec78beb07a08f9b28686d25ee1a05cb9aa Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 7 Oct 2024 21:32:29 -0400 Subject: [PATCH 104/252] Fixes Unit Tests for IntuneMobileAppsMACLobApp --- .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 15 ---------- ...5DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 | 30 +++++++++++++++++-- Tests/Unit/Stubs/Microsoft365.psm1 | 26 +++++++++++++--- 3 files changed, 49 insertions(+), 22 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 index 664ccca695..1561fcd9ca 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 @@ -797,22 +797,7 @@ function Export-TargetResource $params = @{ Id = $config.Id - Description = $config.Description - Developer = $config.Developer DisplayName = $config.DisplayName - InformationUrl = $config.InformationUrl - IsFeatured = $config.IsFeatured - Notes = $config.Notes - Owner = $config.Owner - PrivacyInformationUrl = $config.PrivacyInformationUrl - Publisher = $config.Publisher - PublishingState = $config.PublishingState.ToString() - RoleScopeTagIds = $config.RoleScopeTagIds - BundleId = $config.BundleId - BuildNumber = $config.BuildNumber - VersionNumber = $config.VersionNumber - IgnoreVersionDetection = $config.AdditionalProperties.ignoreVersionDetection - Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 index 1f0c71c7a5..4e98962328 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 @@ -44,6 +44,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Remove-MgBetaDeviceAppManagementMobileApp -MockWith { } + Mock -CommandName Update-MgBetaDeviceAppManagementMobileAppAssignment -MockWith{} + # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { } @@ -126,10 +128,16 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { PublishingState = "published" RoleScopeTagIds = @() IgnoreVersionDetection = $True - + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.macOSLobApp' + } Ensure = 'Present' } } + + Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppAssignment -MockWith{ + return $null + } } It '2.1 Should return Values from the Get method' { @@ -159,7 +167,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Publisher = "Contoso" PublishingState = "published" RoleScopeTagIds = @() - Ensure = 'Present' Credential = $Credential; } @@ -178,8 +185,14 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Publisher = "Contoso" PublishingState = "published" RoleScopeTagIds = @() + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.macOSLobApp' + } } } + Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppAssignment -MockWith{ + return $null + } } It '3.0 Should return true from the Test method' { @@ -220,9 +233,14 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { PrivacyInformationUrl = "" Publisher = "Contoso" PublishingState = "published" - RoleScopeTagIds = @() + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.macOSLobApp' + } } } + Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppAssignment -MockWith{ + return $null + } } It '4.1 Should return Values from the Get method' { @@ -259,8 +277,14 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Publisher = "Contoso" PublishingState = "published" RoleScopeTagIds = @() + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.macOSLobApp' + } } } + Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppAssignment -MockWith{ + return $null + } } It '5.0 Should Reverse Engineer resource from the Export method' { diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 2ab603a280..c564e5d829 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -19520,19 +19520,19 @@ function Update-MgBetaDeviceAppManagementMobileApp { $PublishingState, [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance[]] + [System.Object[]] $Categories, [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance[]] + [System.Object[]] $Assignments, [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance[]] + [System.Object[]] $ChildApps, [Parameter()] - [System.String[]] + [System.Object[]] $RoleScopeTagIds ) } @@ -93415,6 +93415,24 @@ function Get-MgBetaDeviceAppManagementMobileAppConfiguration ) } +function Update-MgBetaDeviceAppManagementMobileAppAssignment +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $MobileAppId, + + [Parameter()] + [System.Object] + $Target, + + [Parameter()] + [System.String] + $Repository + ) +} + function New-MgBetaDeviceAppManagementMobileAppConfiguration { [CmdletBinding()] From 708aa6b31f2a91b607a539f46c463b7b94db6b88 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 7 Oct 2024 21:46:52 -0400 Subject: [PATCH 105/252] Update Microsoft365.psm1 --- Tests/Unit/Stubs/Microsoft365.psm1 | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index c564e5d829..85c62a8cbb 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -93415,6 +93415,16 @@ function Get-MgBetaDeviceAppManagementMobileAppConfiguration ) } +function Get-MgBetaDeviceAppManagementMobileAppAssignment +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $MobileAppId + ) +} + function Update-MgBetaDeviceAppManagementMobileAppAssignment { [CmdletBinding()] From 38d6efce11056e789fd94cd0cdc5e3f63e0edc7c Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Tue, 8 Oct 2024 01:07:14 -0700 Subject: [PATCH 106/252] Cleaned up, tested and added UTs. --- CHANGELOG.md | 2 + .../MSFT_IntuneDerivedCredential.psm1 | 112 ++++++++++------ ...> MSFT_IntuneDerivedCredential.schema.mof} | 36 ++--- .../MSFT_IntuneDerivedCredential/readme.md | 2 +- .../settings.json | 25 +--- ...SFT_IntuneMobileAppsMacOSLobApp.schema.mof | 4 +- .../IntuneDerivedCredential/1-Create.ps1 | 20 ++- .../IntuneDerivedCredential/2-Update.ps1 | 20 ++- .../IntuneDerivedCredential/3-Remove.ps1 | 21 ++- .../IntuneMobileAppsMacOSLobApp/1-Create.ps1 | 8 +- .../IntuneMobileAppsMacOSLobApp/2-Update.ps1 | 8 +- ...ft365DSC.IntuneDerivedCredential.Tests.ps1 | 125 ++++++++++-------- Tests/Unit/Stubs/Microsoft365.psm1 | 69 ++++++++++ 13 files changed, 270 insertions(+), 182 deletions(-) rename Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/{MSFT_IntuneDerivedCredential.schema..mof => MSFT_IntuneDerivedCredential.schema.mof} (61%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 165117b676..e7c6c08668 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ # UNRELEASED +* IntuneDerivedCredential + * Initial release. * AADAdminConsentRequestPolicy * Initial release. * AADApplication diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.psm1 index fc43dfdeec..4c004cfee1 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.psm1 @@ -2,11 +2,14 @@ function Get-TargetResource { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( + + #region resource params + [Parameter()] [System.String] $Id, - [Parameter()] + [Parameter(Mandatory = $true)] [System.String] $DisplayName, @@ -24,6 +27,12 @@ function Get-TargetResource { [System.String] $NotificationType = 'none', + [Parameter()] + [System.Int32] + $RenewalThresholdPercentage, + + #endregion resource params + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -58,7 +67,6 @@ function Get-TargetResource { $AccessTokens ) - Write-Host "Host: start of get." New-M365DSCConnection -Workload 'MicrosoftGraph' ` -InboundParameters $PSBoundParameters | Out-Null @@ -105,27 +113,25 @@ function Get-TargetResource { return $nullResult } } - } - } - Write-Host "Values of Instance Id: $($instance.Id), DisplayName: $($instance.DisplayName), HelpUrl: $($instance.HelpUrl), Issuer: $($instance.Issuer), NotificationType: $($instance.NotificationType)" + $results = @{ - Ensure = 'Present' - Id = $instance.Id - DisplayName = $instance.DisplayName - HelpUrl = $instance.HelpUrl - Issuer = $instance.Issuer - NotificationType = $instance.NotificationType - Credential = $Credential - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - ApplicationSecret = $ApplicationSecret - ManagedIdentity = $ManagedIdentity.IsPresent - AccessTokens = $AccessTokens + Ensure = 'Present' + Id = $instance.Id + DisplayName = $instance.DisplayName + HelpUrl = $instance.HelpUrl + Issuer = $instance.Issuer.ToString() + NotificationType = $instance.NotificationType.ToString() + RenewalThresholdPercentage = $instance.RenewalThresholdPercentage + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ApplicationSecret = $ApplicationSecret + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens } - Write-Host "Values of Results:: Id: $($results.Id), DisplayName: $($results.DisplayName), HelpUrl: $($results.HelpUrl), Issuer: $($results.Issuer), NotificationType: $($results.NotificationType)" return [System.Collections.Hashtable] $results } @@ -145,11 +151,14 @@ function Get-TargetResource { function Set-TargetResource { [CmdletBinding()] param ( + + #region resource params + [Parameter()] [System.String] $Id, - [Parameter()] + [Parameter(Mandatory = $true)] [System.String] $DisplayName, @@ -162,6 +171,12 @@ function Set-TargetResource { [System.String] $Issuer, + [Parameter()] + [System.Int32] + $RenewalThresholdPercentage, + + #endregion resource params + [Parameter()] [ValidateSet('none', 'email', 'companyPortal')] [System.String] @@ -224,11 +239,6 @@ function Set-TargetResource { { New-MgBetaDeviceManagementDerivedCredential @SetParameters } - # UPDATE - elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') - { - Update-MgBetaDeviceManagementDerivedCredential -DeviceManagementDerivedCredentialSettingsId $currentInstance.Id @SetParameters - } # REMOVE elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { @@ -240,11 +250,14 @@ function Test-TargetResource { [CmdletBinding()] [OutputType([System.Boolean])] param ( + + #region resource params + [Parameter()] [System.String] $Id, - [Parameter()] + [Parameter(Mandatory = $true)] [System.String] $DisplayName, @@ -262,6 +275,12 @@ function Test-TargetResource { [System.String] $NotificationType = 'none', + [Parameter()] + [System.Int32] + $RenewalThresholdPercentage, + + #endregion resource params + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -327,6 +346,9 @@ function Export-TargetResource { [CmdletBinding()] [OutputType([System.String])] param ( + + #region resource params + [Parameter()] [System.String] $Id, @@ -349,10 +371,17 @@ function Export-TargetResource { [System.String] $NotificationType = 'none', + [Parameter()] + [System.Int32] + $RenewalThresholdPercentage, + + #endregion resource params + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] $Ensure = 'Present', + [Parameter()] [System.Management.Automation.PSCredential] $Credential, @@ -381,7 +410,6 @@ function Export-TargetResource { [System.String[]] $AccessTokens ) - Write-Host "Host: start of export." $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` -InboundParameters $PSBoundParameters @@ -417,20 +445,22 @@ function Export-TargetResource { { $displayedKey = $config.Id Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ - Ensure = 'Present' - Id = $config.Id - DisplayName = $config.DisplayName - HelpUrl = $config.HelpUrl - Issuer = $config.Issuer - NotificationType = $config.NotificationType - Credential = $Credential - AccessTokens = $AccessTokens - ApplicationId = $ApplicationId - TenantId = $TenantId - ApplicationSecret = $ApplicationSecret - CertificateThumbprint = $CertificateThumbprint - ManagedIdentity = $ManagedIdentity.IsPresent + Ensure = 'Present' + Id = $config.Id + DisplayName = $config.DisplayName + HelpUrl = $config.HelpUrl + Issuer = $config.Issuer.ToString() + NotificationType = $config.NotificationType.ToString() + RenewalThresholdPercentage = $config.RenewalThresholdPercentage + Credential = $Credential + AccessTokens = $AccessTokens + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params @@ -448,6 +478,7 @@ function Export-TargetResource { $i++ Write-Host $Global:M365DSCEmojiGreenCheckMark } + return $dscContent } catch @@ -462,7 +493,6 @@ function Export-TargetResource { return '' } - } Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.schema..mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.schema.mof similarity index 61% rename from Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.schema..mof rename to Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.schema.mof index 990a94b0d6..e893173409 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.schema..mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.schema.mof @@ -1,29 +1,31 @@ [ClassVersion("1.0.0.0"), FriendlyName("IntuneDerivedCredential")] -class MSFT_IntuneDerivedCredential : OMI_BaseResource { - [Write, Description("The name of the app category.")] - String DisplayName; +class MSFT_IntuneDerivedCredential : OMI_BaseResource +{ + [Key, Description("The name of the app category.")] String DisplayName; + [Write, Description("The unique identifier for an entity. Read-only.")] String Id; - [Write, Description("The unique identifier for an entity. Read-only.")] - String Id; + [Write, Description("The URL that will be accessible to end users as they retrieve a derived credential using the Company Portal.")] String HelpUrl; + [Write, Description("The nominal percentage of time before certificate renewal is initiated by the client.")] Uint32 RenewalThresholdPercentage; + [Write, Description("Supported values for the derived credential issuer."), + ValueMap{"intercede", "entrustDatacard", "purebred"}, + Values{"intercede", "entrustDatacard", "purebred"}] + String Issuer; - [Write, Description("The URL that will be accessible to end users as they retrieve a derived credential using the Company Portal.")] - String HelpUrl; + [Write, Description("Supported values for the notification type to use."), + ValueMap{"none", "email", "companyPortal"}, + Values{"none", "email", "companyPortal"}] + String NotificationType; - [Write, Description("Supported values for the derived credential issuer."), ValueMap{"intercede", "entrustDatacard", "purebred"}, Values{"intercede", "entrustDatacard", "purebred"}] - String Issuer; + [Write, Description("Supported values for the notification type to use."), + ValueMap{"Present", "Absent"}, + Values{"Present", "Absent"}] + String Ensure; - [Write, Description("Supported values for the notification type to use."), ValueMap{"none", "email", "companyPortal"}, Values{"none", "email", "companyPortal"}] - String NotificationType = "none"; // Default value is set to "none" - - [Write, Description("Supported values for the notification type to use."), ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] - String Ensure = "Present"; // Default value is set to "none" - - [Write, Description("Credentials of the Intune Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Credentials of the Intune Admin"), EmbeddedInstance("MSFT_Credential")] String Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com")] String TenantId; [Write, Description("Secret of the Azure Active Directory tenant used for authentication."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; [Write, Description("Access token used for authentication.")] String AccessTokens[]; - }; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/readme.md index 5fb6aed2fe..124a837b06 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/readme.md @@ -3,4 +3,4 @@ ## Description -##Create new navigation property to derivedCredentials for deviceManagement +## Create new navigation property to derivedCredentials for deviceManagement for Intune. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/settings.json index f4606a14af..1ca28f6ad4 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/settings.json @@ -1,40 +1,25 @@ { "resourceName": "IntuneDerivedCredential", - "description": "Use this resource to create new navigation property to derivedCredentials for deviceManagement", - // "roles": { - // "read": [ - // "Global Reader" - // ], - // "update": [ - // "Intune Administrator" - // ] - // }, + "description": "Use this resource to create new navigation property to derivedCredentials for device Management in Intune.", "permissions": { "graph": { "delegated": { "read": [ - "DeviceManagementConfiguration.Read.All" + "" ], "update": [ - "DeviceManagementConfiguration.ReadWrite.All" + "" ] }, "application": { "read": [ - "DeviceManagementConfiguration.Read.All" + "" ], "update": [ - "DeviceManagementConfiguration.ReadWrite.All" + "" ] } } } } - -// PS C:\Windows\system32> Find-MgGraphCommand -Command “Get-MgBetaDeviceManagementDerivedCredential” | select Permissions - // OUTPUT: - // Permissions - // ----------- - // {} - // {} diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof index 88248b6460..c2aaec8d81 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof @@ -13,11 +13,11 @@ class MSFT_IntuneMobileAppsMacOSLobApp : OMI_BaseResource [Write, Description("The privacy statement Url. Inherited from mobileApp.")] String PrivacyInformationUrl; [Write, Description("The publisher of the app. Inherited from mobileApp.")] String Publisher; [Write, Description("The publishing state for the app. The app cannot be assigned unless the app is published. Inherited from mobileApp."), ValueMap{"notPublished", "processing","published"}, Values{"notPublished", "processing", "published"}] String PublishingState; - [Write, Description("The bundleId of the app.")] String BundleId; + [Write, Description("The bundleId of the app.")] String BundleId; [Write, Description("The build number of the app.")] String BuildNumber; [Write, Description("The version number of the app.")] String VersionNumber; [Write, Description("List of Scope Tag IDs for mobile app.")] String RoleScopeTagIds[]; - [Write, Description("Wether to ignore the version of the app or not.")] Boolean IgnoreVersionDetection; + [Write, Description("Whether to ignore the version of the app or not.")] Boolean IgnoreVersionDetection; [Write, Description("The icon for this app."), EmbeddedInstance("MSFT_DeviceManagementMimeContent")] String LargeIcon; [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppCategory")] String Categories[]; [Write, Description("The list of assignments for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppAssignment")] String Assignments[]; diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/1-Create.ps1 index 07f1840e08..04a9cefe20 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/1-Create.ps1 @@ -14,18 +14,14 @@ Configuration Example { Import-DscResource -ModuleName Microsoft365DSC node localhost { - IntuneDerivedCredential "IntuneDerivedCredential-DataManagement" { - Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606" - DisplayName = "Custom Data Management" - Ensure = "Present" - HelpUrl = "https://www.microsoft.com" - Issuer = "DISA Purebred" - NotificationType = "Email" - ThresholdPercentage = 0 - Header = @( - [PSCustomObject]@{ Key = 'HeaderKey1'; Value = 'HeaderValue1' } - [PSCustomObject]@{ Key = 'HeaderKey2'; Value = 'HeaderValue2' } - ) + IntuneDerivedCredential "IntuneDerivedCredential-K5" + { + DisplayName = "K5"; + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; + Ensure = "Present"; } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/2-Update.ps1 index 07f1840e08..04a9cefe20 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/2-Update.ps1 @@ -14,18 +14,14 @@ Configuration Example { Import-DscResource -ModuleName Microsoft365DSC node localhost { - IntuneDerivedCredential "IntuneDerivedCredential-DataManagement" { - Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606" - DisplayName = "Custom Data Management" - Ensure = "Present" - HelpUrl = "https://www.microsoft.com" - Issuer = "DISA Purebred" - NotificationType = "Email" - ThresholdPercentage = 0 - Header = @( - [PSCustomObject]@{ Key = 'HeaderKey1'; Value = 'HeaderValue1' } - [PSCustomObject]@{ Key = 'HeaderKey2'; Value = 'HeaderValue2' } - ) + IntuneDerivedCredential "IntuneDerivedCredential-K5" + { + DisplayName = "K5"; + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; + Ensure = "Present"; } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/3-Remove.ps1 index a6c927219e..4c67edeead 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/3-Remove.ps1 @@ -14,19 +14,14 @@ Configuration Example { Import-DscResource -ModuleName Microsoft365DSC node localhost { - IntuneDerivedCredential "IntuneDerivedCredential-DataManagement" { - Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606" - DisplayName = "Custom Data Management" - Ensure = "Present" - HelpUrl = "https://www.microsoft.com" - Issuer = "DISA Purebred" - NotificationType = "Email" - ThresholdPercentage = 0 - Header = @( - [PSCustomObject]@{ Key = 'HeaderKey1'; Value = 'HeaderValue1' } - [PSCustomObject]@{ Key = 'HeaderKey2'; Value = 'HeaderValue2' } - ) + IntuneDerivedCredential "IntuneDerivedCredential-K5" + { + DisplayName = "K5"; + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; + Ensure = "Absent"; } } } - diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 index 1998735068..88d09f9512 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 @@ -37,20 +37,20 @@ Configuration Example Publisher = "Contoso"; PublishingState = "published"; Assignments = @( - MSFT_DeviceManagementMobileAppAssignment{ - groupDisplayName = 'All devices' + MSFT_DeviceManagementMobileAppAssignment { + groupDisplayName = 'All devices' source = 'direct' deviceAndAppManagementAssignmentFilterType = 'none' dataType = '#microsoft.graph.allDevicesAssignmentTarget' intent = 'required' + } MSFT_DeviceManagementMobileAppAssignment{ deviceAndAppManagementAssignmentFilterType = 'none' source = 'direct' dataType = '#microsoft.graph.groupAssignmentTarget' groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' intent = 'required' - } - }); + }); Categories = @(MSFT_DeviceManagementMobileAppCategory { id = '1bff2652-03ec-4a48-941c-152e93736515' displayName = 'Kajal 3' diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 index dccf286c8b..e54b97d9c5 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 @@ -37,20 +37,20 @@ Configuration Example Publisher = "Contoso"; PublishingState = "published"; Assignments = @( - MSFT_DeviceManagementMobileAppAssignment{ + MSFT_DeviceManagementMobileAppAssignment { groupDisplayName = 'All devices' source = 'direct' deviceAndAppManagementAssignmentFilterType = 'none' dataType = '#microsoft.graph.allDevicesAssignmentTarget' intent = 'required' - MSFT_DeviceManagementMobileAppAssignment{ + }, + MSFT_DeviceManagementMobileAppAssignment { deviceAndAppManagementAssignmentFilterType = 'none' source = 'direct' dataType = '#microsoft.graph.groupAssignmentTarget' groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' intent = 'required' - } - }); + }); Categories = @(MSFT_DeviceManagementMobileAppCategory { id = '1bff2652-03ec-4a48-941c-152e93736515' displayName = 'Kajal 3' diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDerivedCredential.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDerivedCredential.Tests.ps1 index 1df65bd189..479cb308f4 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDerivedCredential.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDerivedCredential.Tests.ps1 @@ -39,140 +39,149 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Write-Host -MockWith { } - Mock -CommandName Get-MgBetaDeviceManagementDerivedCredentialy -MockWith { + Mock -CommandName Get-MgBetaDeviceManagementDerivedCredential -MockWith { } Mock -CommandName New-MgBetaDeviceManagementDerivedCredential -MockWith { } - Mock -CommandName Update-MgBetaDeviceManagementDerivedCredential -MockWith { - } Mock -CommandName Remove-MgBetaDeviceManagementDerivedCredential -MockWith { } $Script:exportedInstances =$null $Script:ExportMode = $false } + # Test contexts - Context -Name "The instance should exist but it DOES NOT" -Fixture { + Context -Name " 1. The instance should exist but it DOES NOT" -Fixture { BeforeAll { $testParams = @{ - Ensure = 'Present' - Id = $instance.Id - DisplayName = $instance.DisplayName - HelpUrl = $HelpUrl - Issuer = $Issuer - NotificationType = $NotificationType - ThresholdPercentage = $ThresholdPercentage - Header = $Header + Ensure = 'Present' + DisplayName = "K5"; + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; + Credential = $Credential } Mock -CommandName Get-MgBetaDeviceManagementDerivedCredential -MockWith { return $null } } - It 'Should return Values from the Get method' { + It ' 1.1 Should return Values from the Get method' { (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' } - It 'Should return false from the Test method' { + It ' 1.2 Should return false from the Test method' { Test-TargetResource @testParams | Should -Be $false } - It 'Should create a new instance from the Set method' { + It ' 1.3 Should create a new instance from the Set method' { Set-TargetResource @testParams Should -Invoke -CommandName New-MgBetaDeviceManagementDerivedCredential -Exactly 1 } } - Context -Name "The instance exists but it SHOULD NOT" -Fixture { + Context -Name " 2. The instance exists but it SHOULD NOT" -Fixture { BeforeAll { $testParams = @{ - Ensure = 'Present' - Id = $instance.Id - DisplayName = $instance.DisplayName - HelpUrl = $HelpUrl - Issuer = $Issuer - NotificationType = $NotificationType - ThresholdPercentage = $ThresholdPercentage - Header = $Header + Ensure = 'Present' + DisplayName = "K5"; + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; + Credential = $Credential } Mock -CommandName Get-MgBetaDeviceManagementDerivedCredential -MockWith { return @{ - + DisplayName = "K5"; + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; } } } - It 'Should return Values from the Get method' { + It ' 2.1 Should return Values from the Get method' { (Get-TargetResource @testParams).Ensure | Should -Be 'Present' } - It 'Should return false from the Test method' { + It ' 2.2 Should return false from the Test method' { Test-TargetResource @testParams | Should -Be $false } - It 'Should remove the instance from the Set method' { + It ' 2.3 Should remove the instance from the Set method' { Set-TargetResource @testParams Should -Invoke -CommandName Remove-MgBetaDeviceManagementDerivedCredential -Exactly 1 } } - Context -Name "The instance exists and values are already in the desired state" -Fixture { + Context -Name " 3. The instance exists and values are already in the desired state" -Fixture { BeforeAll { $testParams = @{ - Ensure = 'Present' - Id = $instance.Id - DisplayName = $instance.DisplayName - HelpUrl = $HelpUrl - Issuer = $Issuer - NotificationType = $NotificationType - ThresholdPercentage = $ThresholdPercentage - Header = $Header + Ensure = 'Present' + DisplayName = "K5"; + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; + Credential = $Credential } Mock -CommandName Get-MgBetaDeviceManagementDerivedCredential -MockWith { return @{ - + Ensure = 'Present' + DisplayName = "K5"; + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; } } } - It 'Should return true from the Test method' { + It ' 3.0 Should return true from the Test method' { Test-TargetResource @testParams | Should -Be $true } } - Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + Context -Name " 4. The instance exists and values are NOT in the desired state" -Fixture { BeforeAll { $testParams = @{ - Ensure = 'Present' - Id = $instance.Id - DisplayName = $instance.DisplayName - HelpUrl = $HelpUrl - Issuer = $Issuer - NotificationType = $NotificationType - ThresholdPercentage = $ThresholdPercentage - Header = $Header + Ensure = 'Present' + DisplayName = "K5"; + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; + Credential = $Credential } Mock -CommandName Get-MgBetaDeviceManagementDerivedCredential -MockWith { return @{ - + DisplayName = "K5 drift"; #drift + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; } } } - It 'Should return Values from the Get method' { + It ' 4.1 Should return Values from the Get method' { (Get-TargetResource @testParams).Ensure | Should -Be 'Present' } - It 'Should return false from the Test method' { + It ' 4.2 Should return false from the Test method' { Test-TargetResource @testParams | Should -Be $false } - It 'Should call the Set method' { + # Update is not allowed on DerivedCredential resource so it should be called 0 times. + It ' 4.3 Should call the Set method' { Set-TargetResource @testParams - Should -Invoke -CommandName Update-MgBetaDeviceManagementDerivedCredential -Exactly 1 + Should -Invoke -CommandName Update-MgBetaDeviceManagementDerivedCredential -Exactly 0 } } - Context -Name 'ReverseDSC Tests' -Fixture { + Context -Name ' 5. ReverseDSC Tests' -Fixture { BeforeAll { $Global:CurrentModeIsExport = $true $Global:PartialExportFileName = "$(New-Guid).partial.ps1" @@ -182,11 +191,15 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-MgBetaDeviceManagementDerivedCredential -MockWith { return @{ - + DisplayName = "K5"; + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; } } } - It 'Should Reverse Engineer resource from the Export method' { + It ' 5.0 Should Reverse Engineer resource from the Export method' { $result = Export-TargetResource @testParams $result | Should -Not -BeNullOrEmpty } diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 2ab603a280..9530dae2ac 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -19348,6 +19348,75 @@ function Get-MgBetaDeviceManagementGroupPolicyConfigurationAssignment ) } +New-MgBetaDeviceManagementDerivedCredential { + + [CmdletBinding()] + param ( + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $HelpUrl, + + [Parameter()] + [ValidateSet('intercede', 'entrustData', 'purebred')] + [System.String] + $Issuer, + + [Parameter()] + [ValidateSet('none', 'email', 'companyPortal')] + [System.String] + $NotificationType = 'none' + ) +} + +Get-MgBetaDeviceManagementDerivedCredential { + [CmdletBinding()] + param ( + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $HelpUrl, + + [Parameter()] + [ValidateSet('intercede', 'entrustData', 'purebred')] + [System.String] + $Issuer, + + [Parameter()] + [ValidateSet('none', 'email', 'companyPortal')] + [System.String] + $NotificationType = 'none' + ) +} + +Remove-MgBetaDeviceManagementDerivedCredential +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $DerivedCredentialId, + + [Parameter()] + [System.Boolean] + $Confirm + ) +} + function New-MgBetaDeviceAppManagementMobileApp { [CmdletBinding()] param ( From 64ede975c93c5c026bd6b8f7099c2c9049b42665 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 8 Oct 2024 10:45:34 +0000 Subject: [PATCH 107/252] Updated Resources and Cmdlet documentation pages --- .../docs/resources/azure-ad/AADApplication.md | 63 +++++++++++++++++++ .../intune/IntuneMobileAppsMacOSLobApp.md | 6 +- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/docs/docs/resources/azure-ad/AADApplication.md b/docs/docs/resources/azure-ad/AADApplication.md index 3ad2464b54..ffd452c3b2 100644 --- a/docs/docs/resources/azure-ad/AADApplication.md +++ b/docs/docs/resources/azure-ad/AADApplication.md @@ -24,6 +24,7 @@ | **PublicClient** | Write | Boolean | Specifies whether this application is a public client (such as an installed application running on a mobile device). Default is false. | | | **ReplyURLs** | Write | StringArray[] | Specifies the URLs that user tokens are sent to for sign in, or the redirect URIs that OAuth 2.0 authorization codes and access tokens are sent to. | | | **Owners** | Write | StringArray[] | UPN or ObjectID values of the app's owners. | | +| **OnPremisesPublishing** | Write | MSFT_AADApplicationOnPremisesPublishing | Represents the set of properties required for configuring Application Proxy for this application. Configuring these properties allows you to publish your on-premises application for secure remote access. | | | **Ensure** | Write | String | Specify if the Azure AD App should exist or not. | `Present`, `Absent` | | **Credential** | Write | PSCredential | Credentials for the Microsoft Graph delegated permissions. | | | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | @@ -34,6 +35,68 @@ | **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | | **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | +### MSFT_AADApplicationOnPremisesPublishingSegmentCORS + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **allowedHeaders** | Write | StringArray[] | The request headers that the origin domain may specify on the CORS request. The wildcard character * indicates that any header beginning with the specified prefix is allowed. | | +| **maxAgeInSeconds** | Write | UInt32 | The maximum amount of time that a browser should cache the response to the preflight OPTIONS request. | | +| **resource** | Write | String | Resource within the application segment for which CORS permissions are granted. / grants permission for whole app segment. | | +| **allowedMethods** | Write | StringArray[] | The HTTP request methods that the origin domain may use for a CORS request. | | +| **allowedOrigins** | Write | StringArray[] | The origin domains that are permitted to make a request against the service via CORS. The origin domain is the domain from which the request originates. The origin must be an exact case-sensitive match with the origin that the user age sends to the service. | | + +### MSFT_AADApplicationOnPremisesPublishingSegment + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **alternateUrl** | Write | String | If you're configuring a traffic manager in front of multiple App Proxy application segments, contains the user-friendly URL that will point to the traffic manager. | | +| **corsConfigurations** | Write | MSFT_AADApplicationOnPremisesPublishingSegmentCORS[] | CORS Rule definition for a particular application segment. | | +| **externalUrl** | Write | String | The published external URL for the application segment; for example, https://intranet.contoso.com./ | | +| **internalUrl** | Write | String | The internal URL of the application segment; for example, https://intranet/. | | + +### MSFT_AADApplicationOnPremisesPublishingSingleSignOnSettingKerberos + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **kerberosServicePrincipalName** | Write | String | The Internal Application SPN of the application server. This SPN needs to be in the list of services to which the connector can present delegated credentials. | | +| **kerberosSignOnMappingAttributeType** | Write | String | The Delegated Login Identity for the connector to use on behalf of your users. For more information, see Working with different on-premises and cloud identities . Possible values are: userPrincipalName, onPremisesUserPrincipalName, userPrincipalUsername, onPremisesUserPrincipalUsername, onPremisesSAMAccountName. | | + +### MSFT_AADApplicationOnPremisesPublishingSingleSignOnSetting + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **singleSignOnMode** | Write | String | The preferred single-sign on mode for the application. Possible values are: none, onPremisesKerberos, aadHeaderBased,pingHeaderBased, oAuthToken. | | +| **kerberosSignOnSettings** | Write | MSFT_AADApplicationOnPremisesPublishingSingleSignOnSettingKerberos | The Kerberos Constrained Delegation settings for applications that use Integrated Window Authentication. | | + +### MSFT_AADApplicationOnPremisesPublishing + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **alternateUrl** | Write | String | If you're configuring a traffic manager in front of multiple App Proxy applications, the alternateUrl is the user-friendly URL that points to the traffic manager. | | +| **applicationServerTimeout** | Write | String | The duration the connector waits for a response from the backend application before closing the connection. Possible values are default, long. | | +| **externalAuthenticationType** | Write | String | Details the pre-authentication setting for the application. Pre-authentication enforces that users must authenticate before accessing the app. Pass through doesn't require authentication. Possible values are: passthru, aadPreAuthentication. | | +| **externalUrl** | Write | String | The published external url for the application. For example, https://intranet-contoso.msappproxy.net/. | | +| **internalUrl** | Write | String | The internal url of the application. For example, https://intranet/. | | +| **isBackendCertificateValidationEnabled** | Write | Boolean | Indicates whether backend SSL certificate validation is enabled for the application. For all new Application Proxy apps, the property is set to true by default. For all existing apps, the property is set to false. | | +| **isHttpOnlyCookieEnabled** | Write | Boolean | Indicates if the HTTPOnly cookie flag should be set in the HTTP response headers. Set this value to true to have Application Proxy cookies include the HTTPOnly flag in the HTTP response headers. If using Remote Desktop Services, set this value to False. Default value is false. | | +| **isPersistentCookieEnabled** | Write | Boolean | Indicates if the Persistent cookie flag should be set in the HTTP response headers. Keep this value set to false. Only use this setting for applications that can't share cookies between processes. For more information about cookie settings, see Cookie settings for accessing on-premises applications in Microsoft Entra ID. Default value is false. | | +| **isSecureCookieEnabled** | Write | Boolean | Indicates if the Secure cookie flag should be set in the HTTP response headers. Set this value to true to transmit cookies over a secure channel such as an encrypted HTTPS request. Default value is true. | | +| **isStateSessionEnabled** | Write | Boolean | Indicates whether validation of the state parameter when the client uses the OAuth 2.0 authorization code grant flow is enabled. This setting allows admins to specify whether they want to enable CSRF protection for their apps. | | +| **isTranslateHostHeaderEnabled** | Write | Boolean | Indicates if the application should translate urls in the response headers. Keep this value as true unless your application required the original host header in the authentication request. Default value is true. | | +| **isTranslateLinksInBodyEnabled** | Write | Boolean | Indicates if the application should translate urls in the application body. Keep this value as false unless you have hardcoded HTML links to other on-premises applications and don't use custom domains. For more information, see Link translation with Application Proxy. Default value is false. | | +| **onPremisesApplicationSegments** | Write | MSFT_AADApplicationOnPremisesPublishingSegment[] | Represents the collection of application segments for an on-premises wildcard application that's published through Microsoft Entra application proxy. | | +| **singleSignOnSettings** | Write | MSFT_AADApplicationOnPremisesPublishingSingleSignOnSetting | Represents the single sign-on configuration for the on-premises application. | | + ### MSFT_AADApplicationPermission #### Parameters diff --git a/docs/docs/resources/intune/IntuneMobileAppsMacOSLobApp.md b/docs/docs/resources/intune/IntuneMobileAppsMacOSLobApp.md index 412b83d61a..de60700954 100644 --- a/docs/docs/resources/intune/IntuneMobileAppsMacOSLobApp.md +++ b/docs/docs/resources/intune/IntuneMobileAppsMacOSLobApp.md @@ -154,6 +154,7 @@ Configuration Example deviceAndAppManagementAssignmentFilterType = 'none' dataType = '#microsoft.graph.allDevicesAssignmentTarget' intent = 'required' + } MSFT_DeviceManagementMobileAppAssignment{ deviceAndAppManagementAssignmentFilterType = 'none' source = 'direct' @@ -161,7 +162,7 @@ Configuration Example groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' intent = 'required' } - }); + ); Categories = @(MSFT_DeviceManagementMobileAppCategory { id = '1bff2652-03ec-4a48-941c-152e93736515' displayName = 'Kajal 3' @@ -217,6 +218,7 @@ Configuration Example deviceAndAppManagementAssignmentFilterType = 'none' dataType = '#microsoft.graph.allDevicesAssignmentTarget' intent = 'required' + } MSFT_DeviceManagementMobileAppAssignment{ deviceAndAppManagementAssignmentFilterType = 'none' source = 'direct' @@ -224,7 +226,7 @@ Configuration Example groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' intent = 'required' } - }); + ); Categories = @(MSFT_DeviceManagementMobileAppCategory { id = '1bff2652-03ec-4a48-941c-152e93736515' displayName = 'Kajal 3' From a12f665aa56448cd15c03b594d28bf867388c758 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 8 Oct 2024 10:47:54 +0000 Subject: [PATCH 108/252] Updated {Create} Intune Integration Tests --- .../Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 index a3e123f77e..e76c7e0a1b 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 @@ -2528,6 +2528,7 @@ deviceAndAppManagementAssignmentFilterType = 'none' dataType = '#microsoft.graph.allDevicesAssignmentTarget' intent = 'required' + } MSFT_DeviceManagementMobileAppAssignment{ deviceAndAppManagementAssignmentFilterType = 'none' source = 'direct' @@ -2535,7 +2536,7 @@ groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' intent = 'required' } - }); + ); Categories = @(MSFT_DeviceManagementMobileAppCategory { id = '1bff2652-03ec-4a48-941c-152e93736515' displayName = 'Kajal 3' From 2c8eefac5c7f70eaff4ab3e30e15d2c78de0b2c9 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 8 Oct 2024 11:21:43 +0000 Subject: [PATCH 109/252] Updated Graph Permissions List --- Tests/QA/Graph.PermissionList.txt | Bin 6016 -> 5826 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Tests/QA/Graph.PermissionList.txt b/Tests/QA/Graph.PermissionList.txt index be62932022eaf3d89da4e4db939bb3d45f97f4e0..826113f235a6a0d9238e46bc09b5d42a131a610f 100644 GIT binary patch delta 12 TcmZqBKcu^1pBM`-0~Z4T9Lxhg delta 80 zcmX@4+n~Q;pV;IF+$@q63?&Sy3`Goi42cXm49*PsKvo`5BzdwTpX}s20uszF45^d# gxkM-1G4gThFoZG`gVay{E~q)Vh(m;hmw}4`0D9IF$p8QV From 5086ba8adc8c7e07031d2d878f9eb59fb55a62a1 Mon Sep 17 00:00:00 2001 From: "Ritik Mittal (from Dev Box)" Date: Tue, 8 Oct 2024 16:52:00 +0530 Subject: [PATCH 110/252] added name as primary key --- ...SFT_AADConnectorGroupApplicationProxy.psm1 | 50 +++++++++++++------ ...DConnectorGroupApplicationProxy.schema.mof | 4 +- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/MSFT_AADConnectorGroupApplicationProxy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/MSFT_AADConnectorGroupApplicationProxy.psm1 index 5e244d28ec..d77e4aa571 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/MSFT_AADConnectorGroupApplicationProxy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/MSFT_AADConnectorGroupApplicationProxy.psm1 @@ -4,7 +4,7 @@ function Get-TargetResource [OutputType([System.Collections.Hashtable])] param ( - [Parameter()] + [Parameter(Mandatory = $true)] [System.String] $Name, @@ -13,12 +13,10 @@ function Get-TargetResource [System.String] $Region, - [Parameter(Mandatory = $true)] + [Parameter()] [System.String] $Id, - #endregion - [Parameter()] [System.String] [ValidateSet('Absent', 'Present')] @@ -75,19 +73,42 @@ function Get-TargetResource $getValue = $null #region resource generator code - $getValue = Get-MgBetaOnPremisePublishingProfileConnectorGroup ` - -ConnectorGroupId $Id ` - -OnPremisesPublishingProfileId 'applicationProxy' -ErrorAction SilentlyContinue + if (-not [string]::IsNullOrEmpty($Id)) + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + $getValue = $Script:exportedInstances | Where-Object -FilterScript {$_.Id -eq $Id} + } + else + { + $getValue = Get-MgBetaOnPremisePublishingProfileConnectorGroup -ConnectorGroupId $Id -OnPremisesPublishingProfileId 'applicationProxy' -ErrorAction SilentlyContinue + } + } + if ($null -eq $getValue -and -not [string]::IsNullOrEmpty($Id)) + { + Write-Verbose -Message "Could not find an Azure AD Connector Group Application Proxy with Name {$Name}" + if (-Not [string]::IsNullOrEmpty($DisplayName)) + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + $getValue = $Script:exportedInstances | Where-Object -FilterScript {$_.Name -eq $Name} + } + else + { + $getValue = Get-MgBetaOnPremisePublishingProfileConnectorGroup -OnPremisesPublishingProfileId 'applicationProxy' -Filter "Name eq '$Name'" -ErrorAction Stop + } + } + } + #endregion if ($null -eq $getValue) { - Write-Verbose -Message "Could not find an Azure AD Connector Group Application Proxy with Id {$Id}" + Write-Verbose -Message "Could not find an Azure AD Connector Group Application Proxy with Name {$Name}" return $nullResult } - #endregion $Id = $getValue.Id - Write-Verbose -Message "An Azure AD Connector Group Application Proxy with Id {$Id} was found" + Write-Verbose -Message "An Azure AD Connector Group Application Proxy with Id {$Id} and Name {$Name} was found" $enumRegion = $null if ($null -ne $getValue.Region) @@ -130,7 +151,7 @@ function Set-TargetResource [CmdletBinding()] param ( - [Parameter()] + [Parameter(Mandatory = $true)] [System.String] $Name, @@ -139,11 +160,10 @@ function Set-TargetResource [System.String] $Region, - [Parameter(Mandatory = $true)] + [Parameter()] [System.String] $Id, - #endregion [Parameter()] [System.String] [ValidateSet('Absent', 'Present')] @@ -240,7 +260,7 @@ function Test-TargetResource param ( #region resource generator code - [Parameter()] + [Parameter(Mandatory = $true)] [System.String] $Name, @@ -249,7 +269,7 @@ function Test-TargetResource [System.String] $Region, - [Parameter(Mandatory = $true)] + [Parameter()] [System.String] $Id, diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/MSFT_AADConnectorGroupApplicationProxy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/MSFT_AADConnectorGroupApplicationProxy.schema.mof index a41c3653cf..f38974f6d8 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/MSFT_AADConnectorGroupApplicationProxy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/MSFT_AADConnectorGroupApplicationProxy.schema.mof @@ -2,9 +2,9 @@ [ClassVersion("1.0.0.0"), FriendlyName("AADConnectorGroupApplicationProxy")] class MSFT_AADConnectorGroupApplicationProxy : OMI_BaseResource { - [Write, Description("The name associated with the connectorGroup.")] String Name; + [Key, Description("The name associated with the connectorGroup.")] String Name; [Write, Description("The region the connectorGroup is assigned to and will optimize traffic for. This region can only be set if no connectors or applications are assigned to the connectorGroup. The possible values are: nam (for North America), eur (for Europe), aus (for Australia), asia (for Asia), ind (for India), and unknownFutureValue."), ValueMap{"nam","eur","aus","asia","ind","unknownFutureValue"}, Values{"nam","eur","aus","asia","ind","unknownFutureValue"}] String Region; - [Key, Description("The unique identifier for an entity. Read-only.")] String Id; + [Write, Description("The unique identifier for an entity. Read-only.")] String Id; [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; From 005e9c3ec3a011c084cef21250ea880312a6d9a3 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 8 Oct 2024 11:24:53 +0000 Subject: [PATCH 111/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 1b1c79d4c2..d0ae19637e 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -2635,7 +2635,7 @@ { "CIMType": "String", "Name": "Name", - "Option": "Write" + "Option": "Key" }, { "CIMType": "String", @@ -2645,7 +2645,7 @@ { "CIMType": "String", "Name": "Id", - "Option": "Key" + "Option": "Write" }, { "CIMType": "string", From ffcd42d06200a44acf0271f8ae11a120c0e0adf9 Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Tue, 8 Oct 2024 14:45:45 +0200 Subject: [PATCH 112/252] Add deprecation notice to Intune resources --- CHANGELOG.md | 4 ++++ .../MSFT_IntuneAccountProtectionPolicy.psm1 | 3 +++ ...DeviceConfigurationIdentityProtectionPolicyWindows10.psm1 | 5 ++++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99eb9d728d..fa354f54e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,9 +15,13 @@ * Initial release. * EXOMigrationEndpoint * Initial Release +* IntuneAccountProtectionPolicy + * Added deprecation notice. * IntuneAppAndBrowserIsolationPolicyWindows10 * Initial release. FIXES [#3028](https://github.com/microsoft/Microsoft365DSC/issues/3028) +* IntuneDeviceConfigurationIdentityProtectionPolicyWindows10 + * Added deprecation notice. * IntuneEndpointDetectionAndResponsePolicyWindows10 * Migrate to new Settings Catalog cmdlets. * IntuneMobileAppsMacOSLobApp diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicy/MSFT_IntuneAccountProtectionPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicy/MSFT_IntuneAccountProtectionPolicy.psm1 index 467c65118e..510bddb1d7 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicy/MSFT_IntuneAccountProtectionPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicy/MSFT_IntuneAccountProtectionPolicy.psm1 @@ -371,6 +371,9 @@ function Set-TargetResource $AccessTokens ) + Write-Warning -Message "The resource 'IntuneAccountProtectionPolicy' is deprecated. It will be removed in a future release. Please use 'IntuneAccountProtectionPolicyWindows10' instead." + Write-Warning -Message "For more information, please visit https://learn.microsoft.com/en-us/mem/intune/fundamentals/whats-new#consolidation-of-intune-profiles-for-identity-protection-and-account-protection-" + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` -InboundParameters $PSBoundParameters diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationIdentityProtectionPolicyWindows10/MSFT_IntuneDeviceConfigurationIdentityProtectionPolicyWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationIdentityProtectionPolicyWindows10/MSFT_IntuneDeviceConfigurationIdentityProtectionPolicyWindows10.psm1 index 667a0789f3..ced6ab6e4d 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationIdentityProtectionPolicyWindows10/MSFT_IntuneDeviceConfigurationIdentityProtectionPolicyWindows10.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationIdentityProtectionPolicyWindows10/MSFT_IntuneDeviceConfigurationIdentityProtectionPolicyWindows10.psm1 @@ -214,7 +214,7 @@ function Get-TargetResource AccessTokens = $AccessTokens #endregion } - + $assignmentsValues = Get-MgBetaDeviceManagementDeviceConfigurationAssignment -DeviceConfigurationId $Id $assignmentResult = @() if ($assignmentsValues.Count -gt 0) @@ -359,6 +359,9 @@ function Set-TargetResource $AccessTokens ) + Write-Warning -Message "The resource 'IntuneDeviceConfigurationIdentityProtectionPolicyWindows10' is deprecated. It will be removed in a future release. Please use 'IntuneAccountProtectionPolicyWindows10' instead." + Write-Warning -Message "For more information, please visit https://learn.microsoft.com/en-us/mem/intune/fundamentals/whats-new#consolidation-of-intune-profiles-for-identity-protection-and-account-protection-" + #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies From 716fc9fcd3a47f124547aeec6ee9c07d7e460446 Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Tue, 8 Oct 2024 14:35:20 +0200 Subject: [PATCH 113/252] Add Intune Account Protection Policy for Windows10 --- CHANGELOG.md | 6 + ...ntuneAccountProtectionPolicyWindows10.psm1 | 764 ++++++++++++++++++ ...ccountProtectionPolicyWindows10.schema.mof | 63 ++ .../readme.md | 6 + .../settings.json | 32 + .../Modules/M365DSCDRGUtil.psm1 | 122 ++- .../M365DSCResourceGenerator.psm1 | 91 ++- ...AccountProtectionPolicyWindows10.Tests.ps1 | 390 +++++++++ 8 files changed, 1445 insertions(+), 29 deletions(-) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicyWindows10/MSFT_IntuneAccountProtectionPolicyWindows10.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicyWindows10/MSFT_IntuneAccountProtectionPolicyWindows10.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicyWindows10/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicyWindows10/settings.json create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAccountProtectionPolicyWindows10.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index a42713a14c..0e0790e272 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ * Initial release. * EXOMigrationEndpoint * Initial Release +* IntuneAccountProtectionPolicyWindows10 + * Initial Release + FIXES [#5073](https://github.com/microsoft/Microsoft365DSC/issues/5073) * IntuneAppAndBrowserIsolationPolicyWindows10 * Initial release. FIXES [#3028](https://github.com/microsoft/Microsoft365DSC/issues/3028) @@ -24,6 +27,9 @@ Settings Catalog. FIXES [#5086](https://github.com/microsoft/Microsoft365DSC/issues/5086) * Add Set support for secret Settings Catalog values * Removed unused functions + * Add support for device / user scoped settings. +* ResourceGenerator + * Add support for device / user scoped settings. * DEPENDENCIES * Updated DSCParser to version 2.0.0.11 * Updated ReverseDSC to version 2.0.0.21 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicyWindows10/MSFT_IntuneAccountProtectionPolicyWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicyWindows10/MSFT_IntuneAccountProtectionPolicyWindows10.psm1 new file mode 100644 index 0000000000..5188f9fe59 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicyWindows10/MSFT_IntuneAccountProtectionPolicyWindows10.psm1 @@ -0,0 +1,764 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $DeviceSettings, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $UserSettings, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + #endregion + + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + try + { + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + + $getValue = $null + #region resource generator code + $getValue = Get-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $Id -ErrorAction SilentlyContinue + + if ($null -eq $getValue) + { + Write-Verbose -Message "Could not find an Intune Account Protection Policy for Windows10 with Id {$Id}" + + if (-not [System.String]::IsNullOrEmpty($DisplayName)) + { + $getValue = Get-MgBetaDeviceManagementConfigurationPolicy ` + -Filter "Name eq '$DisplayName'" ` + -ErrorAction SilentlyContinue + } + } + #endregion + if ($null -eq $getValue) + { + Write-Verbose -Message "Could not find an Intune Account Protection Policy for Windows10 with Name {$DisplayName}." + return $nullResult + } + $Id = $getValue.Id + Write-Verbose -Message "An Intune Account Protection Policy for Windows10 with Id {$Id} and Name {$DisplayName} was found" + + # Retrieve policy specific settings + [array]$settings = Get-MgBetaDeviceManagementConfigurationPolicySetting ` + -DeviceManagementConfigurationPolicyId $Id ` + -ExpandProperty 'settingDefinitions' ` + -ErrorAction Stop + + $policySettings = @{} + $policySettings = Export-IntuneSettingCatalogPolicySettings -Settings $settings -ReturnHashtable $policySettings -ContainsDeviceAndUserSettings + + #region resource generator code + $complexDeviceSettings = @{} + if ($null -ne $policySettings.deviceSettings.lsaCfgFlags) + { + $complexDeviceSettings.Add('LsaCfgFlags', $policySettings.deviceSettings.lsaCfgFlags) + } + if ($null -ne $policySettings.deviceSettings.facialFeaturesUseEnhancedAntiSpoofing) + { + $complexDeviceSettings.Add('FacialFeaturesUseEnhancedAntiSpoofing', $policySettings.deviceSettings.facialFeaturesUseEnhancedAntiSpoofing) + } + if ($null -ne $policySettings.deviceSettings.enablePinRecovery) + { + $complexDeviceSettings.Add('EnablePinRecovery', $policySettings.deviceSettings.enablePinRecovery) + } + if ($null -ne $policySettings.deviceSettings.expiration) + { + $complexDeviceSettings.Add('Expiration', $policySettings.deviceSettings.expiration) + } + if ($null -ne $policySettings.deviceSettings.history) + { + $complexDeviceSettings.Add('History', $policySettings.deviceSettings.history) + } + if ($null -ne $policySettings.deviceSettings.lowercaseLetters) + { + $complexDeviceSettings.Add('LowercaseLetters', $policySettings.deviceSettings.lowercaseLetters) + } + if ($null -ne $policySettings.deviceSettings.maximumPINLength) + { + $complexDeviceSettings.Add('MaximumPINLength', $policySettings.deviceSettings.maximumPINLength) + } + if ($null -ne $policySettings.deviceSettings.minimumPINLength) + { + $complexDeviceSettings.Add('MinimumPINLength', $policySettings.deviceSettings.minimumPINLength) + } + if ($null -ne $policySettings.deviceSettings.specialCharacters) + { + $complexDeviceSettings.Add('SpecialCharacters', $policySettings.deviceSettings.specialCharacters) + } + if ($null -ne $policySettings.deviceSettings.uppercaseLetters) + { + $complexDeviceSettings.Add('UppercaseLetters', $policySettings.deviceSettings.uppercaseLetters) + } + if ($null -ne $policySettings.deviceSettings.requireSecurityDevice) + { + $complexDeviceSettings.Add('RequireSecurityDevice', $policySettings.deviceSettings.requireSecurityDevice) + } + if ($null -ne $policySettings.deviceSettings.useCertificateForOnPremAuth) + { + $complexDeviceSettings.Add('UseCertificateForOnPremAuth', $policySettings.deviceSettings.useCertificateForOnPremAuth) + } + if ($null -ne $policySettings.deviceSettings.usePassportForWork) + { + $complexDeviceSettings.Add('UsePassportForWork', $policySettings.deviceSettings.usePassportForWork) + } + if ($complexDeviceSettings.Values.Where({ $_ -ne $null }).Count -eq 0) + { + $complexDeviceSettings = $null + } + + $complexUserSettings = @{} + if ($null -ne $policySettings.userSettings.enablePinRecovery) + { + $complexUserSettings.Add('EnablePinRecovery', $policySettings.userSettings.enablePinRecovery) + } + if ($null -ne $policySettings.userSettings.expiration) + { + $complexUserSettings.Add('Expiration', $policySettings.userSettings.expiration) + } + if ($null -ne $policySettings.userSettings.history) + { + $complexUserSettings.Add('History', $policySettings.userSettings.history) + } + if ($null -ne $policySettings.userSettings.lowercaseLetters) + { + $complexUserSettings.Add('LowercaseLetters', $policySettings.userSettings.lowercaseLetters) + } + if ($null -ne $policySettings.userSettings.maximumPINLength) + { + $complexUserSettings.Add('MaximumPINLength', $policySettings.userSettings.maximumPINLength) + } + if ($null -ne $policySettings.userSettings.minimumPINLength) + { + $complexUserSettings.Add('MinimumPINLength', $policySettings.userSettings.minimumPINLength) + } + if ($null -ne $policySettings.userSettings.specialCharacters) + { + $complexUserSettings.Add('SpecialCharacters', $policySettings.userSettings.specialCharacters) + } + if ($null -ne $policySettings.userSettings.uppercaseLetters) + { + $complexUserSettings.Add('UppercaseLetters', $policySettings.userSettings.uppercaseLetters) + } + if ($null -ne $policySettings.userSettings.requireSecurityDevice) + { + $complexUserSettings.Add('RequireSecurityDevice', $policySettings.userSettings.requireSecurityDevice) + } + if ($null -ne $policySettings.userSettings.usePassportForWork) + { + $complexUserSettings.Add('UsePassportForWork', $policySettings.userSettings.usePassportForWork) + } + if ($complexUserSettings.Values.Where({ $_ -ne $null }).Count -eq 0) + { + $complexUserSettings = $null + } + + $policySettings.Remove('deviceSettings') | Out-Null + $policySettings.Remove('userSettings') | Out-Null + #endregion + + $results = @{ + #region resource generator code + Description = $getValue.Description + DisplayName = $getValue.Name + RoleScopeTagIds = $getValue.RoleScopeTagIds + Id = $getValue.Id + DeviceSettings = $complexDeviceSettings + UserSettings = $complexUserSettings + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + #endregion + } + $results += $policySettings + + $assignmentsValues = Get-MgBetaDeviceManagementConfigurationPolicyAssignment -DeviceManagementConfigurationPolicyId $Id + $assignmentResult = @() + if ($assignmentsValues.Count -gt 0) + { + $assignmentResult += ConvertFrom-IntunePolicyAssignment -Assignments $assignmentsValues -IncludeDeviceFilter $true + } + $results.Add('Assignments', $assignmentResult) + + return [System.Collections.Hashtable] $results + } + catch + { + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $DeviceSettings, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $UserSettings, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + #endregion + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + + $BoundParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + $templateReferenceId = 'fcef01f2-439d-4c3f-9184-823fd6e97646_1' + $platforms = 'windows10' + $technologies = 'mdm' + + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + Write-Verbose -Message "Creating an Intune Account Protection Policy for Windows10 with Name {$DisplayName}" + $BoundParameters.Remove("Assignments") | Out-Null + + $settings = Get-IntuneSettingCatalogPolicySetting ` + -DSCParams ([System.Collections.Hashtable]$BoundParameters) ` + -TemplateId $templateReferenceId ` + -ContainsDeviceAndUserSettings + + $createParameters = @{ + Name = $DisplayName + Description = $Description + TemplateReference = @{ templateId = $templateReferenceId } + Platforms = $platforms + Technologies = $technologies + Settings = $settings + } + + #region resource generator code + $policy = New-MgBetaDeviceManagementConfigurationPolicy -BodyParameter $createParameters + + if ($policy.Id) + { + $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + Update-DeviceConfigurationPolicyAssignment ` + -DeviceConfigurationPolicyId $policy.Id ` + -Targets $assignmentsHash ` + -Repository 'deviceManagement/configurationPolicies' + } + #endregion + } + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Updating the Intune Account Protection Policy for Windows10 with Id {$($currentInstance.Id)}" + $BoundParameters.Remove("Assignments") | Out-Null + + $settings = Get-IntuneSettingCatalogPolicySetting ` + -DSCParams ([System.Collections.Hashtable]$BoundParameters) ` + -TemplateId $templateReferenceId ` + -ContainsDeviceAndUserSettings + + Update-IntuneDeviceConfigurationPolicy ` + -DeviceConfigurationPolicyId $currentInstance.Id ` + -Name $DisplayName ` + -Description $Description ` + -TemplateReferenceId $templateReferenceId ` + -Platforms $platforms ` + -Technologies $technologies ` + -Settings $settings + + #region resource generator code + $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + Update-DeviceConfigurationPolicyAssignment ` + -DeviceConfigurationPolicyId $currentInstance.Id ` + -Targets $assignmentsHash ` + -Repository 'deviceManagement/configurationPolicies' + #endregion + } + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Removing the Intune Account Protection Policy for Windows10 with Id {$($currentInstance.Id)}" + #region resource generator code + Remove-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $currentInstance.Id + #endregion + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $DeviceSettings, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $UserSettings, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + #endregion + + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + Write-Verbose -Message "Testing configuration of the Intune Account Protection Policy for Windows10 with Id {$Id} and Name {$DisplayName}" + + $CurrentValues = Get-TargetResource @PSBoundParameters + [Hashtable]$ValuesToCheck = @{} + $MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object { + if ($_.Key -notlike '*Variable' -or $_.Key -notin @('Verbose', 'Debug', 'ErrorAction', 'WarningAction', 'InformationAction')) + { + if ($null -ne $CurrentValues[$_.Key] -or $null -ne $PSBoundParameters[$_.Key]) + { + $ValuesToCheck.Add($_.Key, $null) + if (-not $PSBoundParameters.ContainsKey($_.Key)) + { + $PSBoundParameters.Add($_.Key, $null) + } + } + } + } + + if ($CurrentValues.Ensure -ne $Ensure) + { + Write-Verbose -Message "Test-TargetResource returned $false" + return $false + } + $testResult = $true + + #Compare Cim instances + foreach ($key in $PSBoundParameters.Keys) + { + $source = $PSBoundParameters.$key + $target = $CurrentValues.$key + if ($null -ne $source -and $source.GetType().Name -like '*CimInstance*') + { + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + if (-not $testResult) + { + break + } + + $ValuesToCheck.Remove($key) | Out-Null + } + } + + $ValuesToCheck.Remove('Id') | Out-Null + $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + + if ($testResult) + { + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + } + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + #region resource generator code + $policyTemplateID = "fcef01f2-439d-4c3f-9184-823fd6e97646_1" + [array]$getValue = Get-MgBetaDeviceManagementConfigurationPolicy ` + -Filter $Filter ` + -All ` + -ErrorAction Stop | Where-Object ` + -FilterScript { + $_.TemplateReference.TemplateId -eq $policyTemplateID + } + #endregion + + $i = 1 + $dscContent = '' + if ($getValue.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $getValue) + { + $displayedKey = $config.Id + if (-not [String]::IsNullOrEmpty($config.displayName)) + { + $displayedKey = $config.displayName + } + elseif (-not [string]::IsNullOrEmpty($config.name)) + { + $displayedKey = $config.name + } + Write-Host " |---[$i/$($getValue.Count)] $displayedKey" -NoNewline + $params = @{ + Id = $config.Id + DisplayName = $config.Name + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + if ($null -ne $Results.DeviceSettings) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.DeviceSettings ` + -CIMInstanceName 'MicrosoftGraphIntuneSettingsCatalogDeviceSettings' + if (-not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.DeviceSettings = $complexTypeStringResult + } + else + { + $Results.Remove('DeviceSettings') | Out-Null + } + } + if ($null -ne $Results.UserSettings) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.UserSettings ` + -CIMInstanceName 'MicrosoftGraphIntuneSettingsCatalogUserSettings' + if (-not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.UserSettings = $complexTypeStringResult + } + else + { + $Results.Remove('UserSettings') | Out-Null + } + } + + if ($Results.Assignments) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString -ComplexObject $Results.Assignments -CIMInstanceName DeviceManagementConfigurationPolicyAssignments + if ($complexTypeStringResult) + { + $Results.Assignments = $complexTypeStringResult + } + else + { + $Results.Remove('Assignments') | Out-Null + } + } + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + if ($Results.DeviceSettings) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "DeviceSettings" -IsCIMArray:$True + } + if ($Results.UserSettings) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "UserSettings" -IsCIMArray:$True + } + + if ($Results.Assignments) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "Assignments" -IsCIMArray:$true + } + + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicyWindows10/MSFT_IntuneAccountProtectionPolicyWindows10.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicyWindows10/MSFT_IntuneAccountProtectionPolicyWindows10.schema.mof new file mode 100644 index 0000000000..269777f6a7 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicyWindows10/MSFT_IntuneAccountProtectionPolicyWindows10.schema.mof @@ -0,0 +1,63 @@ +[ClassVersion("1.0.0.0")] +class MSFT_DeviceManagementConfigurationPolicyAssignments +{ + [Write, Description("The type of the target assignment."), ValueMap{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget","#microsoft.graph.configurationManagerCollectionAssignmentTarget"}, Values{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget","#microsoft.graph.configurationManagerCollectionAssignmentTarget"}] String dataType; + [Write, Description("The type of filter of the target assignment i.e. Exclude or Include. Possible values are:none, include, exclude."), ValueMap{"none","include","exclude"}, Values{"none","include","exclude"}] String deviceAndAppManagementAssignmentFilterType; + [Write, Description("The Id of the filter for the target assignment.")] String deviceAndAppManagementAssignmentFilterId; + [Write, Description("The group Id that is the target of the assignment.")] String groupId; + [Write, Description("The group Display Name that is the target of the assignment.")] String groupDisplayName; + [Write, Description("The collection Id that is the target of the assignment.(ConfigMgr)")] String collectionId; +}; + +[ClassVersion("1.0.0.0")] +class MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings +{ + [Write, Description("Credential Guard (0: (Disabled) Turns off Credential Guard remotely if configured previously without UEFI Lock., 1: (Enabled with UEFI lock) Turns on Credential Guard with UEFI lock., 2: (Enabled without lock) Turns on Credential Guard without UEFI lock.)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String LsaCfgFlags; + [Write, Description("Facial Features Use Enhanced Anti Spoofing (false: Disabled, true: Enabled)"), ValueMap{"false", "true"}, Values{"false", "true"}] String FacialFeaturesUseEnhancedAntiSpoofing; + [Write, Description("Enable Pin Recovery (false: Disabled, true: Enabled)"), ValueMap{"false", "true"}, Values{"false", "true"}] String EnablePinRecovery; + [Write, Description("Expiration")] SInt32 Expiration; + [Write, Description("PIN History")] SInt32 History; + [Write, Description("Lowercase Letters (0: Allows the use of lowercase letters in PIN., 1: Requires the use of at least one lowercase letters in PIN., 2: Does not allow the use of lowercase letters in PIN.)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String LowercaseLetters; + [Write, Description("Maximum PIN Length")] SInt32 MaximumPINLength; + [Write, Description("Minimum PIN Length")] SInt32 MinimumPINLength; + [Write, Description("Special Characters (0: Allows the use of special characters in PIN., 1: Requires the use of at least one special characters in PIN., 2: Does not allow the use of special characters in PIN.)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String SpecialCharacters; + [Write, Description("Uppercase Letters (0: Allows the use of uppercase letters in PIN., 1: Requires the use of at least one uppercase letters in PIN., 2: Does not allow the use of uppercase letters in PIN.)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String UppercaseLetters; + [Write, Description("Require Security Device (false: Disabled, true: Enabled)"), ValueMap{"false", "true"}, Values{"false", "true"}] String RequireSecurityDevice; + [Write, Description("Use Certificate For On Prem Auth (false: Disabled, true: Enabled)"), ValueMap{"false", "true"}, Values{"false", "true"}] String UseCertificateForOnPremAuth; + [Write, Description("Use Windows Hello For Business (Device) (false: Disabled, true: Enabled)"), ValueMap{"false", "true"}, Values{"false", "true"}] String UsePassportForWork; +}; + +[ClassVersion("1.0.0.0")] +class MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings +{ + [Write, Description("Enable Pin Recovery (User) (false: Disabled, true: Enabled)"), ValueMap{"false", "true"}, Values{"false", "true"}] String EnablePinRecovery; + [Write, Description("Expiration (User)")] SInt32 Expiration; + [Write, Description("PIN History (User)")] SInt32 History; + [Write, Description("Lowercase Letters (User) (0: Allows the use of lowercase letters in PIN., 1: Requires the use of at least one lowercase letters in PIN., 2: Does not allow the use of lowercase letters in PIN.)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String LowercaseLetters; + [Write, Description("Maximum PIN Length (User)")] SInt32 MaximumPINLength; + [Write, Description("Minimum PIN Length (User)")] SInt32 MinimumPINLength; + [Write, Description("Special Characters (User) (0: Allows the use of special characters in PIN., 1: Requires the use of at least one special characters in PIN., 2: Does not allow the use of special characters in PIN.)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String SpecialCharacters; + [Write, Description("Uppercase Letters (User) (0: Allows the use of uppercase letters in PIN., 1: Requires the use of at least one uppercase letters in PIN., 2: Does not allow the use of uppercase letters in PIN.)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String UppercaseLetters; + [Write, Description("Require Security Device (User) (false: Disabled, true: Enabled)"), ValueMap{"false", "true"}, Values{"false", "true"}] String RequireSecurityDevice; + [Write, Description("Use Windows Hello For Business (User) (false: Disabled, true: Enabled)"), ValueMap{"false", "true"}, Values{"false", "true"}] String UsePassportForWork; +}; + +[ClassVersion("1.0.0.0"), FriendlyName("IntuneAccountProtectionPolicyWindows10")] +class MSFT_IntuneAccountProtectionPolicyWindows10 : OMI_BaseResource +{ + [Write, Description("Policy description")] String Description; + [Key, Description("Policy name")] String DisplayName; + [Write, Description("List of Scope Tags for this Entity instance.")] String RoleScopeTagIds[]; + [Write, Description("The unique identifier for an entity. Read-only.")] String Id; + [Write, Description("The policy settings for the device scope."), EmbeddedInstance("MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings")] String DeviceSettings; + [Write, Description("The policy settings for the user scope"), EmbeddedInstance("MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings")] String UserSettings; + [Write, Description("Represents the assignment to the Intune policy."), EmbeddedInstance("MSFT_DeviceManagementConfigurationPolicyAssignments")] String Assignments[]; + [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; + [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Secret of the Azure Active Directory tenant used for authentication."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicyWindows10/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicyWindows10/readme.md new file mode 100644 index 0000000000..893c5522f1 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicyWindows10/readme.md @@ -0,0 +1,6 @@ + +# IntuneAccountProtectionPolicyWindows10 + +## Description + +Intune Account Protection Policy for Windows10 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicyWindows10/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicyWindows10/settings.json new file mode 100644 index 0000000000..a20915a6b7 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicyWindows10/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName":"IntuneAccountProtectionPolicyWindows10", + "description":"This resource configures an Intune Account Protection Policy for Windows10.", + "permissions":{ + "graph":{ + "delegated":{ + "read":[ + { + "name":"DeviceManagementConfiguration.Read.All" + } + ], + "update":[ + { + "name":"DeviceManagementConfiguration.ReadWrite.All" + } + ] + }, + "application":{ + "read":[ + { + "name":"DeviceManagementConfiguration.Read.All" + } + ], + "update":[ + { + "name":"DeviceManagementConfiguration.ReadWrite.All" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 index 8d1e1f69d7..39f5223814 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 @@ -794,10 +794,20 @@ function Convert-M365DSCDRGComplexTypeToHashtable [OutputType([hashtable], [hashtable[]])] param( [Parameter(Mandatory = $true)] - $ComplexObject + [AllowNull()] + $ComplexObject, + + [Parameter()] + [switch] + $SingleLevel ) - if ($ComplexObject.getType().Fullname -like '*[[\]]') + if ($null -eq $ComplexObject) + { + return @{} + } + + if ($ComplexObject.GetType().Fullname -like '*[[\]]') { $results = @() foreach ($item in $ComplexObject) @@ -816,11 +826,16 @@ function Convert-M365DSCDRGComplexTypeToHashtable if ($null -ne $hashComplexObject) { - $results = $hashComplexObject.clone() + $results = $hashComplexObject.Clone() + if ($SingleLevel) + { + return [hashtable]$results + } + $keys = $hashComplexObject.Keys | Where-Object -FilterScript { $_ -ne 'PSComputerName' } foreach ($key in $keys) { - if ($hashComplexObject[$key] -and $hashComplexObject[$key].getType().Fullname -like '*CimInstance*') + if ($hashComplexObject[$key] -and $hashComplexObject[$key].GetType().Fullname -like '*CimInstance*') { $results[$key] = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $hashComplexObject[$key] } @@ -828,11 +843,12 @@ function Convert-M365DSCDRGComplexTypeToHashtable { $propertyName = $key[0].ToString().ToLower() + $key.Substring(1, $key.Length - 1) $propertyValue = $results[$key] - $results.remove($key) | Out-Null + $results.Remove($key) | Out-Null $results.Add($propertyName, $propertyValue) } } } + return [hashtable]$results } @@ -1262,9 +1278,24 @@ function Get-IntuneSettingCatalogPolicySetting [Parameter(Mandatory = 'true')] [System.Collections.Hashtable] $DSCParams, - [Parameter(Mandatory = 'true')] + + [Parameter( + Mandatory = 'true', + ParameterSetName = 'Start' + )] [System.String] - $TemplateId + $TemplateId, + + [Parameter( + Mandatory = 'true', + ParameterSetName = 'DeviceAndUserSettings' + )] + [System.Array] + $SettingTemplates, + + [Parameter(ParameterSetName = 'Start')] + [switch] + $ContainsDeviceAndUserSettings ) $global:excludedDefinitionIds = @() @@ -1273,18 +1304,38 @@ function Get-IntuneSettingCatalogPolicySetting $DSCParams.Remove('DisplayName') | Out-Null $DSCParams.Remove('Description') | Out-Null - # Prepare setting definitions mapping - $settingTemplates = Get-MgBetaDeviceManagementConfigurationPolicyTemplateSettingTemplate ` - -DeviceManagementConfigurationPolicyTemplateId $TemplateId ` - -ExpandProperty 'SettingDefinitions' ` - -All $settingInstances = @() + if ($PSCmdlet.ParameterSetName -eq 'Start') + { + # Prepare setting definitions mapping + $SettingTemplates = Get-MgBetaDeviceManagementConfigurationPolicyTemplateSettingTemplate ` + -DeviceManagementConfigurationPolicyTemplateId $TemplateId ` + -ExpandProperty 'SettingDefinitions' ` + -All + + if ($ContainsDeviceAndUserSettings) + { + $deviceSettingTemplates = $SettingTemplates | Where-object -FilterScript { + $_.SettingInstanceTemplate.SettingDefinitionId.StartsWith("device_") + } + $userSettingTemplates = $SettingTemplates | Where-object -FilterScript { + $_.SettingInstanceTemplate.SettingDefinitionId.StartsWith("user_") + } + $deviceDscParams = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $DSCParams.DeviceSettings -SingleLevel + $userDscParams = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $DSCParams.UserSettings -SingleLevel + $combinedSettingInstances = @() + $combinedSettingInstances += Get-IntuneSettingCatalogPolicySetting -DSCParams $deviceDscParams -SettingTemplates $deviceSettingTemplates + $combinedSettingInstances += Get-IntuneSettingCatalogPolicySetting -DSCParams $userDscParams -SettingTemplates $userSettingTemplates + + return ,$combinedSettingInstances + } + } # Iterate over all setting instance templates in the setting template - foreach ($settingInstanceTemplate in $settingTemplates.SettingInstanceTemplate) + foreach ($settingInstanceTemplate in $SettingTemplates.SettingInstanceTemplate) { $settingInstance = @{} - $settingDefinition = $settingTemplates.SettingDefinitions | Where-Object { + $settingDefinition = $SettingTemplates.SettingDefinitions | Where-Object { $_.Id -eq $settingInstanceTemplate.SettingDefinitionId -and ` ($_.AdditionalProperties.dependentOn.Count -eq 0 -and $_.AdditionalProperties.options.dependentOn.Count -eq 0) } @@ -2088,14 +2139,51 @@ function Export-IntuneSettingCatalogPolicySettings [Parameter( ParameterSetName = 'Setting' )] - [switch]$IsRoot + [switch]$IsRoot, + + [Parameter( + ParameterSetName = 'Start' + )] + [switch]$ContainsDeviceAndUserSettings ) if ($PSCmdlet.ParameterSetName -eq 'Start') { - foreach ($setting in $Settings) + if ($ContainsDeviceAndUserSettings) + { + $deviceSettingsReturnHashtable = @{} + $deviceSettings = $Settings | Where-Object -FilterScript { + $_.SettingInstance.settingDefinitionId.StartsWith("device_") + } + foreach ($setting in $deviceSettings) + { + Export-IntuneSettingCatalogPolicySettings -SettingInstance $setting.SettingInstance -SettingDefinitions $setting.SettingDefinitions -ReturnHashtable $deviceSettingsReturnHashtable -AllSettingDefinitions $deviceSettings.SettingDefinitions -IsRoot + } + + $userSettings = $Settings | Where-Object -FilterScript { + $_.SettingInstance.settingDefinitionId.StartsWith("user_") + } + $userSettingsReturnHashtable = @{} + foreach ($setting in $userSettings) + { + Export-IntuneSettingCatalogPolicySettings -SettingInstance $setting.SettingInstance -SettingDefinitions $setting.SettingDefinitions -ReturnHashtable $userSettingsReturnHashtable -AllSettingDefinitions $userSettings.SettingDefinitions -IsRoot + } + + if ($deviceSettingsReturnHashtable.Keys.Count -gt 0) + { + $ReturnHashtable.Add('DeviceSettings', $deviceSettingsReturnHashtable) + } + if ($userSettingsReturnHashtable.Keys.Count -gt 0) + { + $ReturnHashtable.Add('UserSettings', $userSettingsReturnHashtable) + } + } + else { - Export-IntuneSettingCatalogPolicySettings -SettingInstance $setting.SettingInstance -SettingDefinitions $setting.SettingDefinitions -ReturnHashtable $ReturnHashtable -AllSettingDefinitions $Settings.SettingDefinitions -IsRoot + foreach ($setting in $Settings) + { + Export-IntuneSettingCatalogPolicySettings -SettingInstance $setting.SettingInstance -SettingDefinitions $setting.SettingDefinitions -ReturnHashtable $ReturnHashtable -AllSettingDefinitions $Settings.SettingDefinitions -IsRoot + } } return $ReturnHashtable } diff --git a/ResourceGenerator/M365DSCResourceGenerator.psm1 b/ResourceGenerator/M365DSCResourceGenerator.psm1 index ecdccf6a86..fbe1658771 100644 --- a/ResourceGenerator/M365DSCResourceGenerator.psm1 +++ b/ResourceGenerator/M365DSCResourceGenerator.psm1 @@ -245,20 +245,87 @@ function New-M365DSCResource } $templateSettings = @() - $allSettingDefinitions = $SettingsCatalogSettingTemplates.SettingDefinitions - foreach ($settingTemplate in $SettingsCatalogSettingTemplates) + $deviceSettingsCatalogTemplates = $SettingsCatalogSettingTemplates | Where-Object -FilterScript { $_.SettingInstanceTemplate.SettingDefinitionId.StartsWith("device_") } + $deviceSettingDefinitions = $deviceSettingsCatalogTemplates.SettingDefinitions + + $userSettingsCatalogTemplates = $SettingsCatalogSettingTemplates | Where-Object -FilterScript { $_.SettingInstanceTemplate.SettingDefinitionId.StartsWith("user_") } + $userSettingDefinitions = $userSettingsCatalogTemplates.SettingDefinitions + + $containsDeviceAndUserSettings = $false + if ($deviceSettingDefinitions.Count -gt 0 -and $userSettingDefinitions.Count -gt 0) + { + $containsDeviceAndUserSettings = $true + } + + $deviceTemplateSettings = @() + foreach ($deviceSettingTemplate in $deviceSettingsCatalogTemplates) { - $templateSettings += New-SettingsCatalogSettingDefinitionSettingsFromTemplate ` + $deviceTemplateSettings += New-SettingsCatalogSettingDefinitionSettingsFromTemplate ` -FromRoot ` - -SettingTemplate $settingTemplate ` - -AllSettingDefinitions $allSettingDefinitions + -SettingTemplate $deviceSettingTemplate ` + -AllSettingDefinitions $deviceSettingDefinitions + } + + $userTemplateSettings = @() + foreach ($userSettingTemplate in $userSettingsCatalogTemplates) + { + $userTemplateSettings += New-SettingsCatalogSettingDefinitionSettingsFromTemplate ` + -FromRoot ` + -SettingTemplate $userSettingTemplate ` + -AllSettingDefinitions $userSettingDefinitions + } + + $deviceDefinitionSettings = @() + foreach ($deviceTemplateSetting in $deviceTemplateSettings) + { + $deviceDefinitionSettings += New-ParameterDefinitionFromSettingsCatalogTemplateSetting ` + -TemplateSetting $deviceTemplateSetting + } + + $userDefinitionSettings = @() + foreach ($userTemplateSetting in $userTemplateSettings) + { + $userDefinitionSettings += New-ParameterDefinitionFromSettingsCatalogTemplateSetting ` + -TemplateSetting $userTemplateSetting } - $definitionSettings = @() - foreach ($templateSetting in $templateSettings) + if ($containsDeviceAndUserSettings) + { + $definitionSettings = @{ + PowerShell = @( + +@" + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + `$DeviceSettings +"@, +@" + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + `$UserSettings +"@ + ) + MOFInstance = @( +@" +[ClassVersion("1.0.0.0")] +class MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings +{ +$($deviceDefinitionSettings.MOF -join "`r`n") +}; +"@, +@" +[ClassVersion("1.0.0.0")] +class MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings +{ +$($userDefinitionSettings.MOF -join "`r`n") +}; +"@ + ) + } + } + else { - $definitionSettings += New-ParameterDefinitionFromSettingsCatalogTemplateSetting ` - -TemplateSetting $templateSetting + $definitionSettings = $deviceDefinitionSettings + $userDefinitionSettings } $parameterString += $definitionSettings.PowerShell -join ",`r`n`r`n" @@ -475,7 +542,7 @@ function New-M365DSCResource -ErrorAction Stop `$policySettings = @{} - `$policySettings = Export-IntuneSettingCatalogPolicySettings -Settings `$settings -ReturnHashtable `$policySettings `r`n + `$policySettings = Export-IntuneSettingCatalogPolicySettings -Settings `$settings -ReturnHashtable `$policySettings$(if ($containsDeviceAndUserSettings) { ' -ContainsDeviceAndUserSettings' })`r`n "@ $settingsCatalogAddSettings = " `$results += `$policySettings`r`n`r`n" } @@ -595,7 +662,7 @@ function New-M365DSCResource $defaultCreateParameters = @" `$settings = Get-IntuneSettingCatalogPolicySetting `` -DSCParams ([System.Collections.Hashtable]`$BoundParameters) `` - -TemplateId `$templateReferenceId + -TemplateId `$templateReferenceId$(if ($containsDeviceAndUserSettings) { " ```r`n -ContainsDeviceAndUserSettings" })`r`n `$createParameters = @{ Name = `$DisplayName @@ -718,7 +785,7 @@ function New-M365DSCResource $defaultUpdateParameters = @" `$settings = Get-IntuneSettingCatalogPolicySetting `` -DSCParams ([System.Collections.Hashtable]`$BoundParameters) `` - -TemplateId `$templateReferenceId + -TemplateId `$templateReferenceId$(if ($containsDeviceAndUserSettings) { " ```r`n -ContainsDeviceAndUserSettings" })`r`n Update-IntuneDeviceConfigurationPolicy `` -DeviceConfigurationPolicyId `$currentInstance.Id `` diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAccountProtectionPolicyWindows10.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAccountProtectionPolicyWindows10.Tests.ps1 new file mode 100644 index 0000000000..b83b974567 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAccountProtectionPolicyWindows10.Tests.ps1 @@ -0,0 +1,390 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource "IntuneAccountProtectionPolicyWindows10" -GenericStubModule $GenericStubPath +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName Get-PSSession -MockWith { + } + + Mock -CommandName Remove-PSSession -MockWith { + } + + Mock -CommandName Update-MgBetaDeviceManagementConfigurationPolicy -MockWith { + } + + Mock -CommandName New-MgBetaDeviceManagementConfigurationPolicy -MockWith { + return @{ + Id = '12345-12345-12345-12345-12345' + } + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicy -MockWith { + return @{ + Id = '12345-12345-12345-12345-12345' + Description = 'My Test' + Name = 'My Test' + RoleScopeTagIds = @("FakeStringValue") + TemplateReference = @{ + TemplateId = 'fcef01f2-439d-4c3f-9184-823fd6e97646_1' + } + } + } + + Mock -CommandName Remove-MgBetaDeviceManagementConfigurationPolicy -MockWith { + } + + Mock -CommandName Update-IntuneDeviceConfigurationPolicy -MockWith { + } + + Mock -CommandName Get-IntuneSettingCatalogPolicySetting -MockWith { + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicySetting -MockWith { + return @( + @{ + Id = '0' + SettingDefinitions = @( + @{ + Id = 'device_vendor_msft_passportforwork_{tenantid}_policies_pincomplexity_history' + Name = 'History' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingDefinition' + dependentOn = @( + @{ + dependentOn = 'device_vendor_msft_passportforwork_{tenantid}' + parentSettingId = 'device_vendor_msft_passportforwork_{tenantid}' + } + ) + } + }, + @{ + Id = 'device_vendor_msft_passportforwork_{tenantid}' + Name = '{TenantId}' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSettingGroupCollectionDefinition' + childIds = @( + 'device_vendor_msft_passportforwork_{tenantid}_policies_pincomplexity_history' + ) + maximumCount = 1 + minimumCount = 0 + } + } + ) + SettingInstance = @{ + SettingDefinitionId = 'device_vendor_msft_passportforwork_{tenantid}' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = '0ece2bdc-57c1-4be9-93e9-ac9c395a9c94' + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance' + groupSettingCollectionValue = @( + @{ + children = @( + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance' + settingDefinitionId = 'device_vendor_msft_passportforwork_{tenantid}_policies_pincomplexity_history' + simpleSettingValue = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationIntegerSettingValue' + value = '10' + } + } + ) + } + ) + } + } + }, + @{ + Id = '1' + SettingDefinitions = @( + @{ + Id = 'user_vendor_msft_passportforwork_{tenantid}_policies_pincomplexity_history' + Name = 'History' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingDefinition' + dependentOn = @( + @{ + dependentOn = 'user_vendor_msft_passportforwork_{tenantid}' + parentSettingId = 'user_vendor_msft_passportforwork_{tenantid}' + } + ) + } + }, + @{ + Id = 'user_vendor_msft_passportforwork_{tenantid}' + Name = '{TenantId}' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSettingGroupCollectionDefinition' + childIds = @( + 'user_vendor_msft_passportforwork_{tenantid}_policies_pincomplexity_history' + ) + maximumCount = 1 + minimumCount = 0 + } + } + ) + SettingInstance = @{ + SettingDefinitionId = 'user_vendor_msft_passportforwork_{tenantid}' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = '0ece2bdc-57c1-4be9-93e9-ac9c395a9c94' + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance' + groupSettingCollectionValue = @( + @{ + children = @( + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance' + settingDefinitionId = 'user_vendor_msft_passportforwork_{tenantid}_policies_pincomplexity_history' + simpleSettingValue = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationIntegerSettingValue' + value = '20' + } + } + ) + } + ) + } + } + } + ) + } + + Mock -CommandName Update-DeviceConfigurationPolicyAssignment -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicyAssignment -MockWith { + return @(@{ + Id = '12345-12345-12345-12345-12345' + Source = 'direct' + SourceId = '12345-12345-12345-12345-12345' + Target = @{ + DeviceAndAppManagementAssignmentFilterId = '12345-12345-12345-12345-12345' + DeviceAndAppManagementAssignmentFilterType = 'none' + AdditionalProperties = @( + @{ + '@odata.type' = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + } + ) + } + }) + } + + } + # Test contexts + Context -Name "The IntuneAccountProtectionPolicyWindows10 should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + deviceAndAppManagementAssignmentFilterType = 'none' + } -ClientOnly) + ) + Description = "My Test" + DeviceSettings = [CimInstance]( + New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings -Property @{ + History = 10 + } -ClientOnly + ) + Id = "12345-12345-12345-12345-12345" + DisplayName = "My Test" + RoleScopeTagIds = @("FakeStringValue") + UserSettings = [CimInstance]( + New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings -Property @{ + History = 20 + } -ClientOnly + ) + Ensure = "Present" + Credential = $Credential + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicy -MockWith { + return $null + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + It 'Should Create the group from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-MgBetaDeviceManagementConfigurationPolicy -Exactly 1 + } + } + + Context -Name "The IntuneAccountProtectionPolicyWindows10 exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + deviceAndAppManagementAssignmentFilterType = 'none' + } -ClientOnly) + ) + Description = "My Test" + DeviceSettings = [CimInstance]( + New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings -Property @{ + History = 10 + } -ClientOnly + ) + Id = "12345-12345-12345-12345-12345" + DisplayName = "My Test" + RoleScopeTagIds = @("FakeStringValue") + UserSettings = [CimInstance]( + New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings -Property @{ + History = 20 + } -ClientOnly + ) + Ensure = "Absent" + Credential = $Credential + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should Remove the group from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-MgBetaDeviceManagementConfigurationPolicy -Exactly 1 + } + } + Context -Name "The IntuneAccountProtectionPolicyWindows10 Exists and Values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + deviceAndAppManagementAssignmentFilterType = 'none' + } -ClientOnly) + ) + Description = "My Test" + DeviceSettings = [CimInstance]( + New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings -Property @{ + History = 10 + } -ClientOnly + ) + Id = "12345-12345-12345-12345-12345" + DisplayName = "My Test" + RoleScopeTagIds = @("FakeStringValue") + UserSettings = [CimInstance]( + New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings -Property @{ + History = 20 + } -ClientOnly + ) + Ensure = "Present" + Credential = $Credential + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The IntuneAccountProtectionPolicyWindows10 exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + deviceAndAppManagementAssignmentFilterType = 'none' + } -ClientOnly) + ) + Description = "My Test" + DeviceSettings = [CimInstance]( + New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings -Property @{ + History = 10 + } -ClientOnly + ) + Id = "12345-12345-12345-12345-12345" + DisplayName = "My Test" + RoleScopeTagIds = @("FakeStringValue") + UserSettings = [CimInstance]( + New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings -Property @{ + History = 30 # Drift + } -ClientOnly + ) + Ensure = "Present" + Credential = $Credential + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Update-IntuneDeviceConfigurationPolicy -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + } + + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope From f58b0bcf9835a93e0cadbfc61d04f143fa25e6d7 Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Tue, 8 Oct 2024 15:02:31 +0200 Subject: [PATCH 114/252] Add examples new account protection policy --- .../1-Create.ps1 | 44 +++++++++++++++++++ .../2-Update.ps1 | 44 +++++++++++++++++++ .../3-Remove.ps1 | 34 ++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneAccountProtectionPolicyWindows10/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneAccountProtectionPolicyWindows10/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneAccountProtectionPolicyWindows10/3-Remove.ps1 diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAccountProtectionPolicyWindows10/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAccountProtectionPolicyWindows10/1-Create.ps1 new file mode 100644 index 0000000000..13e7d999e7 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAccountProtectionPolicyWindows10/1-Create.ps1 @@ -0,0 +1,44 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneAccountProtectionPolicyWindows10 'myAccountProtectionPolicy' + { + DisplayName = 'test' + DeviceSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings + { + History = 10 + EnablePinRecovery = 'true' + } + UserSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings + { + History = 20 + EnablePinRecovery = 'true' + } + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAccountProtectionPolicyWindows10/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAccountProtectionPolicyWindows10/2-Update.ps1 new file mode 100644 index 0000000000..3752c70dd6 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAccountProtectionPolicyWindows10/2-Update.ps1 @@ -0,0 +1,44 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneAccountProtectionPolicyWindows10 'myAccountProtectionPolicy' + { + DisplayName = 'test' + DeviceSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings + { + History = 10 + EnablePinRecovery = 'true' + } + UserSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings + { + History = 30 # Updated property + EnablePinRecovery = 'true' + } + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAccountProtectionPolicyWindows10/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAccountProtectionPolicyWindows10/3-Remove.ps1 new file mode 100644 index 0000000000..93129a03ad --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAccountProtectionPolicyWindows10/3-Remove.ps1 @@ -0,0 +1,34 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneAccountProtectionPolicyWindows10 'myAccountProtectionPolicy' + { + DisplayName = 'test' + Ensure = 'Absent' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} From cd6ab092be6848203fdaabdd62a562438112aaf4 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 8 Oct 2024 14:27:36 +0000 Subject: [PATCH 115/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index d0ae19637e..7d261a4265 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -264,6 +264,166 @@ } ] }, + { + "ClassName": "MSFT_AADApplicationOnPremisesPublishingSegmentCORS", + "Parameters": [ + { + "CIMType": "String[]", + "Name": "allowedHeaders", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "maxAgeInSeconds", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "resource", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "allowedMethods", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "allowedOrigins", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_AADApplicationOnPremisesPublishingSegment", + "Parameters": [ + { + "CIMType": "String", + "Name": "alternateUrl", + "Option": "Write" + }, + { + "CIMType": "MSFT_AADApplicationOnPremisesPublishingSegmentCORS[]", + "Name": "corsConfigurations", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "externalUrl", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "internalUrl", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_AADApplicationOnPremisesPublishingSingleSignOnSettingKerberos", + "Parameters": [ + { + "CIMType": "String", + "Name": "kerberosServicePrincipalName", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "kerberosSignOnMappingAttributeType", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_AADApplicationOnPremisesPublishingSingleSignOnSetting", + "Parameters": [ + { + "CIMType": "String", + "Name": "singleSignOnMode", + "Option": "Write" + }, + { + "CIMType": "MSFT_AADApplicationOnPremisesPublishingSingleSignOnSettingKerberos", + "Name": "kerberosSignOnSettings", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_AADApplicationOnPremisesPublishing", + "Parameters": [ + { + "CIMType": "String", + "Name": "alternateUrl", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "applicationServerTimeout", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "externalAuthenticationType", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "externalUrl", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "internalUrl", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "isBackendCertificateValidationEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "isHttpOnlyCookieEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "isPersistentCookieEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "isSecureCookieEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "isStateSessionEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "isTranslateHostHeaderEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "isTranslateLinksInBodyEnabled", + "Option": "Write" + }, + { + "CIMType": "MSFT_AADApplicationOnPremisesPublishingSegment[]", + "Name": "onPremisesApplicationSegments", + "Option": "Write" + }, + { + "CIMType": "MSFT_AADApplicationOnPremisesPublishingSingleSignOnSetting", + "Name": "singleSignOnSettings", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_AADApplicationPermission", "Parameters": [ @@ -592,6 +752,11 @@ "Name": "Owners", "Option": "Write" }, + { + "CIMType": "MSFT_AADApplicationOnPremisesPublishing", + "Name": "OnPremisesPublishing", + "Option": "Write" + }, { "CIMType": "String", "Name": "Ensure", From 7fef33f8b65d91c93d8ac9dff82cb6f8f6c78e10 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 8 Oct 2024 16:01:00 +0000 Subject: [PATCH 116/252] Updated Resources and Cmdlet documentation pages --- .../AADConnectorGroupApplicationProxy.md | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 docs/docs/resources/azure-ad/AADConnectorGroupApplicationProxy.md diff --git a/docs/docs/resources/azure-ad/AADConnectorGroupApplicationProxy.md b/docs/docs/resources/azure-ad/AADConnectorGroupApplicationProxy.md new file mode 100644 index 0000000000..e5968a7f31 --- /dev/null +++ b/docs/docs/resources/azure-ad/AADConnectorGroupApplicationProxy.md @@ -0,0 +1,165 @@ +# AADConnectorGroupApplicationProxy + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Name** | Key | String | The name associated with the connectorGroup. | | +| **Region** | Write | String | The region the connectorGroup is assigned to and will optimize traffic for. This region can only be set if no connectors or applications are assigned to the connectorGroup. The possible values are: nam (for North America), eur (for Europe), aus (for Australia), asia (for Asia), ind (for India), and unknownFutureValue. | `nam`, `eur`, `aus`, `asia`, `ind`, `unknownFutureValue` | +| **Id** | Write | String | The unique identifier for an entity. Read-only. | | +| **Ensure** | Write | String | Present ensures the policy exists, absent ensures it is removed. | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials of the Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **ApplicationSecret** | Write | PSCredential | Secret of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Azure AD Connector Group Application Proxy + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - Directory.ReadWrite.All + +- **Update** + + - Directory.ReadWrite.All + +#### Application permissions + +- **Read** + + - Directory.ReadWrite.All + +- **Update** + + - Directory.ReadWrite.All + +## Examples + +### Example 1 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + AADConnectorGroupApplicationProxy "AADConnectorGroupApplicationProxy-testgroup" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Present"; + Id = "4984dcf7-d9e9-4663-90b4-5db09f92a669"; + Name = "testgroup"; + Region = "nam"; + } + } +} +``` + +### Example 2 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADConnectorGroupApplicationProxy "AADConnectorGroupApplicationProxy-testgroup" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Present"; + Id = "4984dcf7-d9e9-4663-90b4-5db09f92a669"; + Name = "testgroup-new"; + Region = "nam"; + } + } +} +``` + +### Example 3 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + AADConnectorGroupApplicationProxy "AADConnectorGroupApplicationProxy-testgroup" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Absent"; + Id = "4984dcf7-d9e9-4663-90b4-5db09f92a669"; + } + } +} +``` + From 4b500dab5407cfdc5017c46658baed2bdec6e0c1 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Tue, 8 Oct 2024 10:18:22 -0700 Subject: [PATCH 117/252] Fixed a typo in example to make the PR validation pass. --- .../Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 index e54b97d9c5..f5a8380f86 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 @@ -36,14 +36,14 @@ Configuration Example PrivacyInformationUrl = ""; Publisher = "Contoso"; PublishingState = "published"; - Assignments = @( + Assignments = @( MSFT_DeviceManagementMobileAppAssignment { - groupDisplayName = 'All devices' + groupDisplayName = 'All devices' source = 'direct' deviceAndAppManagementAssignmentFilterType = 'none' dataType = '#microsoft.graph.allDevicesAssignmentTarget' intent = 'required' - }, + } MSFT_DeviceManagementMobileAppAssignment { deviceAndAppManagementAssignmentFilterType = 'none' source = 'direct' From 88ad08eec67e12816386e546274f88f90cc210ab Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Tue, 8 Oct 2024 21:57:49 +0200 Subject: [PATCH 118/252] Fix Intune MacOS Lob App resource --- .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 694 +++++++----------- ...SFT_IntuneMobileAppsMacOSLobApp.schema.mof | 100 +-- .../IntuneMobileAppsMacOSLobApp/1-Create.ps1 | 15 +- .../IntuneMobileAppsMacOSLobApp/2-Update.ps1 | 12 +- .../IntuneMobileAppsMacOSLobApp/3-Remove.ps1 | 9 - .../Modules/M365DSCDRGUtil.psm1 | 139 +++- ...5DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 | 6 - 7 files changed, 460 insertions(+), 515 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 index 1561fcd9ca..c6699b0e1b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 @@ -34,6 +34,14 @@ function Get-TargetResource [System.Boolean] $IgnoreVersionDetection, + [Parameter()] + [System.Boolean] + $InstallAsManaged, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $MinimumSupportedOperatingSystem, + [Parameter()] [System.String] $Notes, @@ -50,11 +58,6 @@ function Get-TargetResource [System.String] $Publisher, - [Parameter()] - [System.String] - [ValidateSet('notPublished', 'processing','published')] - $PublishingState, - [Parameter()] [System.String[]] $RoleScopeTagIds, @@ -142,74 +145,101 @@ function Get-TargetResource $nullResult.Ensure = 'Absent' try { - $instance = Get-MgBetaDeviceAppManagementMobileApp ` - -Filter "(isof('microsoft.graph.macOSLobApp') and displayName eq '$DisplayName')" ` - -ExpandProperty "categories,assignments" ` - -ErrorAction SilentlyContinue | Where-Object ` - -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.macOSLobApp' } + $instance = Get-MgBetaDeviceAppManagementMobileApp -MobileAppId $Id ` + -ExpandProperty "categories" ` + -ErrorAction SilentlyContinue if ($null -eq $instance) { - Write-Verbose -Message "No Mobile app with DisplayName {$DisplayName} was found. Search with DisplayName." - $instance = Get-MgBetaDeviceAppManagementMobileApp ` - -MobileAppId $Id ` - -ExpandProperty "categories,assignments" ` - -ErrorAction Stop | Where-Object ` - -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.macOSLobApp' } + Write-Verbose -Message "Could not find an Intune MacOS Lob App with Id {$Id}." + + if (-not [System.String]::IsNullOrEmpty($DisplayName)) + { + $instance = Get-MgBetaDeviceAppManagementMobileApp ` + -Filter "(isof('microsoft.graph.macOSLobApp') and displayName eq '$DisplayName')" ` + -ErrorAction SilentlyContinue + } + + if ($null -ne $instance) + { + $instance = Get-MgBetaDeviceAppManagementMobileApp -MobileAppId $instance.Id ` + -ExpandProperty "categories" ` + -ErrorAction SilentlyContinue + } } if ($null -eq $instance) { - Write-Verbose -Message "No Mobile app with {$Id} was found." + Write-Verbose -Message "Could not find an Intune MacOS Lob App with DisplayName {$DisplayName} was found." return $nullResult } - $results = @{ - Id = $instance.Id - Description = $instance.Description - Developer = $instance.Developer - DisplayName = $instance.DisplayName - InformationUrl = $instance.InformationUrl - IsFeatured = $instance.IsFeatured - Notes = $instance.Notes - Owner = $instance.Owner - PrivacyInformationUrl = $instance.PrivacyInformationUrl - Publisher = $instance.Publisher - PublishingState = $instance.PublishingState.ToString() - RoleScopeTagIds = $instance.RoleScopeTagIds - BundleId = $instance.BundleId - BuildNumber = $instance.BuildNumber - VersionNumber = $instance.VersionNumber - IgnoreVersionDetection = $instance.AdditionalProperties.ignoreVersionDetection - - Ensure = 'Present' - Credential = $Credential - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - ApplicationSecret = $ApplicationSecret - ManagedIdentity = $ManagedIdentity.IsPresent - AccessTokens = $AccessTokens - } + Write-Verbose "An Intune MacOS Lob App with Id {$Id} and DisplayName {$DisplayName} was found." #region complex types - - #Categories - if($null -ne $instance.Categories) + $complexCategories = @() + foreach ($category in $instance.Categories) { - $results.Add('Categories', $instance.Categories) + $myCategory = @{} + $myCategory.Add('Id', $category.id) + $myCategory.Add('DisplayName', $category.displayName) + $complexCategories += $myCategory } - else { - $results.Add('Categories', "") + + $complexChildApps = @() + foreach ($childApp in $instance.AdditionalProperties.childApps) + { + $myChildApp = @{} + $myChildApp.Add('BundleId', $childApp.bundleId) + $myChildApp.Add('BuildNumber', $childApp.buildNumber) + $myChildApp.Add('VersionNumber', $childApp.versionNumber) + $complexChildApps += $myChildApp } - #childApps - if($null -ne $instance.AdditionalProperties.childApps) + $complexLargeIcon = @{} + if ($null -ne $instance.LargeIcon.Value) { - $results.Add('ChildApps', $instance.AdditionalProperties.childApps) + $complexLargeIcon.Add('Value', [System.Convert]::ToBase64String($instance.LargeIcon.Value)) + $complexLargeIcon.Add('Type', $instance.LargeIcon.Type) + } + + $complexMinimumSupportedOperatingSystem = @{} + $instance.AdditionalProperties.minimumSupportedOperatingSystem.GetEnumerator() | Foreach-Object { + if ($_.Value) # Values are either true or false. Only export the true value. + { + $complexMinimumSupportedOperatingSystem.Add($_.Key, $_.Value) + } } - else { - $results.Add('ChildApps', "") + + $results = @{ + Id = $instance.Id + BundleId = $instance.AdditionalProperties.bundleId + BuildNumber = $instance.AdditionalProperties.buildNumber + Categories = $complexCategories + ChildApps = $complexChildApps + Description = $instance.Description + Developer = $instance.Developer + DisplayName = $instance.DisplayName + IgnoreVersionDetection = $instance.AdditionalProperties.ignoreVersionDetection + InformationUrl = $instance.InformationUrl + IsFeatured = $instance.IsFeatured + InstallAsManaged = $instance.AdditionalProperties.installAsManaged + LargeIcon = $complexLargeIcon + MinimumSupportedOperatingSystem = $complexMinimumSupportedOperatingSystem + Notes = $instance.Notes + Owner = $instance.Owner + PrivacyInformationUrl = $instance.PrivacyInformationUrl + Publisher = $instance.Publisher + RoleScopeTagIds = $instance.RoleScopeTagIds + VersionNumber = $instance.AdditionalProperties.versionNumber + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ApplicationSecret = $ApplicationSecret + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens } #Assignments @@ -220,22 +250,8 @@ function Get-TargetResource $resultAssignments += ConvertFrom-IntuneMobileAppAssignment ` -IncludeDeviceFilter:$true ` -Assignments ($appAssignments) - - $results.Add('Assignments', $resultAssignments) - } - - #LargeIcon - # The large is returned only when Get cmdlet is called with Id parameter. The large icon is a base64 encoded string, so we need to convert it to a byte array. - $instanceWithLargeIcon = Get-MgBetaDeviceAppManagementMobileApp -MobileAppId $instance.Id - if($null -ne $instanceWithLargeIcon.LargeIcon) - { - $results.Add('LargeIcon', $instanceWithLargeIcon.LargeIcon) } - else { - $results.Add('LargeIcon', "") - } - - #end region complex types + $results.Add('Assignments', $resultAssignments) return [System.Collections.Hashtable] $results } @@ -258,7 +274,6 @@ function Set-TargetResource param ( #region Intune resource parameters - [Parameter()] [System.String] $Id, @@ -287,6 +302,14 @@ function Set-TargetResource [System.Boolean] $IgnoreVersionDetection, + [Parameter()] + [System.Boolean] + $InstallAsManaged, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $MinimumSupportedOperatingSystem, + [Parameter()] [System.String] $Notes, @@ -303,11 +326,6 @@ function Set-TargetResource [System.String] $Publisher, - [Parameter()] - [System.String] - [ValidateSet('notPublished', 'processing','published')] - $PublishingState, - [Parameter()] [System.String[]] $RoleScopeTagIds, @@ -389,135 +407,118 @@ function Set-TargetResource #endregion $currentInstance = Get-TargetResource @PSBoundParameters - $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 - - $CreateParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters - - # CREATE + $BoundParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { - Write-Host "Create MacOS app: $DisplayName" + Write-Verbose -Message "Creating an Intune MacOS Lob App with DisplayName {$DisplayName}" + $BoundParameters.Remove('Assignments') | Out-Null - $CreateParameters = ([Hashtable]$PSBoundParameters).clone() + $CreateParameters = ([Hashtable]$BoundParameters).Clone() $CreateParameters = Rename-M365DSCCimInstanceParameter -Properties $CreateParameters + $CreateParameters.Remove('Id') | Out-Null + $CreateParameters.Remove('Categories') | Out-Null - $AdditionalProperties = Get-M365DSCIntuneMobileMocOSLobAppAdditionalProperties -Properties ($CreateParameters) - foreach ($key in $AdditionalProperties.keys) + foreach ($key in ($CreateParameters.Clone()).Keys) { - if ($key -ne '@odata.type') + if ($null -ne $CreateParameters.$key -and $CreateParameters.$key.GetType().Name -like '*CimInstance*') { - $keyName = $key.substring(0, 1).ToUpper() + $key.substring(1, $key.length - 1) - $CreateParameters.remove($keyName) + $CreateParameters.$key = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $CreateParameters.$key } } - $CreateParameters.remove('Id') | Out-Null - $CreateParameters.remove('Ensure') | Out-Null - $CreateParameters.remove('Categories') | Out-Null - $CreateParameters.remove('Assignments') | Out-Null - $CreateParameters.remove('childApps') | Out-Null - $CreateParameters.remove('IgnoreVersionDetection') | Out-Null - $CreateParameters.Remove('Verbose') | Out-Null - $CreateParameters.Remove('PublishingState') | Out-Null #Not allowed to update as it's a computed property - $CreateParameters.Remove('LargeIcon') | Out-Null - - foreach ($key in ($CreateParameters.clone()).Keys) + $CreateParameters.Add('@odata.type', '#microsoft.graph.macOSLobApp') + $app = New-MgBetaDeviceAppManagementMobileApp -BodyParameter $CreateParameters + + foreach ($category in $Categories) { - if ($CreateParameters[$key].getType().Fullname -like '*CimInstance*') + if ($category.Id) { - $CreateParameters[$key] = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $CreateParameters[$key] + $currentCategory = Get-MgBetaDeviceAppManagementMobileAppCategory -CategoryId $category.Id + } + else + { + $currentCategory = Get-MgBetaDeviceAppManagementMobileAppCategory -Filter "displayName eq '$($category.DisplayName)'" } - } - if ($AdditionalProperties) - { - $CreateParameters.add('AdditionalProperties', $AdditionalProperties) - } + if ($null -eq $currentCategory) + { + throw "Mobile App Category with DisplayName $($category.DisplayName) not found." + } - #LargeIcon - if($LargeIcon) - { - [System.Object]$LargeIconValue = ConvertTo-M365DSCIntuneAppLargeIcon -LargeIcon $LargeIcon - $CreateParameters.Add('LargeIcon', $LargeIconValue) + Invoke-MgBetaGraphRequest -Uri "/beta/deviceAppManagement/mobileApps/$($app.Id)/categories/`$ref" -Method 'POST' -Body @{ + '@odata.id' = "https://graph.microsoft.com/beta/deviceAppManagement/mobileAppCategories/$($currentCategory.Id)" + } } - $app = New-MgBetaDeviceAppManagementMobileApp @CreateParameters - #Assignments - $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments - if ($app.id) + if ($app.Id) { - Update-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $app.id ` - -Target $assignmentsHash ` - -Repository 'deviceAppManagement/mobileAppAssignments' + $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + Update-DeviceAppManagementPolicyAssignment -AppManagementPolicyId $app.Id ` + -Assignments $assignmentsHash } } - # UPDATE elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { - Write-Host "Update MacOS app: $DisplayName" + Write-Host "Updating the Intune MacOS Lob App with DisplayName {$DisplayName}" + $BoundParameters.Remove('Assignments') | Out-Null - $PSBoundParameters.Remove('Assignments') | Out-Null - $UpdateParameters = ([Hashtable]$PSBoundParameters).clone() + $UpdateParameters = ([Hashtable]$BoundParameters).Clone() $UpdateParameters = Rename-M365DSCCimInstanceParameter -Properties $UpdateParameters - - $AdditionalProperties = Get-M365DSCIntuneMobileMocOSLobAppAdditionalProperties -Properties ($UpdateParameters) - foreach ($key in $AdditionalProperties.keys) - { - if ($key -ne '@odata.type') - { - $keyName = $key.substring(0, 1).ToUpper() + $key.substring(1, $key.length - 1) - #Remove additional keys, so that later they can be added as 'AdditionalProperties' - $UpdateParameters.Remove($keyName) - } - } - $UpdateParameters.Remove('Id') | Out-Null - $UpdateParameters.Remove('Verbose') | Out-Null $UpdateParameters.Remove('Categories') | Out-Null - $UpdateParameters.Remove('PublishingState') | Out-Null #Not allowed to update as it's a computed property - foreach ($key in ($UpdateParameters.clone()).Keys) + foreach ($key in ($UpdateParameters.Clone()).Keys) { - if ($UpdateParameters[$key].getType().Fullname -like '*CimInstance*') + if ($null -ne $UpdateParameters.$key -and $UpdateParameters.$key.GetType().Name -like '*CimInstance*') { - $value = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $UpdateParameters[$key] - $UpdateParameters[$key] = $value + $UpdateParameters.$key = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $UpdateParameters.$key } } - if ($AdditionalProperties) + $UpdateParameters.Add('@odata.type', '#microsoft.graph.macOSLobApp') + Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id -BodyParameter $UpdateParameters + + $delta = Compare-Object -ReferenceObject $currentInstance.Categories.DisplayName -DifferenceObject $Categories.DisplayName -PassThru + foreach ($diff in $delta) { - $UpdateParameters.Add('AdditionalProperties', $AdditionalProperties) - } + if ($diff.SideIndicator -eq '=>') + { + $category = $Categories | Where-Object { $_.DisplayName -eq $diff } + if ($category.Id) + { + $currentCategory = Get-MgBetaDeviceAppManagementMobileAppCategory -MobileAppCategoryId $category.Id + } + else + { + $currentCategory = Get-MgBetaDeviceAppManagementMobileAppCategory -Filter "displayName eq '$($category.DisplayName)'" + } - #LargeIcon - if($LargeIcon) - { - [System.Object]$LargeIconValue = ConvertTo-M365DSCIntuneAppLargeIcon -LargeIcon $LargeIcon - $UpdateParameters.Add('LargeIcon', $LargeIconValue) - } + if ($null -eq $currentCategory) + { + throw "Mobile App Category with DisplayName $($category.DisplayName) not found." + } - Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id @UpdateParameters - Write-Host "Updated MacOS App: $DisplayName." + Invoke-MgGraphRequest -Uri "/beta/deviceAppManagement/mobileApps/$($currentInstance.Id)/categories/`$ref" -Method 'POST' -Body @{ + '@odata.id' = "https://graph.microsoft.com/beta/deviceAppManagement/mobileAppCategories/$($currentCategory.Id)" + } + } + else + { + $category = $currentInstance.Categories | Where-Object { $_.DisplayName -eq $diff } + Invoke-MgGraphRequest -Uri "/beta/deviceAppManagement/mobileApps/$($currentInstance.Id)/categories/$($category.Id)/`$ref" -Method 'DELETE' + } + } #Assignments $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments - Update-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $currentInstance.id ` - -Target $assignmentsHash ` - -Repository 'deviceAppManagement/mobileAppAssignments' + Update-DeviceAppManagementPolicyAssignment -AppManagementPolicyId $currentInstance.Id ` + -Assignments $assignmentsHash } - # REMOVE elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { - Write-Host "Remove MacOS app: $DisplayName" + Write-Host "Remove the Intune MacOS Lob App with Id {$($currentInstance.Id)}" Remove-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id -Confirm:$false } } @@ -558,6 +559,14 @@ function Test-TargetResource [System.Boolean] $IgnoreVersionDetection, + [Parameter()] + [System.Boolean] + $InstallAsManaged, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $MinimumSupportedOperatingSystem, + [Parameter()] [System.String] $Notes, @@ -574,11 +583,6 @@ function Test-TargetResource [System.String] $Publisher, - [Parameter()] - [System.String] - [ValidateSet('notPublished', 'processing','published')] - $PublishingState, - [Parameter()] [System.String[]] $RoleScopeTagIds, @@ -610,7 +614,6 @@ function Test-TargetResource [Parameter()] [Microsoft.Management.Infrastructure.CimInstance] $LargeIcon, - #endregion [Parameter()] @@ -659,20 +662,10 @@ function Test-TargetResource Add-M365DSCTelemetryEvent -Data $data #endregion - Write-Verbose -Message "Testing configuration of Intune Mobile MacOS App: {$DisplayName}" + Write-Verbose -Message "Testing configuration of the Intune MacOS Lob App with Id {$Id} and DisplayName {$DisplayName}" $CurrentValues = Get-TargetResource @PSBoundParameters - if (-not (Test-M365DSCAuthenticationParameter -BoundParameters $CurrentValues)) - { - Write-Verbose "An error occured in Get-TargetResource, the app {$displayName} will not be processed" - throw "An error occured in Get-TargetResource, the app {$displayName} will not be processed. Refer to the event viewer logs for more information." - } - $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() - $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck - $ValuesToCheck.Remove('Id') | Out-Null - - Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" - Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() if ($CurrentValues.Ensure -ne $Ensure) { @@ -686,15 +679,14 @@ function Test-TargetResource { $source = $PSBoundParameters.$key $target = $CurrentValues.$key - if ($source.getType().Name -like '*CimInstance*') + if ($null -ne $source -and $source.GetType().Name -like '*CimInstance*') { $testResult = Compare-M365DSCComplexObject ` -Source ($source) ` -Target ($target) - if (-Not $testResult) + if (-not $testResult) { - $testResult = $false break } @@ -702,6 +694,17 @@ function Test-TargetResource } } + # Prevent screen from filling up with the LargeIcon value + # Comparison will already be done because it's a CimInstance + $CurrentValues.Remove('LargeIcon') | Out-Null + $PSBoundParameters.Remove('LargeIcon') | Out-Null + + $ValuesToCheck.Remove('Id') | Out-Null + $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + if ($testResult) { $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` @@ -721,6 +724,10 @@ function Export-TargetResource [OutputType([System.String])] param ( + [Parameter()] + [System.String] + $Filter, + [Parameter()] [System.Management.Automation.PSCredential] $Credential, @@ -770,9 +777,7 @@ function Export-TargetResource $Script:ExportMode = $true [array] $Script:getInstances = Get-MgBetaDeviceAppManagementMobileApp ` -Filter "isof('microsoft.graph.macOSLobApp')" ` - -ExpandProperty "categories,assignments" ` - -ErrorAction Stop | Where-Object ` - -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.macOSLobApp' } + -ErrorAction Stop $i = 1 $dscContent = '' @@ -812,57 +817,89 @@ function Export-TargetResource $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` -Results $Results - if (-not (Test-M365DSCAuthenticationParameter -BoundParameters $Results)) - { - Write-Verbose "An error occured in Get-TargetResource, the app {$($params.displayName)} will not be processed." - throw "An error occured in Get-TargetResource, the app {$($params.displayName)} will not be processed. Refer to the event viewer logs for more information." - } - #region complex types - - #Categories - if($null -ne $Results.Categories) + if ($null -ne $Results.Categories) { - $Results.Categories = Get-M365DSCIntuneAppCategoriesAsString -Categories $Results.Categories - } - else { - $Results.Remove('Categories') | Out-Null + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.Categories ` + -CIMInstanceName 'DeviceManagementMobileAppCategory' + + if (-not [System.String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.Categories = $complexTypeStringResult + } + else + { + $Results.Remove('Categories') | Out-Null + } } - #ChildApps - if($null -ne $Results.childApps) + if ($null -ne $Results.ChildApps) { - $Results.childApps = Get-M365DSCIntuneAppChildAppsAsString -ChildApps $Results.childApps - } - else { - $Results.Remove('childApps') | Out-Null + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.ChildApps ` + -CIMInstanceName 'DeviceManagementMobileAppChildApp' + + if (-not [System.String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.ChildApps = $complexTypeStringResult + } + else + { + $Results.Remove('ChildApps') | Out-Null + } } - #Assignments - if ($null -ne $Results.Assignments) + if ($null -ne $Results.LargeIcon) { - $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString -ComplexObject ([Array]$Results.Assignments) -CIMInstanceName DeviceManagementMobileAppAssignment + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.LargeIcon ` + -CIMInstanceName 'DeviceManagementMimeContent' - if ($complexTypeStringResult) + if (-not [System.String]::IsNullOrWhiteSpace($complexTypeStringResult)) { - $Results.Assignments = $complexTypeStringResult + $Results.LargeIcon = $complexTypeStringResult } else { - $Results.Remove('Assignments') | Out-Null + $Results.Remove('LargeIcon') | Out-Null } } - #LargeIcon - if($null -ne $Results.LargeIcon) + if ($null -ne $Results.MinimumSupportedOperatingSystem) { - $Results.LargeIcon = Get-M365DSCIntuneAppLargeIconAsString -LargeIcon $Results.LargeIcon + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.MinimumSupportedOperatingSystem ` + -CIMInstanceName 'DeviceManagementMinimumOperatingSystem' + + if (-not [System.String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.MinimumSupportedOperatingSystem = $complexTypeStringResult + } + else + { + $Results.Remove('MinimumSupportedOperatingSystem') | Out-Null + } } - else + + if ($null -ne $Results.Assignments) { - $Results.Remove('LargeIcon') | Out-Null - } + if ($Results.Assignments) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.Assignments ` + -CIMInstanceName DeviceManagementMobileAppAssignment + if ($complexTypeStringResult) + { + $Results.Assignments = $complexTypeStringResult + } + else + { + $Results.Remove('Assignments') | Out-Null + } + } + } #endregion complex types $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` @@ -872,49 +909,30 @@ function Export-TargetResource -Credential $Credential #region complex types - - #Categories if ($null -ne $Results.Categories) { - $isCIMArray = $false - if ($Results.Categories.getType().Fullname -like '*[[\]]') - { - $isCIMArray = $true - } - - $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Categories' -IsCIMArray:$isCIMArray + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Categories' -IsCIMArray:$true } - #ChildApps - if ($null -ne $Results.childApps) + if ($null -ne $Results.ChildApps) { - $isCIMArray = $false - if ($Results.childApps.getType().Fullname -like '*[[\]]') - { - $isCIMArray = $true - } - - $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'ChildApps' -IsCIMArray:$isCIMArray + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'ChildApps' -IsCIMArray:$true } - #Assignments - if ($null -ne $Results.Assignments) + if ($null -ne $Results.LargeIcon) { - $isCIMArray = $false - if ($Results.Assignments.getType().Fullname -like '*[[\]]') - { - $isCIMArray = $true - } - - $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Assignments' -IsCIMArray:$isCIMArray + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'LargeIcon' -IsCIMArray:$false } - #LargeIcon - if ($null -ne $Results.LargeIcon) + if ($null -ne $Results.MinimumSupportedOperatingSystem) { - $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'LargeIcon' -IsCIMArray:$false + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'MinimumSupportedOperatingSystem' -IsCIMArray:$false } + if ($null -ne $Results.Assignments) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Assignments' -IsCIMArray:$true + } #endregion complex types $dscContent += $currentDSCBlock @@ -940,184 +958,4 @@ function Export-TargetResource } } -#region Helper functions - -function Get-M365DSCIntuneAppCategoriesAsString -{ - [CmdletBinding()] - [OutputType([System.String])] - param( - [Parameter(Mandatory = $true)] - [System.Object[]] - $Categories - ) - - $StringContent = '@(' - $space = ' ' - $indent = ' ' - - $i = 1 - foreach ($category in $Categories) - { - if ($Categories.Count -gt 1) - { - $StringContent += "`r`n" - $StringContent += "$space" - } - - #Only export the displayName, not Id - $StringContent += "MSFT_DeviceManagementMobileAppCategory { `r`n" - $StringContent += "$($space)$($indent)displayName = '" + $category.displayName + "'`r`n" - $StringContent += "$space}" - - $i++ - } - - $StringContent += ')' - - return $StringContent -} - -function Get-M365DSCIntuneAppChildAppsAsString -{ - [CmdletBinding()] - [OutputType([System.String])] - param( - [Parameter(Mandatory = $true)] - [System.Object[]] - $ChildApps - ) - - $StringContent = '@(' - $space = ' ' - $indent = ' ' - - $i = 1 - foreach ($childApp in $ChildApps) - { - if ($ChildApps.Count -gt 1) - { - $StringContent += "`r`n" - $StringContent += "$space" - } - - $StringContent += "MSFT_DeviceManagementMobileAppChildApp { `r`n" - $StringContent += "$($space)$($indent)bundleId = '" + $childApp.bundleId + "'`r`n" - $StringContent += "$($space)$($indent)buildNumber = '" + $childApp.buildNumber + "'`r`n" - $StringContent += "$($space)$($indent)versionNumber = '" + $childApp.versionNumber + "'`r`n" - $StringContent += "$space}" - - $i++ - } - - $StringContent += ')' - - return $StringContent -} - -function Get-M365DSCIntuneMobileMocOSLobAppAdditionalProperties -{ - [CmdletBinding()] - [OutputType([System.Collections.Hashtable])] - param - ( - [Parameter(Mandatory = 'true')] - [System.Collections.Hashtable] - $Properties - ) - - $additionalProperties = @( - 'IgnoreVersionDetection' - 'ChildApps' - ) - - $results = @{'@odata.type' = '#microsoft.graph.macOSLobApp' } - $cloneProperties = $Properties.clone() - foreach ($property in $cloneProperties.Keys) - { - if ($property -in $additionalProperties) - { - $propertyName = $property[0].ToString().ToLower() + $property.Substring(1, $property.Length - 1) - if ($properties.$property -and $properties.$property.getType().FullName -like '*CIMInstance*') - { - if ($properties.$property.getType().FullName -like '*[[\]]') - { - $array = @() - foreach ($item in $properties.$property) - { - $array += Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $item - - } - $propertyValue = $array - } - else - { - $propertyValue = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $properties.$property - } - - } - else - { - $propertyValue = $properties.$property - } - - $results.Add($propertyName, $propertyValue) - } - } - - if ($results.Count -eq 1) - { - return $null - } - return $results -} - -function Get-M365DSCIntuneAppLargeIconAsString #Get and Export -{ - [CmdletBinding()] - [OutputType([System.String])] - param( - [Parameter(Mandatory = $true)] - [System.Object] - $LargeIcon - ) - - $space = ' ' - $indent = ' ' - - if ($null -ne $LargeIcon.Value) - { - $StringContent += "`r`n" - $StringContent += "$space" - - $base64String = [System.Convert]::ToBase64String($LargeIcon.Value) # This exports the base64 string (blob) of the byte array, same as we see in Graph API response - - $StringContent += "MSFT_DeviceManagementMimeContent { `r`n" - $StringContent += "$($space)$($indent)type = '" + $LargeIcon.Type + "'`r`n" - $StringContent += "$($space)$($indent)value = '" + $base64String + "'`r`n" - $StringContent += "$space}" - } - - return $StringContent - } - -function ConvertTo-M365DSCIntuneAppLargeIcon #set -{ - [OutputType([System.Object])] - param( - [Parameter(Mandatory = $true)] - [System.Object] - $LargeIcon - ) - - $result = @{ - type = $LargeIcon.Type - value = $iconValue - } - - return $result -} - -#endregion Helper functions - Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof index 88248b6460..ec3e29882d 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof @@ -1,9 +1,54 @@ -[ClassVersion("1.0.0"), FriendlyName("IntuneMobileAppsMacOSLobApp")] +class MSFT_DeviceManagementMobileAppAssignment +{ + [Write, Description("The type of the target assignment."), ValueMap{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget", "#microsoft.graph.mobileAppAssignment"}, Values{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget", "#microsoft.graph.mobileAppAssignment"}] String dataType; + [Write, Description("The Id of the filter for the target assignment.")] String deviceAndAppManagementAssignmentFilterId; + [Write, Description("The type of filter of the target assignment i.e. Exclude or Include. Possible values are: none, include, exclude."), ValueMap{"none", "include", "exclude"}, Values{"none", "include", "exclude"}] String deviceAndAppManagementAssignmentFilterType; + [Write, Description("The group Id that is the target of the assignment.")] String groupId; + [Write, Description("The group Display Name that is the target of the assignment.")] String groupDisplayName; + [Write, Description("Possible values for the install intent chosen by the admin."), ValueMap{"available", "required", "uninstall", "availableWithoutEnrollment"}, Values{"available", "required", "uninstall", "availableWithoutEnrollment"}] String intent; +}; + +class MSFT_DeviceManagementMinimumOperatingSystem +{ + [Write, Description("Indicates if Mac OS X 10.7 or later is required to install the app.")] Boolean v10_7; + [Write, Description("Indicates if Mac OS X 10.8 or later is required to install the app.")] Boolean v10_8; + [Write, Description("Indicates if Mac OS X 10.9 or later is required to install the app.")] Boolean v10_9; + [Write, Description("Indicates if Mac OS X 10.10 or later is required to install the app.")] Boolean v10_10; + [Write, Description("Indicates if Mac OS X 10.11 or later is required to install the app.")] Boolean v10_11; + [Write, Description("Indicates if Mac OS X 10.12 or later is required to install the app.")] Boolean v10_12; + [Write, Description("Indicates if Mac OS X 10.13 or later is required to install the app.")] Boolean v10_13; + [Write, Description("Indicates if Mac OS X 10.14 or later is required to install the app.")] Boolean v10_14; + [Write, Description("Indicates if Mac OS X 10.15 or later is required to install the app.")] Boolean v10_15; + [Write, Description("Indicates if Mac OS X 11.0 or later is required to install the app.")] Boolean v11_0; + [Write, Description("Indicates if Mac OS X 12.0 or later is required to install the app.")] Boolean v12_0; + [Write, Description("Indicates if Mac OS X 13.0 or later is required to install the app.")] Boolean v13_0; + [Write, Description("Indicates if Mac OS X 14.0 or later is required to install the app.")] Boolean v14_0; +}; + +class MSFT_DeviceManagementMimeContent +{ + [Write, Description("Indicates the type of content mime.")] String Type; + [Write, Description("The Base64 encoded string content.")] String Value; +}; + +class MSFT_DeviceManagementMobileAppCategory +{ + [Key, Description("The name of the app category.")] String DisplayName; + [Write, Description("The unique identifier for an entity. Read-only.")] String Id; +}; + +class MSFT_DeviceManagementMobileAppChildApp +{ + [Write, Description("The bundleId of the app.")] String BundleId; + [Write, Description("The build number of the app.")] String BuildNumber; + [Write, Description("The version number of the app.")] String VersionNumber; +}; + +[ClassVersion("1.0.0.0"), FriendlyName("IntuneMobileAppsMacOSLobApp")] class MSFT_IntuneMobileAppsMacOSLobApp : OMI_BaseResource { [Key, Description("The admin provided or imported title of the app. Inherited from mobileApp.")] String DisplayName; [Write, Description("The unique identifier for an entity. Read-only. Inherited from mobileApp object.")] String Id; - [Write, Description("The description of the app. Inherited from mobileApp.")] String Description; [Write, Description("The dewveloper of the app. Inherited from mobileApp.")] String Developer; [Write, Description("The InformationUrl of the app. Inherited from mobileApp.")] String InformationUrl; @@ -12,17 +57,17 @@ class MSFT_IntuneMobileAppsMacOSLobApp : OMI_BaseResource [Write, Description("The owner of the app. Inherited from mobileApp.")] String Owner; [Write, Description("The privacy statement Url. Inherited from mobileApp.")] String PrivacyInformationUrl; [Write, Description("The publisher of the app. Inherited from mobileApp.")] String Publisher; - [Write, Description("The publishing state for the app. The app cannot be assigned unless the app is published. Inherited from mobileApp."), ValueMap{"notPublished", "processing","published"}, Values{"notPublished", "processing", "published"}] String PublishingState; - [Write, Description("The bundleId of the app.")] String BundleId; + [Write, Description("The bundleId of the app.")] String BundleId; [Write, Description("The build number of the app.")] String BuildNumber; [Write, Description("The version number of the app.")] String VersionNumber; [Write, Description("List of Scope Tag IDs for mobile app.")] String RoleScopeTagIds[]; - [Write, Description("Wether to ignore the version of the app or not.")] Boolean IgnoreVersionDetection; + [Write, Description("Whether to ignore the version of the app or not.")] Boolean IgnoreVersionDetection; + [Write, Description("Install the app as managed. Requires macOS 11.0.")] Boolean InstallAsManaged; [Write, Description("The icon for this app."), EmbeddedInstance("MSFT_DeviceManagementMimeContent")] String LargeIcon; + [Write, Description("The minimum supported operating system to install the app."), EmbeddedInstance("MSFT_DeviceManagementMinimumOperatingSystem")] String MinimumSupportedOperatingSystem; [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppCategory")] String Categories[]; [Write, Description("The list of assignments for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppAssignment")] String Assignments[]; [Write, Description("The list of child apps for this app package."), EmbeddedInstance("MSFT_DeviceManagementMobileAppChildApp")] String ChildApps[]; - [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] String Ensure; [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] String Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; @@ -32,46 +77,3 @@ class MSFT_IntuneMobileAppsMacOSLobApp : OMI_BaseResource [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; [Write, Description("Access token used for authentication.")] String AccessTokens[]; }; - -class MSFT_DeviceManagementMimeContent -{ - [Write, Description("Indicates the type of content mime.")] String type; - [Write, Description("The byte array that contains the actual content.")] String value[]; -}; - -class MSFT_DeviceManagementMobileAppCategory -{ - [Key, Description("The name of the app category.")] String displayName; - [Write, Description("The unique identifier for an entity. Read-only.")] String id; -}; - -class MSFT_DeviceManagementMobileAppChildApp -{ - [Write, Description("The bundleId of the app.")] String bundleId; - [Write, Description("The build number of the app.")] String buildNumber; - [Write, Description("The version number of the app.")] String versionNumber; -}; - -class MSFT_DeviceManagementMobileAppAssignment -{ - [Write, Description("The type of the target assignment."), - ValueMap{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget", "#microsoft.graph.mobileAppAssignment"}, - Values{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget", "#microsoft.graph.mobileAppAssignment"}] - String dataType; - - [Write, Description("The Id of the filter for the target assignment.")] String deviceAndAppManagementAssignmentFilterId; - [Write, Description("The type of filter of the target assignment i.e. Exclude or Include. Possible values are: none, include, exclude."), - ValueMap{"none", "include", "exclude"}, - Values{"none", "include", "exclude"}] - String deviceAndAppManagementAssignmentFilterType; - - [Write, Description("The group Id that is the target of the assignment.")] String groupId; - [Write, Description("The group Display Name that is the target of the assignment.")] String groupDisplayName; - - [Write, Description("Possible values for the install intent chosen by the admin."), - ValueMap{"available", "required", "uninstall", "availableWithoutEnrollment"}, - Values{"available", "required", "uninstall", "availableWithoutEnrollment"}] - String intent; - - [Write, Description("The source of this assignment.")] String source; -}; diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 index fce902352a..09046e547f 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 @@ -31,30 +31,31 @@ Configuration Example Ensure = "Present"; InformationUrl = ""; IsFeatured = $False; + MinimumSupportedOperatingSystem = MinimumSupportedOperatingSystem{ + v11_0 = $true + } Notes = ""; Owner = ""; PrivacyInformationUrl = ""; Publisher = "Contoso"; - PublishingState = "published"; Assignments = @( MSFT_DeviceManagementMobileAppAssignment{ - groupDisplayName = 'All devices' - source = 'direct' + groupDisplayName = 'All devices' deviceAndAppManagementAssignmentFilterType = 'none' dataType = '#microsoft.graph.allDevicesAssignmentTarget' intent = 'required' } MSFT_DeviceManagementMobileAppAssignment{ deviceAndAppManagementAssignmentFilterType = 'none' - source = 'direct' dataType = '#microsoft.graph.groupAssignmentTarget' groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' intent = 'required' } ); - Categories = @(MSFT_DeviceManagementMobileAppCategory { - id = '1bff2652-03ec-4a48-941c-152e93736515' - displayName = 'Kajal 3' + Categories = @( + MSFT_DeviceManagementMobileAppCategory { + Id = '1bff2652-03ec-4a48-941c-152e93736515' + DisplayName = 'Kajal 3' }); } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 index 5687dfcd83..0a7024eb48 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 @@ -31,30 +31,30 @@ Configuration Example Ensure = "Present"; InformationUrl = ""; IsFeatured = $False; + MinimumSupportedOperatingSystem = MinimumSupportedOperatingSystem{ + v11_0 = $true + } Notes = ""; Owner = ""; PrivacyInformationUrl = ""; Publisher = "Contoso"; - PublishingState = "published"; Assignments = @( MSFT_DeviceManagementMobileAppAssignment{ - groupDisplayName = 'All devices' - source = 'direct' + groupDisplayName = 'All devices' deviceAndAppManagementAssignmentFilterType = 'none' dataType = '#microsoft.graph.allDevicesAssignmentTarget' intent = 'required' } MSFT_DeviceManagementMobileAppAssignment{ deviceAndAppManagementAssignmentFilterType = 'none' - source = 'direct' dataType = '#microsoft.graph.groupAssignmentTarget' groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' intent = 'required' } ); Categories = @(MSFT_DeviceManagementMobileAppCategory { - id = '1bff2652-03ec-4a48-941c-152e93736515' - displayName = 'Kajal 3' + Id = '1bff2652-03ec-4a48-941c-152e93736515' + DisplayName = 'Kajal 3' }); } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/3-Remove.ps1 index 33cc9276b4..4d1bf4b0a7 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/3-Remove.ps1 @@ -25,17 +25,8 @@ Configuration Example IntuneMobileAppsMacOSLobApp "IntuneMobileAppsMacOSLobApp-TeamsForBusinessInstaller" { Id = "8d027f94-0682-431e-97c1-827d1879fa79"; - Description = "TeamsForBusinessInstaller"; - Developer = "Contoso"; DisplayName = "TeamsForBusinessInstaller"; Ensure = "Absent"; - InformationUrl = ""; - IsFeatured = $False; - Notes = ""; - Owner = ""; - PrivacyInformationUrl = ""; - Publisher = "Contoso"; - PublishingState = "published"; } } } diff --git a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 index 30baaf6254..af403fb2d3 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 @@ -1073,7 +1073,6 @@ function ConvertFrom-IntuneMobileAppAssignment } $hashAssignment.Add('intent', $assignment.intent.ToString()) - $hashAssignment.Add('source', $assignment.source.ToString()) # $concatenatedSettings = $assignment.settings.ToString() -join ',' # $hashAssignment.Add('settings', $concatenatedSettings) @@ -1125,6 +1124,7 @@ function ConvertTo-IntuneMobileAppAssignment $assignmentResult = @() foreach ($assignment in $Assignments) { + $formattedAssignment = @{} $target = @{"@odata.type" = $assignment.dataType} if ($IncludeDeviceFilter) { @@ -1132,14 +1132,10 @@ function ConvertTo-IntuneMobileAppAssignment { $target.Add('deviceAndAppManagementAssignmentFilterType', $assignment.DeviceAndAppManagementAssignmentFilterType) $target.Add('deviceAndAppManagementAssignmentFilterId', $assignment.DeviceAndAppManagementAssignmentFilterId) - - $target.GetEnumerator() | ForEach-Object { - Write-Host "target key:value: $($_.Key): $($_.Value)" } } } - $assignmentResult += $assignment.intent; - $assignmentResult += $assignment.source; + $formattedAssignment.Add('intent', $assignment.intent) if ($assignment.dataType -like '*groupAssignmentTarget') { @@ -1181,8 +1177,9 @@ function ConvertTo-IntuneMobileAppAssignment if ($target) { - $assignmentResult += @{target = $target} + $formattedAssignment.Add('target', $target) } + $assignmentResult += $formattedAssignment } return ,$assignmentResult @@ -1209,6 +1206,8 @@ function Compare-M365DSCIntunePolicyAssignment { $assignmentTarget = $Target | Where-Object -FilterScript { $_.dataType -eq $assignment.DataType -and $_.groupId -eq $assignment.groupId } $testResult = $null -ne $assignmentTarget + # Check for mobile app assignments with intent + $testResult = $assignment.intent -eq $assignmentTarget.intent # Using assignment groupDisplayName only if the groupId is not found in the directory otherwise groupId should be the key if (-not $testResult) { @@ -1314,14 +1313,14 @@ function Update-DeviceConfigurationPolicyAssignment { $message = "Skipping assignment for the group with DisplayName {$($target.groupDisplayName)} as it could not be found in the directory.`r`n" $message += "Please update your DSC resource extract with the correct groupId or groupDisplayName." - write-verbose -Message $message + Write-Verbose -Message $message $target = $null } if ($group -and $group.count -gt 1) { $message = "Skipping assignment for the group with DisplayName {$($target.groupDisplayName)} as it is not unique in the directory.`r`n" $message += "Please update your DSC resource extract with the correct groupId or a unique group DisplayName." - write-verbose -Message $message + Write-Verbose -Message $message $group = $null $target = $null } @@ -1330,7 +1329,7 @@ function Update-DeviceConfigurationPolicyAssignment { $message = "Skipping assignment for the group with Id {$($target.groupId)} as it could not be found in the directory.`r`n" $message += "Please update your DSC resource extract with the correct groupId or a unique group DisplayName." - write-verbose -Message $message + Write-Verbose -Message $message $target = $null } } @@ -1372,6 +1371,126 @@ function Update-DeviceConfigurationPolicyAssignment } } +function Update-DeviceAppManagementPolicyAssignment +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param ( + [Parameter(Mandatory = $true)] + [System.String] + $AppManagementPolicyId, + + [Parameter()] + [Array] + $Assignments, + + [Parameter()] + [System.String] + $Repository = 'deviceAppManagement/mobileApps', + + [Parameter()] + [ValidateSet('v1.0','beta')] + [System.String] + $APIVersion = 'beta', + + [Parameter()] + [System.String] + $RootIdentifier = 'mobileAppAssignments' + ) + + try + { + $appManagementPolicyAssignments = @() + $Uri = "/$APIVersion/$Repository/$AppManagementPolicyId/assign" + + foreach ($assignment in $Assignments) + { + $formattedAssignment = @{ + '@odata.type' = '#microsoft.graph.mobileAppAssignment' + intent = $assignment.intent + } + if ($assigment.settings) + { + $formattedAssignment.Add('settings', $assignment.settings) + } + + if ($assignment.target -is [hashtable]) + { + $target = $assignment.target + } + + $formattedTarget = @{"@odata.type" = $target.dataType} + if(-not $formattedTarget."@odata.type" -and $target."@odata.type") + { + $formattedTarget."@odata.type" = $target."@odata.type" + } + if ($target.groupId) + { + $group = Get-MgGroup -GroupId ($target.groupId) -ErrorAction SilentlyContinue + if ($null -eq $group) + { + if ($target.groupDisplayName) + { + $group = Get-MgGroup -Filter "DisplayName eq '$($target.groupDisplayName)'" -ErrorAction SilentlyContinue + if ($null -eq $group) + { + $message = "Skipping assignment for the group with DisplayName {$($target.groupDisplayName)} as it could not be found in the directory.`r`n" + $message += "Please update your DSC resource extract with the correct groupId or groupDisplayName." + Write-Verbose -Message $message + $target = $null + } + if ($group -and $group.count -gt 1) + { + $message = "Skipping assignment for the group with DisplayName {$($target.groupDisplayName)} as it is not unique in the directory.`r`n" + $message += "Please update your DSC resource extract with the correct groupId or a unique group DisplayName." + Write-Verbose -Message $message + $group = $null + $target = $null + } + } + else + { + $message = "Skipping assignment for the group with Id {$($target.groupId)} as it could not be found in the directory.`r`n" + $message += "Please update your DSC resource extract with the correct groupId or a unique group DisplayName." + Write-Verbose -Message $message + $target = $null + } + } + #Skipping assignment if group not found from either groupId or groupDisplayName + if ($null -ne $group) + { + $formattedTarget.Add('groupId',$group.Id) + } + } + if ($target.deviceAndAppManagementAssignmentFilterType) + { + $formattedTarget.Add('deviceAndAppManagementAssignmentFilterType',$target.deviceAndAppManagementAssignmentFilterType) + } + if ($target.deviceAndAppManagementAssignmentFilterId) + { + $formattedTarget.Add('deviceAndAppManagementAssignmentFilterId',$target.deviceAndAppManagementAssignmentFilterId) + } + $formattedAssignment.Add('target', $formattedTarget) + $appManagementPolicyAssignments += $formattedAssignment + } + + $body = @{$RootIdentifier = $appManagementPolicyAssignments} | ConvertTo-Json -Depth 20 + Write-Verbose -Message $body + + Invoke-MgGraphRequest -Method POST -Uri $Uri -Body $body -ErrorAction Stop + } + catch + { + New-M365DSCLogEntry -Message 'Error updating data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $null + } +} + function Get-OmaSettingPlainTextValue { [CmdletBinding()] diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 index 4e98962328..45eea18922 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 @@ -68,9 +68,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Owner = "" PrivacyInformationUrl = "" Publisher = "Contoso" - PublishingState = "published" RoleScopeTagIds = @() - Ensure = 'Present' Credential = $Credential } @@ -105,7 +103,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Owner = "" PrivacyInformationUrl = "" Publisher = "Contoso" - PublishingState = "published" RoleScopeTagIds = @() IgnoreVersionDetection = $True @@ -165,7 +162,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Owner = "" PrivacyInformationUrl = "" Publisher = "Contoso" - PublishingState = "published" RoleScopeTagIds = @() Ensure = 'Present' Credential = $Credential; @@ -213,9 +209,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Owner = "" PrivacyInformationUrl = "" Publisher = "Contoso" - PublishingState = "published" RoleScopeTagIds = @() - Ensure = 'Present' Credential = $Credential; } From d8d461192db01e7251da00569b592cb33733be8f Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Tue, 8 Oct 2024 13:04:08 -0700 Subject: [PATCH 119/252] updating perms settings to pass PR validation. --- .../DSCResources/MSFT_IntuneDerivedCredential/settings.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/settings.json index 1ca28f6ad4..488bd5b384 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/settings.json @@ -6,18 +6,14 @@ "graph": { "delegated": { "read": [ - "" ], "update": [ - "" ] }, "application": { "read": [ - "" ], "update": [ - "" ] } } From 5e8af183c0ed136f1cf9320f3598fc98f84dbc74 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 8 Oct 2024 16:11:34 -0400 Subject: [PATCH 120/252] Update Graph.PermissionList.txt Full Permission list --- Tests/QA/Graph.PermissionList.txt | Bin 5826 -> 23238 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Tests/QA/Graph.PermissionList.txt b/Tests/QA/Graph.PermissionList.txt index 826113f235a6a0d9238e46bc09b5d42a131a610f..cf0217fdd80ea178b7d2fcaf254df03117a32835 100644 GIT binary patch literal 23238 zcmbVUOLybQZr9LsjBck6QZR<~x=f#mN| z5j_4aJixSOH`ZOt$i=d03Ws|d&G8D9TUva1Z%uW7$uOmu(A3t9BlHjIOr+##uaMm& zOFEP4<+~{z(jySmQ1Xdj`(9p#04u(lzTVfSTJ@$f82GXo7BBsI7)|vw4Ck`lnW8eM zrn?-09?Rj!qQ_+AVDCJEujTuBFn#f0e%3p~EfrhLtZJ0!D!|mwPv@qA>SNzE3cAKx zIT!}KnEtpOyIurmKw&8Uf)=5pOzJ^O_|`O7My4vd{!q5{KTBFtgUs{5eU*M~&coa4 zt;C{J%a!FU+pfJFyYo=2jiKc+EdJ5et!Q1KJ3mc7h}Z=rj0tG7efc8+EzecmeXT3g z1(Dm`o2kx?`O-en7O9HATAsK~*VMbq;>EPsH!|F`oBoXlqFC;BW*D9^7v`OjqHzih zqc&j>)Y=?h(TlhG1d%=US4pdmbz2W(k3Rl1P)pR1mhw2&-k~>!mX?wifik3|;|T`D zE-z`Qek5aZ>g&Oc zXdcY)W9&|7bzf_fLECV7Iyq|9@dTI^&g6n|_5i}3yT&Ysp+2;JEF>s@%QUa{C zdG^0|*ru=-v<+m=V)iesdFZiHX9>1%Wp6guRM4#B8`({nd9q#ZxUx;pp~GO^V~o$I zXETspyOZT|rp=^}wvULeh+}K&2V)}0qvu4dJ8bDrY$Ho`IG-Cq2FNb<3N_X84w$17^xp%NIIvS!{vtaBOS{9i- zMxu^o|3m50ckeiY=$!iu>!@tbeGa1%#ej1zeY-xDYYux4t{W$~WR~2#!wg58=zTae z4s~8YIfko4FlNR)f@LHsmROMqBFmgkSks*=*ps`5df0Vv5%rcJ+-9X_R{>Pp-SK$F z($<_2NRz^+ZO3Qxzr1L}vLRnLhDS^||E=XB7d8B1qGHu|!yumLQ@ii_V>q2UiI$q(4w ziIXINZaI#9{dyi#pG`)B)xJV?RiN{A)Z&@QdoX)=?6HF(n(I~*sK3&dn04zNYllCA>JMobaiBm(mXG#OzV+yiU)yB!R*yZ7+mc~LnEEy&+aEt~(H z5`FG=WfQK)T5ICTp~K>rTd>$l@*1$=)u7E{QyqeU69VUf%Lih8HusuQ?@jt$3A!sb!ERhu)&!2Sv5L9L4LGe=@!r_-mdsSsWiY8SjyCdPr7f>xck~Yim=YH{pz?H` z<|bi(Ax00+G!pgHzINxfO7zu@r4%zweL0UGNt%$%h?t~3y?-Xhu+M)3m ztcVEqdR%M~`2CnlE0YmsGYQ_3;l^Gc-f%9`%3d4XSazY)pAoWa$u{vpj{FhEcu?_( zEBK&>BSK%f8@}lrV#)?%zIUOWSq0{ZlsNc#xCIB7gnOy+d$YUj8uP8|f9$dM)uHvd z&f+xlFjAgw@JCPXtdansJDhS9>#~--Q{n&O1(f{cMc^q|4WZb=r{uq0yT9cK4RcBK zF*xXNahz&=I+CCC_&5FQ8v-LE{oGlOD30V>j(}D>&Mb*Czt~;VF1m#033V?-3@N;g>*dagqU zQ`G9FH%EWN+Fmg3$W+>luGa2DI^8M}Bd0iQ&aX|4utj^Y5iC($k!F|bWC72|f}+)-xXe{@^y+9R(bgZDsu@J=h-*MNN2d50|z)*1O?r=aTzu2%zc}lDw!- zh!@W26Hs~9b&VYK(Cx>6|Ih!hab-2XN|!mpyx5nn>hf|tCNOTwe#DL9UQ$(o&B75# zJEI;#g=TXIB@Xr(Ys*!z(2;A`nG$`SMhojsjXI1shJL#l(gG)NC8Q~Jf_+0jC6J;7 zB*27Q$X^fvJi>jDu}~yZx!?~DWzH5@)5str1X4C)nG1~-x#A(&7*>RLE_ra2B6JcO z)Hti1s*lKELz;e81uG|tP?H-zWW+^8@Uz~!Do@q*)|gGvSI0|~0f`FrXGDYm{B+1g z#0TRpL~aS&NvKVx&!3PdJNE`v3kYY9Q(Zop>ZSW(+OK6(ODJqgbA6IUmk(#!ZBtxE zN;nl6Rk;}IQ(qnpxd{c11B_y{F*HP)rAQ%NRil`W1|($v=w59;jjbtD5-e;D66PSm z!-)tpGKrtT2}{NjPy;Wh?n-WDkx(1YmDORD`zNMx`9Qs$$8x0O8VO1W_=<+%&&jb$ zTx%*Kxze7Z%Qou6lCIn;>gGgno?JDue7K3{hy>tbDIH819-I15zt#;7lbe*9qra+E zo++mmXYV#|-KdUAdr}3cZHu=-cfjU>@$q#gc8yQqiiv!!9V$C;Gww@7PtH3s7ivFT zAqZmrY*n5_{Lmp69?heIoXMp?0MlKRfomzU$hRl6L*?Esu}$1LI6j;mCj;Wv=LhsJ zrabb9-bhcLh0sSOWAW1RUUU%`mPJ(3wHruz8O3z@^@e(_+sJZF=S61P&MpBAMhfRt z+h)Z>km6!BQ|zNHLCdj<>Q`jv`j#{xBr~n3Xz`quf#iB)+UJU_6RnD%lO~&MQqf48 zx5-QOa|`f}VlnWSDcr_8#|p*1aU{W7M35#{XnLRz+Yyzj^QnHLlBp@golIfntXhzN?Q{z8zhTpkus|Caq`qui* zC^yjF;=QP8C2LASr$e;xxTWa?F*vho7*1{`XI&mAmASUPJcSwqUr{Szz3I^zYHl+W zS`fl>fB2Y|%;H-FQ^cowzc=i_t30^yWKoLs{Q5sg(mZnjd{Q;Fox>^tbK$34Txyn$ zlSX`E+w=~(=xRR0&me*w0$Zuaf72}>TmT59vW`3&2`rYSh#B!m*HY+AEqB0V2YED9QUjvy!-%h?&_7^G&T!c|KNV%Ja** zQF7z|qo3vbWgRWwje6d$*-ewj;|0naTmQAO`Lz+rjlxyleVbZ1EWFXY|iNv4ZIhfL&k$k6ls{#HKgEECe%L0vqzE~P?5j&2!0{ihzf51 zjzIKd%)0oT3XE(uy)lWrp%-RIFw&AM?sp`k!HWtiyjPcK!Qm{km6S?*7Mx(x zE(G+{w}%@Z$IWn;$AqXB=!v0^swr$}g%*h|&>3I4Ckm!TPeplfn23_FD@xE(B0aP* zgG*Y7lchoErW^*$V5Ot*2`l0qZF>8lMi*QaZ*U>Ue90Nf;K#OnZK%+W{)Z?UYBMB{ zD%g-$<=;;&+(pGL_pRXhdR4i{;ecmmy!b=>bc;2{WrP$@Ab4CdEwSc!z-B4pzQYBh z7)Ch31ubp|UezM)#0_rW>ivkAsjc}?t_!J?#l{V}trxWXTKD4_X@TS^4iCo+E{L2G zL_J|I#nL3@N*elX4!#`nj*9tMyU@zFx~&lFmlp`qXN81W*mo#Mp(Rbm3^SDQpD{My z>*EP8E|CEtf&w-3*Z`(_t5Hmg$5I!5nz|@4u{(LVakNiDU|uSQkJe_6FiZq|r}w!Y zGfbYi3aUID<*nzWfe0{$UxR&_TA?BJVwS}n=y?t7+*l%vUk0AGt4zsRmH>M&r`}*m znd-aqCUxWug~J{{W7hCCRW4Z(-$%rsjH!469vXVxDiS;pFVfRH6F-H(6;Lh}zWPC? z*jZkjZ&cHgrJ?N@;luoA;JmWe@*aNi8P5=4SWcA8DPC%3WCFFCrbjEQR?s5o+U8OW zs4_-ZGl2vvQRrm{$luHACq1~W`1xjN)v5JNi;lXb0Wu&O`ZUl}B;%>JyAtIdwrgZB zQDcMx6U0q;(K`&vI8SiM|2&sSlH+s?0>13`uU*+!T85tS%(jfFX(sqSJ z6s~)4rRWXGZg3+Tdf-9@6e|t|+M&fQveEB&HX0yb&kb%#r9|!nc#BtUiV9DK>9HDh zH(cgex6kz}cKXF8hOi7J1~Z*prk+Pn`+&2;PzA`4^Fo3kIAJwEvR-xWPkA@%&*BgQ zv@c>%C&q8}y<;Pduh$RP309l+s(877C_YOq7M;2kg8pIHu!=fgBJ;2TQP7mVO|&+ z7vJa%39JE*1Nz7V3<^IByGkgDPxpfCDk<%FALWvXSq|h8;CUs&0PYPbuiF?D)@s-c zG8Ex=vByUuzRTh9y&S%m5NvDC?CpTg%cu2nV_$_`TEj;k6_MWTO;QI+$~QqbHuyu=vf4#k+ZZ!)swa_}=}QO#To% z(ny%IBGT^(xTsrl?Fzhp;;(ZoDoI_#s5krX5JJyZzE}M94g8N@pdxqvPL(R5e=prh z7jwEvQ0+$VnPpnG=feRe8ZS6e$85a^??AYW*h0i)5Oi!I=gi_Q zmHVYp(lXhWhIdwnECYNgs_Ep1>$KqUU-+a+_$5tyr0j-()*{!J@C2f8KZHLWOMZ>W z4z`*y|Md}4J;Ws^^b&=O-Yb5FA{>Uv2o-S;`D5I}v0qgb}cKHyUbLQLPdSi$L| z&u7@FAqbu_@YN7qN*?#~Vz^Giy>fKZFIP~LQ>dMS1m&D4HGt_`c~OxGxXmm0pqN|V zcFA*G8xKY!%g2|s1SS#!xqUG&6N98MeR#$N=pRuV4Rpuq_|FTNB zSK2a4gjE4weygp1YohR;*-{BWnu}_UT#yUnIpAE@;dF9$Qq9_Ssy4hh3T1bkZW>d_jrb zLm8ONTLv*Jg%O@@6+Mq5jbexw^Bi8F5taJsWht1j;nPGl4uAFD>~I|Ku>Hw^lf4+U zC3*ao8M#j=Fm0q((7y8GbsKD>ucTLKX+6;JZ%v4=BklO(R(_xGmj1272d|KluCOh&g{1W)+1qYtx;L0!0<8i>)Cmt$pR=5`rvI3&_6dni8@cJqbm2q&wDER7( zzJ4IV{*u@=yQO>-jHlLZG!M1INm)F3MZnIHCX3$>IEPHVG!V_KqsDh;{hYut_{%f^ z^wF(dO<06KMUCXQHBdHg1*DH{snr@2b^ASCp{zR?SH#=B zJ6FzLbSKl+@H@CFR}4H?*YcmCGirGVaNWseQig!9INGcAt5IBa8|sC7qbe4q`;@L7 zVOrC7Xc@RthnV0g*wJNL{8Szc?;Q*0btOxTW^DqMb(TdXO;XvTZqt=PicI%QOcFQa zK&r11NRdWKg3vCU2wWn~ttD7=Xx>Uo@yuIkX+mB2$sY4x@f|n$IF|Ho8|S`@1BCt&<#U=gEk*d437(_ZfNoLF}S_wlm132$*7Mh zCX8!}34Mt$6a9188L6qBaaxm?sZJ4206fedN(yq|4Y8zn_vR9c%qyEam&+@%xj$*p zepiyqkd^Dduphh%w@%3@*?74+yTn+lB+zV5NhD<6KLlw^LIX@g#bAM;?vKu27p|Af zdwfJsb3MX81DD?GG*3hx(m_J_Z7z+&qmJtuvU@xJB7@{aI2{tg&uR1>ehq){R`py% zifR1aM}#vW=^_e87t>HQsw6ubhQ?`>2|;`5a1)Yy`W2K6jSC^;pv}gaDSm`Uv`oC9 zFw$Tl?0`=IhX6MT`m6gU;YoviQZ`d literal 5826 zcmb_gU2hsO5ZvcV{U;y zTCKo7eX{Uz=Jd=G^jPLrzGKaE`0qk~swZi$=X_`C^EGTnuU+EV%QyVJQEvoG2HV9P zAxelngwzTM6)^T{|Jv}mC4T`wZJ_TS(mNSF#n4CmGFJDd=kjGNMn)QStzn-DIAe~U z#$jso0`s}LDQtQSC9rbdJ)~;&#|o>Vor&MxDeYM|7+=dBzIW0318Uf#ZMl)+a&Onz z0r9#{m$2EmJ0D=T0oE1bB1X4o*l6@T<7EuJYqe5?jN~F=pmD*yOlytQip(%vna%ui zG+RrTTQ=|r?K?$`H~3JOJJ`bS9cs!9OY5iheg7#>m1C7^=&bn&-59^r@0caKSKN(f zY3gHt0bkQ@j3dT4tCPzc)a(P^aL2^eB8A2kO@U!W1lbP9yO3^_dx9v7tJVlC^!OH9 z+50MHI}M{mqY9dA3pF{EEz#h#TH9rv9JCTGV^7R9_xgw^^I{%eiKau;>MD^{yR3I8 zTcQE8+wR|vi9OP_yJD;OPA><|)^Z6gm}l9E?9jj1?CDu~sO)#AU|8ehdjX%jQ?c=! zGZ(|wh};v+!}bcTaSQ26b0sSeE2X!;z|WC8&TRK(q5BD3_Dl=?8dZ?-$JlES?V+;recb;A zo_raL@fN78!0Z8jby%-^?kNoHyV<*wd!~_Z_i`!LFP+AHqfD+p-r#)P$QyYl zZ{->q@svfo@@(SwUx>7n9%JY+!(+*?r{fvY_3dqome04mI{=S6)!J1eJ#L+c`K|wrexde`9J!!F?lw*hZZik#CH%Sc@U31%ZaJN~E?JW>_WAuEVTP#D&WdvVoge|b{J3NdwW@(-W zXxkYo9%sb}mzcA|yU@Y({@st{R%OrLHNOw`a3as=d5Ml!@E^F+SGQDGj z@)g7=r>!NG1uR|sjm2DZ2P+D1D!ChJx4ak}Y0Y4yG2(OTb*@Bgg9 Date: Tue, 8 Oct 2024 20:44:19 +0000 Subject: [PATCH 121/252] Updated Graph Permissions List --- Tests/QA/Graph.PermissionList.txt | Bin 23238 -> 5826 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Tests/QA/Graph.PermissionList.txt b/Tests/QA/Graph.PermissionList.txt index cf0217fdd80ea178b7d2fcaf254df03117a32835..826113f235a6a0d9238e46bc09b5d42a131a610f 100644 GIT binary patch literal 5826 zcmb_gU2hsO5ZvcV{U;y zTCKo7eX{Uz=Jd=G^jPLrzGKaE`0qk~swZi$=X_`C^EGTnuU+EV%QyVJQEvoG2HV9P zAxelngwzTM6)^T{|Jv}mC4T`wZJ_TS(mNSF#n4CmGFJDd=kjGNMn)QStzn-DIAe~U z#$jso0`s}LDQtQSC9rbdJ)~;&#|o>Vor&MxDeYM|7+=dBzIW0318Uf#ZMl)+a&Onz z0r9#{m$2EmJ0D=T0oE1bB1X4o*l6@T<7EuJYqe5?jN~F=pmD*yOlytQip(%vna%ui zG+RrTTQ=|r?K?$`H~3JOJJ`bS9cs!9OY5iheg7#>m1C7^=&bn&-59^r@0caKSKN(f zY3gHt0bkQ@j3dT4tCPzc)a(P^aL2^eB8A2kO@U!W1lbP9yO3^_dx9v7tJVlC^!OH9 z+50MHI}M{mqY9dA3pF{EEz#h#TH9rv9JCTGV^7R9_xgw^^I{%eiKau;>MD^{yR3I8 zTcQE8+wR|vi9OP_yJD;OPA><|)^Z6gm}l9E?9jj1?CDu~sO)#AU|8ehdjX%jQ?c=! zGZ(|wh};v+!}bcTaSQ26b0sSeE2X!;z|WC8&TRK(q5BD3_Dl=?8dZ?-$JlES?V+;recb;A zo_raL@fN78!0Z8jby%-^?kNoHyV<*wd!~_Z_i`!LFP+AHqfD+p-r#)P$QyYl zZ{->q@svfo@@(SwUx>7n9%JY+!(+*?r{fvY_3dqome04mI{=S6)!J1eJ#L+c`K|wrexde`9J!!F?lw*hZZik#CH%Sc@U31%ZaJN~E?JW>_WAuEVTP#D&WdvVoge|b{J3NdwW@(-W zXxkYo9%sb}mzcA|yU@Y({@st{R%OrLHNOw`a3as=d5Ml!@E^F+SGQDGj z@)g7=r>!NG1uR|sjm2DZ2P+D1D!ChJx4ak}Y0Y4yG2(OTb*@Bgg99LsjBck6QZR<~x=f#mN| z5j_4aJixSOH`ZOt$i=d03Ws|d&G8D9TUva1Z%uW7$uOmu(A3t9BlHjIOr+##uaMm& zOFEP4<+~{z(jySmQ1Xdj`(9p#04u(lzTVfSTJ@$f82GXo7BBsI7)|vw4Ck`lnW8eM zrn?-09?Rj!qQ_+AVDCJEujTuBFn#f0e%3p~EfrhLtZJ0!D!|mwPv@qA>SNzE3cAKx zIT!}KnEtpOyIurmKw&8Uf)=5pOzJ^O_|`O7My4vd{!q5{KTBFtgUs{5eU*M~&coa4 zt;C{J%a!FU+pfJFyYo=2jiKc+EdJ5et!Q1KJ3mc7h}Z=rj0tG7efc8+EzecmeXT3g z1(Dm`o2kx?`O-en7O9HATAsK~*VMbq;>EPsH!|F`oBoXlqFC;BW*D9^7v`OjqHzih zqc&j>)Y=?h(TlhG1d%=US4pdmbz2W(k3Rl1P)pR1mhw2&-k~>!mX?wifik3|;|T`D zE-z`Qek5aZ>g&Oc zXdcY)W9&|7bzf_fLECV7Iyq|9@dTI^&g6n|_5i}3yT&Ysp+2;JEF>s@%QUa{C zdG^0|*ru=-v<+m=V)iesdFZiHX9>1%Wp6guRM4#B8`({nd9q#ZxUx;pp~GO^V~o$I zXETspyOZT|rp=^}wvULeh+}K&2V)}0qvu4dJ8bDrY$Ho`IG-Cq2FNb<3N_X84w$17^xp%NIIvS!{vtaBOS{9i- zMxu^o|3m50ckeiY=$!iu>!@tbeGa1%#ej1zeY-xDYYux4t{W$~WR~2#!wg58=zTae z4s~8YIfko4FlNR)f@LHsmROMqBFmgkSks*=*ps`5df0Vv5%rcJ+-9X_R{>Pp-SK$F z($<_2NRz^+ZO3Qxzr1L}vLRnLhDS^||E=XB7d8B1qGHu|!yumLQ@ii_V>q2UiI$q(4w ziIXINZaI#9{dyi#pG`)B)xJV?RiN{A)Z&@QdoX)=?6HF(n(I~*sK3&dn04zNYllCA>JMobaiBm(mXG#OzV+yiU)yB!R*yZ7+mc~LnEEy&+aEt~(H z5`FG=WfQK)T5ICTp~K>rTd>$l@*1$=)u7E{QyqeU69VUf%Lih8HusuQ?@jt$3A!sb!ERhu)&!2Sv5L9L4LGe=@!r_-mdsSsWiY8SjyCdPr7f>xck~Yim=YH{pz?H` z<|bi(Ax00+G!pgHzINxfO7zu@r4%zweL0UGNt%$%h?t~3y?-Xhu+M)3m ztcVEqdR%M~`2CnlE0YmsGYQ_3;l^Gc-f%9`%3d4XSazY)pAoWa$u{vpj{FhEcu?_( zEBK&>BSK%f8@}lrV#)?%zIUOWSq0{ZlsNc#xCIB7gnOy+d$YUj8uP8|f9$dM)uHvd z&f+xlFjAgw@JCPXtdansJDhS9>#~--Q{n&O1(f{cMc^q|4WZb=r{uq0yT9cK4RcBK zF*xXNahz&=I+CCC_&5FQ8v-LE{oGlOD30V>j(}D>&Mb*Czt~;VF1m#033V?-3@N;g>*dagqU zQ`G9FH%EWN+Fmg3$W+>luGa2DI^8M}Bd0iQ&aX|4utj^Y5iC($k!F|bWC72|f}+)-xXe{@^y+9R(bgZDsu@J=h-*MNN2d50|z)*1O?r=aTzu2%zc}lDw!- zh!@W26Hs~9b&VYK(Cx>6|Ih!hab-2XN|!mpyx5nn>hf|tCNOTwe#DL9UQ$(o&B75# zJEI;#g=TXIB@Xr(Ys*!z(2;A`nG$`SMhojsjXI1shJL#l(gG)NC8Q~Jf_+0jC6J;7 zB*27Q$X^fvJi>jDu}~yZx!?~DWzH5@)5str1X4C)nG1~-x#A(&7*>RLE_ra2B6JcO z)Hti1s*lKELz;e81uG|tP?H-zWW+^8@Uz~!Do@q*)|gGvSI0|~0f`FrXGDYm{B+1g z#0TRpL~aS&NvKVx&!3PdJNE`v3kYY9Q(Zop>ZSW(+OK6(ODJqgbA6IUmk(#!ZBtxE zN;nl6Rk;}IQ(qnpxd{c11B_y{F*HP)rAQ%NRil`W1|($v=w59;jjbtD5-e;D66PSm z!-)tpGKrtT2}{NjPy;Wh?n-WDkx(1YmDORD`zNMx`9Qs$$8x0O8VO1W_=<+%&&jb$ zTx%*Kxze7Z%Qou6lCIn;>gGgno?JDue7K3{hy>tbDIH819-I15zt#;7lbe*9qra+E zo++mmXYV#|-KdUAdr}3cZHu=-cfjU>@$q#gc8yQqiiv!!9V$C;Gww@7PtH3s7ivFT zAqZmrY*n5_{Lmp69?heIoXMp?0MlKRfomzU$hRl6L*?Esu}$1LI6j;mCj;Wv=LhsJ zrabb9-bhcLh0sSOWAW1RUUU%`mPJ(3wHruz8O3z@^@e(_+sJZF=S61P&MpBAMhfRt z+h)Z>km6!BQ|zNHLCdj<>Q`jv`j#{xBr~n3Xz`quf#iB)+UJU_6RnD%lO~&MQqf48 zx5-QOa|`f}VlnWSDcr_8#|p*1aU{W7M35#{XnLRz+Yyzj^QnHLlBp@golIfntXhzN?Q{z8zhTpkus|Caq`qui* zC^yjF;=QP8C2LASr$e;xxTWa?F*vho7*1{`XI&mAmASUPJcSwqUr{Szz3I^zYHl+W zS`fl>fB2Y|%;H-FQ^cowzc=i_t30^yWKoLs{Q5sg(mZnjd{Q;Fox>^tbK$34Txyn$ zlSX`E+w=~(=xRR0&me*w0$Zuaf72}>TmT59vW`3&2`rYSh#B!m*HY+AEqB0V2YED9QUjvy!-%h?&_7^G&T!c|KNV%Ja** zQF7z|qo3vbWgRWwje6d$*-ewj;|0naTmQAO`Lz+rjlxyleVbZ1EWFXY|iNv4ZIhfL&k$k6ls{#HKgEECe%L0vqzE~P?5j&2!0{ihzf51 zjzIKd%)0oT3XE(uy)lWrp%-RIFw&AM?sp`k!HWtiyjPcK!Qm{km6S?*7Mx(x zE(G+{w}%@Z$IWn;$AqXB=!v0^swr$}g%*h|&>3I4Ckm!TPeplfn23_FD@xE(B0aP* zgG*Y7lchoErW^*$V5Ot*2`l0qZF>8lMi*QaZ*U>Ue90Nf;K#OnZK%+W{)Z?UYBMB{ zD%g-$<=;;&+(pGL_pRXhdR4i{;ecmmy!b=>bc;2{WrP$@Ab4CdEwSc!z-B4pzQYBh z7)Ch31ubp|UezM)#0_rW>ivkAsjc}?t_!J?#l{V}trxWXTKD4_X@TS^4iCo+E{L2G zL_J|I#nL3@N*elX4!#`nj*9tMyU@zFx~&lFmlp`qXN81W*mo#Mp(Rbm3^SDQpD{My z>*EP8E|CEtf&w-3*Z`(_t5Hmg$5I!5nz|@4u{(LVakNiDU|uSQkJe_6FiZq|r}w!Y zGfbYi3aUID<*nzWfe0{$UxR&_TA?BJVwS}n=y?t7+*l%vUk0AGt4zsRmH>M&r`}*m znd-aqCUxWug~J{{W7hCCRW4Z(-$%rsjH!469vXVxDiS;pFVfRH6F-H(6;Lh}zWPC? z*jZkjZ&cHgrJ?N@;luoA;JmWe@*aNi8P5=4SWcA8DPC%3WCFFCrbjEQR?s5o+U8OW zs4_-ZGl2vvQRrm{$luHACq1~W`1xjN)v5JNi;lXb0Wu&O`ZUl}B;%>JyAtIdwrgZB zQDcMx6U0q;(K`&vI8SiM|2&sSlH+s?0>13`uU*+!T85tS%(jfFX(sqSJ z6s~)4rRWXGZg3+Tdf-9@6e|t|+M&fQveEB&HX0yb&kb%#r9|!nc#BtUiV9DK>9HDh zH(cgex6kz}cKXF8hOi7J1~Z*prk+Pn`+&2;PzA`4^Fo3kIAJwEvR-xWPkA@%&*BgQ zv@c>%C&q8}y<;Pduh$RP309l+s(877C_YOq7M;2kg8pIHu!=fgBJ;2TQP7mVO|&+ z7vJa%39JE*1Nz7V3<^IByGkgDPxpfCDk<%FALWvXSq|h8;CUs&0PYPbuiF?D)@s-c zG8Ex=vByUuzRTh9y&S%m5NvDC?CpTg%cu2nV_$_`TEj;k6_MWTO;QI+$~QqbHuyu=vf4#k+ZZ!)swa_}=}QO#To% z(ny%IBGT^(xTsrl?Fzhp;;(ZoDoI_#s5krX5JJyZzE}M94g8N@pdxqvPL(R5e=prh z7jwEvQ0+$VnPpnG=feRe8ZS6e$85a^??AYW*h0i)5Oi!I=gi_Q zmHVYp(lXhWhIdwnECYNgs_Ep1>$KqUU-+a+_$5tyr0j-()*{!J@C2f8KZHLWOMZ>W z4z`*y|Md}4J;Ws^^b&=O-Yb5FA{>Uv2o-S;`D5I}v0qgb}cKHyUbLQLPdSi$L| z&u7@FAqbu_@YN7qN*?#~Vz^Giy>fKZFIP~LQ>dMS1m&D4HGt_`c~OxGxXmm0pqN|V zcFA*G8xKY!%g2|s1SS#!xqUG&6N98MeR#$N=pRuV4Rpuq_|FTNB zSK2a4gjE4weygp1YohR;*-{BWnu}_UT#yUnIpAE@;dF9$Qq9_Ssy4hh3T1bkZW>d_jrb zLm8ONTLv*Jg%O@@6+Mq5jbexw^Bi8F5taJsWht1j;nPGl4uAFD>~I|Ku>Hw^lf4+U zC3*ao8M#j=Fm0q((7y8GbsKD>ucTLKX+6;JZ%v4=BklO(R(_xGmj1272d|KluCOh&g{1W)+1qYtx;L0!0<8i>)Cmt$pR=5`rvI3&_6dni8@cJqbm2q&wDER7( zzJ4IV{*u@=yQO>-jHlLZG!M1INm)F3MZnIHCX3$>IEPHVG!V_KqsDh;{hYut_{%f^ z^wF(dO<06KMUCXQHBdHg1*DH{snr@2b^ASCp{zR?SH#=B zJ6FzLbSKl+@H@CFR}4H?*YcmCGirGVaNWseQig!9INGcAt5IBa8|sC7qbe4q`;@L7 zVOrC7Xc@RthnV0g*wJNL{8Szc?;Q*0btOxTW^DqMb(TdXO;XvTZqt=PicI%QOcFQa zK&r11NRdWKg3vCU2wWn~ttD7=Xx>Uo@yuIkX+mB2$sY4x@f|n$IF|Ho8|S`@1BCt&<#U=gEk*d437(_ZfNoLF}S_wlm132$*7Mh zCX8!}34Mt$6a9188L6qBaaxm?sZJ4206fedN(yq|4Y8zn_vR9c%qyEam&+@%xj$*p zepiyqkd^Dduphh%w@%3@*?74+yTn+lB+zV5NhD<6KLlw^LIX@g#bAM;?vKu27p|Af zdwfJsb3MX81DD?GG*3hx(m_J_Z7z+&qmJtuvU@xJB7@{aI2{tg&uR1>ehq){R`py% zifR1aM}#vW=^_e87t>HQsw6ubhQ?`>2|;`5a1)Yy`W2K6jSC^;pv}gaDSm`Uv`oC9 zFw$Tl?0`=IhX6MT`m6gU;YoviQZ`d From 684af2da82fd89b7ca070d4861dd0a79bb5aa4a3 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 8 Oct 2024 17:20:05 -0400 Subject: [PATCH 122/252] AADLifecycleWorkflowSettings - Initial Release --- CHANGELOG.md | 2 + .../MSFT_AADLifecycleWorkflowSettings.psm1 | 368 ++++++++++++++++++ ...FT_AADLifecycleWorkflowSettings.schema.mof | 15 + .../readme.md | 6 + .../settings.json | 28 ++ .../AADLifecycleWorkflowSettings/2-Update.ps1 | 35 ++ ...DSC.AADLifecycleWorkflowSettings.Tests.ps1 | 113 ++++++ Tests/Unit/Stubs/Microsoft365.psm1 | 20 + 8 files changed, 587 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADLifecycleWorkflowSettings/MSFT_AADLifecycleWorkflowSettings.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADLifecycleWorkflowSettings/MSFT_AADLifecycleWorkflowSettings.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADLifecycleWorkflowSettings/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADLifecycleWorkflowSettings/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADLifecycleWorkflowSettings/2-Update.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADLifecycleWorkflowSettings.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index fc43269dc1..a977310eae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ * Initial release. * AADEntitlementManagementSettings * Added support for ApplicationSecret +* AADLifecycleWorkflowSettings + * Initial release. * ADOPermissionGroupSettings * Initial release. * EXOMigrationEndpoint diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADLifecycleWorkflowSettings/MSFT_AADLifecycleWorkflowSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADLifecycleWorkflowSettings/MSFT_AADLifecycleWorkflowSettings.psm1 new file mode 100644 index 0000000000..94f4ab10ca --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADLifecycleWorkflowSettings/MSFT_AADLifecycleWorkflowSettings.psm1 @@ -0,0 +1,368 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $IsSingleInstance, + + [Parameter()] + [System.UInt32] + $WorkflowScheduleIntervalInHours, + + [Parameter()] + [System.String] + $SenderDomain, + + [Parameter()] + [System.Boolean] + $UseCompanyBranding, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters | Out-Null + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + try + { + $instance = Get-MgBetaIdentityGovernanceLifecycleWorkflowSetting -ErrorAction SilentlyContinue + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + IsSingleInstance = 'Yes' + WorkflowScheduleIntervalInHours = $instance.WorkflowScheduleIntervalInHours + SenderDomain = $instance.EmailSettings.SenderDomain + UseCompanyBranding = $instance.EmailSettings.UseCompanyBranding + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $IsSingleInstance, + + [Parameter()] + [System.UInt32] + $WorkflowScheduleIntervalInHours, + + [Parameter()] + [System.String] + $SenderDomain, + + [Parameter()] + [System.Boolean] + $UseCompanyBranding, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $updateSettings = @{ + WorkflowScheduleIntervalInHours = $WorkflowScheduleIntervalInHours + EmailSettings = @{ + SenderDomain = $SenderDomain + UseCompanyBranding = $UseCompanyBranding + } + } + Write-Verbose -Message "Updating the lifecycle workflow settings with payload: $payload" + Update-MgBetaIdentityGovernanceLifecycleWorkflowSetting @updateSettings +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $IsSingleInstance, + + [Parameter()] + [System.UInt32] + $WorkflowScheduleIntervalInHours, + + [Parameter()] + [System.String] + $SenderDomain, + + [Parameter()] + [System.Boolean] + $UseCompanyBranding, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-MgBetaIdentityGovernanceLifecycleWorkflowSetting -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + $displayedKey = $config.Id + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + IsSingleInstance = 'Yes' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADLifecycleWorkflowSettings/MSFT_AADLifecycleWorkflowSettings.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADLifecycleWorkflowSettings/MSFT_AADLifecycleWorkflowSettings.schema.mof new file mode 100644 index 0000000000..aade973744 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADLifecycleWorkflowSettings/MSFT_AADLifecycleWorkflowSettings.schema.mof @@ -0,0 +1,15 @@ +[ClassVersion("1.0.0.0"), FriendlyName("AADLifecycleWorkflowSettings")] +class MSFT_AADLifecycleWorkflowSettings : OMI_BaseResource +{ + [Key, Description("Only valid value is 'Yes'."), ValueMap{"Yes"}, Values{"Yes"}] String IsSingleInstance; + [Write, Description("Specifies the domain that should be used when sending email notifications. This domain must be verified in order to be used. We recommend that you use a domain that has the appropriate DNS records to facilitate email validation, like SPF, DKIM, DMARC, and MX, because this then complies with the RFC compliance for sending and receiving email. For details, see Learn more about Exchange Online Email Routing.")] String SenderDomain; + [Write, Description("The interval in hours at which all workflows running in the tenant should be scheduled for execution. This interval has a minimum value of 1 and a maximum value of 24. The default value is 3 hours.")] UInt32 WorkflowScheduleIntervalInHours; + [Write, Description("Specifies if the organization's banner logo should be included in email notifications. The banner logo will replace the Microsoft logo at the top of the email notification. If true the banner logo will be taken from the tenant's branding settings. This value can only be set to true if the organizationalBranding bannerLogo property is set.")] Boolean UseCompanyBranding; + + [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADLifecycleWorkflowSettings/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_AADLifecycleWorkflowSettings/readme.md new file mode 100644 index 0000000000..747af821a1 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADLifecycleWorkflowSettings/readme.md @@ -0,0 +1,6 @@ + +# AADLifecycleWorkflowSettings + +## Description + +Update the properties of a lifecycleManagementSettings object. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADLifecycleWorkflowSettings/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADLifecycleWorkflowSettings/settings.json new file mode 100644 index 0000000000..ec4851eb0b --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADLifecycleWorkflowSettings/settings.json @@ -0,0 +1,28 @@ +{ + "resourceName": "AADLifecycleWorkflowSettings", + "description": "Update the properties of a lifecycleManagementSettings object.", + "roles": { + "read": [], + "update": [] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [ + { + "name": "LifecycleWorkflows.Read.All" + } + ], + "update": [ + { + "name": "LifecycleWorkflows.ReadWrite.All" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADLifecycleWorkflowSettings/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADLifecycleWorkflowSettings/2-Update.ps1 new file mode 100644 index 0000000000..b6db1874a8 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADLifecycleWorkflowSettings/2-Update.ps1 @@ -0,0 +1,35 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADLifecycleWorkflowSettings "AADLifecycleWorkflowSettings" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + IsSingleInstance = "Yes"; + SenderDomain = "microsoft.com"; + TenantId = $TenantId; + UseCompanyBranding = $True; + WorkflowScheduleIntervalInHours = 10; + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADLifecycleWorkflowSettings.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADLifecycleWorkflowSettings.Tests.ps1 new file mode 100644 index 0000000000..0581150cca --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADLifecycleWorkflowSettings.Tests.ps1 @@ -0,0 +1,113 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -GenericStubModule $GenericStubPath + +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + Mock -CommandName Update-MgBetaIdentityGovernanceLifecycleWorkflowSetting -MockWith { + } + + Mock -CommandName Get-MgBetaIdentityGovernanceLifecycleWorkflowSetting -MockWith { + return @{ + EmailSettings = @{ + SenderDomain = 'contoso.com' + UseCompanyBranding = $True; + } + WorkflowScheduleIntervalInHours = 10; + + } + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + IsSingleInstance = "Yes"; + SenderDomain = "contoso.com"; + UseCompanyBranding = $True; + WorkflowScheduleIntervalInHours = 10; + Credential = $Credential; + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + IsSingleInstance = "Yes"; + SenderDomain = "contoso.com"; + UseCompanyBranding = $True; + WorkflowScheduleIntervalInHours = 11; # Drift + Credential = $Credential; + } + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Update-MgBetaIdentityGovernanceLifecycleWorkflowSetting -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 90905c17b8..9f2c2cb47c 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -94293,6 +94293,26 @@ function Update-MgBetaDeviceManagementWindowsQualityUpdateProfile #endregion +function Update-MgBetaIdentityGovernanceLifecycleWorkflowSetting +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $EmailSettings, + + [Parameter()] + [System.UInt32] + $WorkflowScheduleIntervalInHours + ) +} + +function Get-MgBetaIdentityGovernanceLifecycleWorkflowSetting +{ + [CmdletBinding()] + param() +} + #region MgBetaDeviceManagementWindowsQualityUpdateProfileAssignment function Get-MgBetaDeviceManagementWindowsQualityUpdateProfileAssignment { From 2fceff0c8b603e291bae3ce7a5d36e3bebe4e385 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 8 Oct 2024 17:33:18 -0400 Subject: [PATCH 123/252] Update settings.json --- .../MSFT_AADConnectorGroupApplicationProxy/settings.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/settings.json index 8394b8c68b..aa6b7ca3b9 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConnectorGroupApplicationProxy/settings.json @@ -6,7 +6,7 @@ "delegated": { "read": [ { - "name": "Directory.ReadWrite.All" + "name": "Directory.Read.All" } ], "update": [ @@ -18,7 +18,7 @@ "application": { "read": [ { - "name": "Directory.ReadWrite.All" + "name": "Directory.Read.All" } ], "update": [ From c969360c42902dbb40f255ffa7617dac3660bdc5 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 8 Oct 2024 17:36:56 -0400 Subject: [PATCH 124/252] Permissions --- .../Scheduled - Generate Permission List.yml | 49 ------------------ Tests/QA/Graph.PermissionList.txt | Bin 5826 -> 46478 bytes 2 files changed, 49 deletions(-) delete mode 100644 .github/workflows/Scheduled - Generate Permission List.yml diff --git a/.github/workflows/Scheduled - Generate Permission List.yml b/.github/workflows/Scheduled - Generate Permission List.yml deleted file mode 100644 index 55965360ac..0000000000 --- a/.github/workflows/Scheduled - Generate Permission List.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: Generate Permissions List -on: - push: - branches: - - Master - - Dev - schedule: - - cron: "0 0 * * *" - -jobs: - # This workflow contains a single job called "build" - GeneratePermissionsList: - # The type of runner that the job will run on - runs-on: windows-latest - - permissions: write-all - - # Only when run from the main repo - if: github.repository == 'microsoft/Microsoft365DSC' - # Steps represent a sequence of tasks that will be executed as part of the job - - steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - name: Checkout Repository - uses: actions/checkout@v3 - - - name: Install Dependencies - shell: powershell - run: | - Import-Module './Modules/Microsoft365DSC/Microsoft365DSC.psd1' -Force; - Import-Module './Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1' -Force; - Update-M365DSCModule - - name: Get Permissions List - shell: powershell - run: | - Import-Module './Tests/TestHarness.psm1' -Force; - $permissions = Get-M365DSCAllGraphPermissionsList - $permissions -join ',' | Out-File '.\Tests\QA\Graph.PermissionList.txt' - - name: Commit Permissions List - shell: powershell - run: | - git config --local user.email "nicharl@microsoft.com" - git config --local user.name "NikCharlebois" - git add D:/a/Microsoft365DSC/Microsoft365DSC/Tests/QA/* - git pull - git commit -m "Updated Graph Permissions List" - git push - $SHA = git rev-parse HEAD - echo "commitid=$SHA" >> $env:GITHUB_OUTPUT diff --git a/Tests/QA/Graph.PermissionList.txt b/Tests/QA/Graph.PermissionList.txt index 826113f235a6a0d9238e46bc09b5d42a131a610f..9afee7e857249bba6f9499ddf94ee9a8322165a0 100644 GIT binary patch literal 46478 zcmchgTX!5sZh-qa=j5M^l!u(;ox0gf#5Gr>?Y#L=BqcK@MTQ(%tNroG;wumWsvFf^ zJsjou>`IzJ;a0d63f=R6|NCON8a@plhnK_ca6fE^Gx^uq@N77gKexlBe8#`8hv&mP z`PbQSG5ji@U6t=P!-;%$Q`T(dv-9Cd{(e6EUT|I(oQmad0-s}eJ@B2=fsaq}-=*LI zC;#%5&xZry<$Bl*<8_Ax%gv6kF4Objr{PPXe=)omzIIYtT9ZkI?zTln^zSmR;bjfp zWyvyZ`{TitY2~rC12o ziD$6(R6hSKf5Vb5#CIO#zt6=l&gGL$S#c+@w?gaYaW%g7F#I8_!HH+}!hH!I_+D0i zDYWsS&G1Ta{VAM5*ENo(s?X+UHz2C};DVHZDKcGph=Tf5Wr((03 zMbPih@`-!gv0%KGf1iu=_!*vuEyaAY`IejhrOHkRvI;-I8{f&F_{F7oi(5w2@e*ui zMavZ8DztGkyqEuHFUXR2A}=`b9o^rYw+mUv-d@Q%JWcnJ{Zeg3ZA6*Ytc#qQhaQN> zV#V;SF)!z@4b_L$^mr%IvAcEjiV|H(=C{h^PIyBjm!VoYleOlNIj_e8U1thnPmGI^ z-ZFG9;hpU5%d$`8h}$Z|NBnbeZOrNs?#<7NeG?ssQse+K3sDs=uq`rJtIF`*hMO_& zT#NIN{hT}YxMo~W9SC1{A|tWjQalEaMxIZJT}C{$WO&)1vM1LP(ZKY1!BU{vvnHoV zF2EZ9D7p8h#5>55r%DFXGWxsrg@uhL0N2ac&(R zc_F&e{L_j>OBgh+<$9T4`!~_DW>c*%i1pM{y>gR-@EW2CF?Br;Cxt$dl6*y^Uay4~ z)ve&x*h?043$nWFvYepywK}t`7ms%Qx%eQl#p*R|#-qz;(V+8}ar9J7yK(2W>C`fo zIhw9s%f(UA5%o8jX02Y}*)_he)oW#-4n7m^@wA+WD~YJ&4(ldZ&S_ai&H-8?UlKQo zOaCeVPvw{G+!8E%OP)BF^_B@<2<}_Kt$dR8W4$~FmvJ!0WiYvHHMHh5ix$)RY7Ph0 z^1Vor>xG>4MI=Xmc9wZ75@SVqo%2E<`_|-KarQ-{T5D6|6S3ft6G4m-k>hcee<8VO zJ)X$XT8yuRN3!%&xSHaacuHTD<&m;Gv$VF?bJXu z$k~eXCwn>O2-rj6fp`G~HF6)+55+IYdnR4J&d%OXho`pvq10sPEmEud1=@*HS=itD zTTTF2*;vvV%Jw0*tOy%VuKC_CL%Th;q=E{2X?-H&uNVGj*(baTsbk-Ojs*2S-&jZ4 zZ6tC|maBU>OFXn!wB==Av;E`qn2mfFbFT9mQ*ELC?$=U7-ivhj0hUFa!9wV`Ojoom zBI1ouYbnfY$Fv@ydMWH~1=|uutV7eb^EO-`kGVHRS!?TT(TgkkDKB{#)feY2txulG zxroYvh_3y?yc&Bc)}-r>#h!BAoUw}CbL&M^T+MaEv87JjwoiT8ex&*_@SXlA@ek91vTn5;{FTi#?Q>wuCoo;iBC2*dDW! zch(3b1tA#C#LDyTdT5GR2kFk#gTIa?K6=h&(*IA zZ{zPXOx*tToO0&jGR&_+9ClTF`lB$1v^<$8Rj| zcy!3VoyVVdA2WZftBRGIa2lw-=cJ1kai zQRr)_)aj|}v}7Jr``7ePd?&P+3-epR%$CPA=T@zu`c=A%*npi@^rXVQBXf{g&l+yl zU|Ywf#oBe;Ojq?#wN-CKdhXwQXtvkn6sgNUmmJGUz;3JQ>(dcBd+bLO6X`Y*F>@}S zf@go6al3=Av}bxKu{@WKZ{7pUl%TmUUc_Q9cyEq>iCK z%}KeZ6WZ4OTAXV+W>44IDD$425s>dhyg)0?{Ar=KT+3M2NpdQYkD66`mYkcJS)Ath zHb?Uq)^Ou=vsxVvruR;IcU0d~df0#_|tk=L=OgVRS7O+F~9`^+ARqHf;wAK@2nXo#SOmrzvsgP&?5TDY#l%KRX zVfL?UQ6|J znu}Ww-Zjy;mMoiXH3G3+pfB z{Lj<1==PW5{d5W3rhD+z{M$WgpC?DXJl&_q*_1uw6sFyUKCN=9(c8B-@;7Qdq5}5+ zN6{*}R$FXmj229k_Mq$*`o*)bZ0d(RujCN(*m%P6z2J-UHZda@PJ_d*xTEWV$$B_0 z#~5QDpGM!I=c)A71STc3_uQnbMWAobd9HJ(J=Q`!pBrO`uV&5PAHDHFDB0fbveu_W zcEy4|A4)XPTQs$P^wGmlt%+TwYGc_=z8qh_q|<51@!PH1ySdEq8tl0wSk3$^OU+G|#2{ILG6P_3T^ttl8pPcDiW+wd)3VkAEi&d`az zbMIU#2r7r=r?9l+V;$^TlKtW5>`K-2z3^MlBI3t8@_XL7s5R|H^IpPTaK&BQ4_1#x zbNJT8H?8gViLF=aHC*<|-5&*XH<#f3sWzU4cPm(0H>b^|wVVRE{AAYxf33nw2UR()HvmXi!i0|9=u_D{)7PkFx73JI~e-UrS={TA` z`!*M&{pC~1Nn~ZO79vJF@s6=Lw8!)|Ob^B^BgWg29EVPF;gec-W&O;Y*L5pf)Z;w> zCrsYIbsiau(YNBVw^DNUjKsAzxrtDKVQJkg8f%+!8+5Oq?ml|BqT-1tm= zpMG=r9!hn8O#6HBd4-luMalbd?8*_kW?qg;yH6t-Pc1CFa%I(C%eveCka4$!t&dB6 z0^*|RtIlC9kKtrRy*^#jqUg8YCOKUj&f&ZTuC5$f_A`g0b=Uf(@Nb9WM}6v zGGVgxPSzzHc6MmnpL5XTK@Qy)YaHIXnf|QHYmsm1ow>DqYjEUtKy`R8TBVvG!)~i- zJ*efAgV8H?#nIx3_^_3?%TMRDYN~Cx9P^z>_(A@=6dA1ppFa;C>GZG4snWstZ=p%H zeJ32)1UUBZw@kS|tX-RPuy*>XcV22eHG973nY^R^LFDH)qJDbEy6CxoX5VI9n3s>A zoAl2u`eZi%28BmwbFLPH=i%n~$}#&2Z2yzY|LL#J+<)sCxLq1;=9sjOv*?{!(i}8C zuJg|kirZ&$3VpgWIZZKlVAbLhg}$||UeS6k6qBvXb+m>jx6ScRqwPLSzLz>@R^Kr1 zPxc-<`_N1eo$s$VZ1q|q`2UywYI@&ak2Ssh>hpW(Y=55T_N6%YD|@ZiX@A;wb{GGy zaT}(mL?PEjjk~QA;Fjt%@ ztZzfon`OPXG`tRJb}^OTU^H8|Eq?cvzOQW@OoC9AwWfH+66Nqcl(3k57I;i!44Gs9 zUG&fCd@J=1{WI;N-N>J<+t5?#Y1*0}*gtQ z8^e5t)0u~7x*ki>sB}^0@qEUk9}6?Jbin#nJTH@I^wH5Sv68bK{uQID>E*ff{OEl1 z9Fo1!&i=&-llchs>Zwjyn?0}UxY-#!pXRjV{Z`gh&1fPK{ln}8@05Z1Q+Q|o6f1X+ zB_Elu8T{N^ra80QT(j@MK5)!gk9NUq4kJ5*$JMbm(}<@TkY7+Fiu2nq{Kg>9($G5` zzvm;*(d*Ynp2j*JXQWJ*zX*@?0QtRCo)+NDZT-o)EVOQ2#$^wN_MTv2+DobN_|49; zv<{2yG9#z6Qoi>*!}dw^5#M-{$?~hLg&W=?^icY2I(J>yV);tq1n(l?PjVt2OdPSw zZ2X?}49n+7oBK`ppc2IXxcwo{STAWKG>D~|0l2fnK7ph!%}puKn_#JWSAae6ThDyM zTm$j&TCl5U+dbbD9{kJ}21o6B zSJv}hYczK;{3do<_a@&JC~T^pdDGu0o~~b4t?BQkVp)Hdz5H6T9+6{8@2Qx1vH=<0 zpI^y7*l)K+9;T4`8|i)%l;1P?uR>_m9d9ZQi-zO7ilYCGYhFFSu_yR&KOT$R?e#9b z)1Twp;XQAX`|$;072ZdE#!NA`@*o-|Uf_WnsTQw-z8ymzn|e;Ik!!Pk=v_Xv=c8XFz7TndW%$=c`1Q>mZK0+57ImyogK%D4b7R;;k(qfm^bPS>0W9NHzDsocbT@UsSMn6CLr^2GFu%2W_v)*5a%$^ zBvzNbK|AC4L}01s_|^J*S)0N9QnCaZMZa<8K7(eLiJ3Vr_#<<0X7@Z!UxBAz@(L24 zeqU(olcwmADnO?a#~MJZoaCm@dgk2L`s-QUvk!W%pt?|7q&H0V(;SEfu+v_Sv=fHL ztj7SK<4@!7&019Rb8*y~(I?tcXW>bFcE2#c9wk2#Se_x;9m7jGMI6a`?EFQ+#ZD8) zG-lgbmnwy*kZDV^40rt|6Bf-g0pQ72)HI@2xKDmlY+b8Ltqj?xjXZmZcJw4=CtE!) zQQv6Hq4Ik!lLypARw+6MYjEV4v2?3zpNz_#jRrvK07rNGjxK; zb+&(uYdF(bkV(1@3$ajhBJb%U3h)cr=-($ecE_kEaUu)5vM;Pwy-jDiqQ?-^tVf`~ zX9*Xa2wF3Gb5Oq9o@ukp;BZ8aY3ATm$hqcP&JgkB!M`5LXLJO#I^guE?_jI%4y@`p zln8YoaSD$73=`!(mPw1b@7WPMMUV?VO8v$R8{X_yyxY9Xej>C_3vOW1YovQ7Sf|hU zk0quyu=xI){O!Hy02o_q8D$eb(=(WApvI@wx&Mw{gd}(WAbb)nzZ41SIMO@w6W^Cd zA15*sEjf!@f9P0X$(BsCktJOtale9+lyORUcv-+r5nQ;*U}H1#*AXmc^Q=N2_b&XZBmFElv-_lkba6w%W26@4)j& z7FA-DEmEiY^J( zh+psql5r2(BeyQH&+-<#c;F!jFDOv)1Zu8p2u{l`3S(}H8 zJY?8gzY`DE*u}?($@JP6;8u~GhGovfnGZN0ODn7zGq`vL%08<#0nc&8ly2+SnH@K> z+WkOoPb#xwidr#gYg`c`N=Ggs`%O<4<4G>{@)m5QI)~HXGzzFEQY&gEfoIKbdh(pN z%oe2Uduq*4L>H$;X5!@bTddaXtDS-N?;6A7)3G>@bzaanqEUat8y@&dZ2VrhN0aSRyr|icY718|x>6 zQq9|b9Let7$Y;+Uv%fu?5^c^ojJRLRxwp^e-Uts^8`X&8@?L#y6ItDeXVZICzql-( zlEFp(=D%-Yq-xS<=cq0sXO7$B*AKFf3a3xWSzo}VTmzd?X!k3oQGl9N@95ce^Jk57 z*cvfKtE5=NIj@^?uiuBEu754gZ{)sC&m=?^&Y#39ivjE#l<_7qOQbwrr(9D%bGnc3 zDVx%0!@5SNtJI?Ue?h|gOV0N=<51IM=MLdsyA12xwqfC#Owodv`~3lzU=GT;7{ecm z{SZ0YzfRCz;TD39?6!xu0V0oP=ICwiH+}HVwXf9496f=?S*T6=G-3X!<6Zi`uAu69 ztJaKAl-McFVd8d=-vq(C=wVSgaW2No=H3w>DfPlRM;q~4CU)>@?RQ+3Pl(8F>-0gm zEv|2B9EHOvlhFz+cR?@j)lOq0F#;_iL(QLdZ}RV)BZWfi+sCRE{acmh zI*2mTYg&SL3fW4He6{T&iQ?67^BznKo1e($c?Nd|8{?T(pEXC>s(C5x{f#X-?R$?Q zPI3I5^A~q)4CVavLFHJ9#q}hZap?GcAMQk>KIhBZcd$9{KaKe5QKaH(vA5 z@$?fXVPct{`hO8ir?X65r8ZypR!cI}aYGK+3LiF?G|po&_xiJO+HcSr!p;d^={ntfwcmhg z*Mgq2uZCBrG!N^P#y5vQlsb@^dup9&*B{OvWb%TUA~Jb)*Xf_NYXj$C?mTJQwy7=7 zN7OmzvZq$>z~}T?r^rM5mn8DF&YNQ~3pT5YdN(dlg)?^5&c9RX9rK*j)Rk0?eNPlI z%e4mHc^I#ZQ{Q%0=z)nCe=Qa7nx}Ex*6FkG3^I$kd-=Q0j%)3x_x<=^ zyxqz_jr?&^KNmltUXR^@9vHAM&%f)Lfk`Opaw=kUc`kCzPf4?`H66_^Fk=SK?Wt%m zKnGn#`-DEaT%LlS@*aD!NaTJODG;%v#67E`#>eaRMC+cUH%kvfg~(@i5jpVRgo$Uc z=ijE0=s!gmbfWfT^Ga<9>m|LK z0b_~Kx%C+1{bOq`lLPu=#qY^TOu+aJl*4I8 z;oH|jh2Pg@k}!VHet(iFL?RY-mVXy%&|Cd4`Hq<_-qoge(K_XsednD&dc;!*za4OT z?i*NLeRtx#WKisf-h`OnYfRh<9{MG@Z?$1EYV*_5^bWH=xMR|;ncWJa^QCEFV$AE| P$I0yKX87mfpN4+`rlR0x delta 572 zcmZXSv1=1?6vuy!N6h{FS+3XQyk5iQ+H{Daxr7KABwVl88q<;?P@-)VJXDZ|nkI@4 z9YPcdQlX~(ijzqG0Fh{RDV>}$I7{i|pbnWF9IC%ubr6Tg`@Z)+@O_WpZ|9ruAmRIU zjKk9=tU1ba1!Xae*P@18JG0xRu-jK)QEe!jqMyqew%$qjC>G#e4Wps!2*`0XOO$5| z@n;e`;|x3FF$DKwup0tw2h?uQmnlBkX-v;&QG6Oi|E`Vw2mDJ2 S0dLu#g6thp6#c?kLdkDz2fz;i From cf8ff5db7311eccf46db48f51216d17e1384cec0 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 8 Oct 2024 18:17:29 -0400 Subject: [PATCH 125/252] Update 3-Remove.ps1 --- .../Resources/AADConnectorGroupApplicationProxy/3-Remove.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADConnectorGroupApplicationProxy/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADConnectorGroupApplicationProxy/3-Remove.ps1 index 79c6eefb37..4e38370dc0 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/AADConnectorGroupApplicationProxy/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/AADConnectorGroupApplicationProxy/3-Remove.ps1 @@ -28,6 +28,7 @@ Configuration Example TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint Ensure = "Absent"; + Name = "testgroup-new"; Id = "4984dcf7-d9e9-4663-90b4-5db09f92a669"; } } From c91f1d326d99a7e5b90b84c2b612c0c561ce4959 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 8 Oct 2024 22:40:19 +0000 Subject: [PATCH 126/252] Updated Resources and Cmdlet documentation pages --- .../AADConnectorGroupApplicationProxy.md | 5 +- .../azure-ad/AADLifecycleWorkflowSettings.md | 88 +++++++++++++++++++ 2 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 docs/docs/resources/azure-ad/AADLifecycleWorkflowSettings.md diff --git a/docs/docs/resources/azure-ad/AADConnectorGroupApplicationProxy.md b/docs/docs/resources/azure-ad/AADConnectorGroupApplicationProxy.md index e5968a7f31..fb2b20f1ad 100644 --- a/docs/docs/resources/azure-ad/AADConnectorGroupApplicationProxy.md +++ b/docs/docs/resources/azure-ad/AADConnectorGroupApplicationProxy.md @@ -31,7 +31,7 @@ To authenticate with the Microsoft Graph API, this resource required the followi - **Read** - - Directory.ReadWrite.All + - Directory.Read.All - **Update** @@ -41,7 +41,7 @@ To authenticate with the Microsoft Graph API, this resource required the followi - **Read** - - Directory.ReadWrite.All + - Directory.Read.All - **Update** @@ -157,6 +157,7 @@ Configuration Example TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint Ensure = "Absent"; + Name = "testgroup-new"; Id = "4984dcf7-d9e9-4663-90b4-5db09f92a669"; } } diff --git a/docs/docs/resources/azure-ad/AADLifecycleWorkflowSettings.md b/docs/docs/resources/azure-ad/AADLifecycleWorkflowSettings.md new file mode 100644 index 0000000000..795e0ba97a --- /dev/null +++ b/docs/docs/resources/azure-ad/AADLifecycleWorkflowSettings.md @@ -0,0 +1,88 @@ +# AADLifecycleWorkflowSettings + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **IsSingleInstance** | Key | String | Only valid value is 'Yes'. | `Yes` | +| **SenderDomain** | Write | String | Specifies the domain that should be used when sending email notifications. This domain must be verified in order to be used. We recommend that you use a domain that has the appropriate DNS records to facilitate email validation, like SPF, DKIM, DMARC, and MX, because this then complies with the RFC compliance for sending and receiving email. For details, see Learn more about Exchange Online Email Routing. | | +| **WorkflowScheduleIntervalInHours** | Write | UInt32 | The interval in hours at which all workflows running in the tenant should be scheduled for execution. This interval has a minimum value of 1 and a maximum value of 24. The default value is 3 hours. | | +| **UseCompanyBranding** | Write | Boolean | Specifies if the organization's banner logo should be included in email notifications. The banner logo will replace the Microsoft logo at the top of the email notification. If true the banner logo will be taken from the tenant's branding settings. This value can only be set to true if the organizationalBranding bannerLogo property is set. | | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Update the properties of a lifecycleManagementSettings object. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - LifecycleWorkflows.Read.All + +- **Update** + + - LifecycleWorkflows.ReadWrite.All + +## Examples + +### Example 1 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADLifecycleWorkflowSettings "AADLifecycleWorkflowSettings" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + IsSingleInstance = "Yes"; + SenderDomain = "microsoft.com"; + TenantId = $TenantId; + UseCompanyBranding = $True; + WorkflowScheduleIntervalInHours = 10; + } + } +} +``` + From 8fe24bb617e42bac1dfca2e6db4dadfd54df9ed5 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 8 Oct 2024 22:40:46 +0000 Subject: [PATCH 127/252] Updated {Update} AAD Integration Tests --- .../M365DSCIntegration.AAD.Update.Tests.ps1 | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 index f71bf7eb31..97df9b5436 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 @@ -831,6 +831,16 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + AADLifecycleWorkflowSettings 'AADLifecycleWorkflowSettings' + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + IsSingleInstance = "Yes"; + SenderDomain = "microsoft.com"; + TenantId = $TenantId; + UseCompanyBranding = $True; + WorkflowScheduleIntervalInHours = 10; + } AADNamedLocationPolicy 'CompanyNetwork' { DisplayName = "Company Network" From 44231013196f4f0efbc6ac199bce90a8de45438e Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 8 Oct 2024 22:40:59 +0000 Subject: [PATCH 128/252] Updated {Update} AAD Integration Tests --- .../Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 index 50df775325..611d0c5be0 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 @@ -155,6 +155,7 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint Ensure = "Absent"; + Name = "testgroup-new"; Id = "4984dcf7-d9e9-4663-90b4-5db09f92a669"; } AADCrossTenantAccessPolicyConfigurationPartner 'AADCrossTenantAccessPolicyConfigurationPartner' From b7f663c037cce65582d85c39c2c96a9485efc154 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 8 Oct 2024 22:43:03 +0000 Subject: [PATCH 129/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 7d261a4265..a36dd65ab1 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -4769,6 +4769,61 @@ } ] }, + { + "ClassName": "MSFT_AADLifecycleWorkflowSettings", + "Parameters": [ + { + "CIMType": "String", + "Name": "IsSingleInstance", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "SenderDomain", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "WorkflowScheduleIntervalInHours", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "UseCompanyBranding", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_AADNamedLocationPolicy", "Parameters": [ From fa3ca351635b1c39c58f7444ad1decdf325839cf Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Wed, 9 Oct 2024 12:46:01 +0200 Subject: [PATCH 130/252] Fix Intune MacOS Lob App Examples --- .../Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 | 2 +- .../Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 index 09046e547f..0241cc86d4 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 @@ -31,7 +31,7 @@ Configuration Example Ensure = "Present"; InformationUrl = ""; IsFeatured = $False; - MinimumSupportedOperatingSystem = MinimumSupportedOperatingSystem{ + MinimumSupportedOperatingSystem = MSFT_DeviceManagementMinimumOperatingSystem{ v11_0 = $true } Notes = ""; diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 index 0a7024eb48..0ccab66255 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 @@ -31,7 +31,7 @@ Configuration Example Ensure = "Present"; InformationUrl = ""; IsFeatured = $False; - MinimumSupportedOperatingSystem = MinimumSupportedOperatingSystem{ + MinimumSupportedOperatingSystem = MSFT_DeviceManagementMinimumOperatingSystem{ v11_0 = $true } Notes = ""; From ae36c26a97c1522209c3dd3900521e83116b9e8c Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 9 Oct 2024 10:26:50 -0400 Subject: [PATCH 131/252] AADDomain - Initial Release --- .../MSFT_AADDomain/MSFT_AADDomain.psm1 | 501 ++++++++++++++++++ .../MSFT_AADDomain/MSFT_AADDomain.schema.mof | 22 + .../DSCResources/MSFT_AADDomain/readme.md | 6 + .../DSCResources/MSFT_AADDomain/settings.json | 28 + .../Examples/Resources/AADDomain/1-Create.ps1 | 40 ++ .../Examples/Resources/AADDomain/2-Update.ps1 | 40 ++ .../Examples/Resources/AADDomain/3-Remove.ps1 | 33 ++ .../Modules/M365DSCStubsUtility.psm1 | 87 +-- .../Microsoft365DSC.AADDomain.Tests.ps1 | 229 ++++++++ Tests/Unit/Stubs/Microsoft365.psm1 | 400 ++++++++++++++ 10 files changed, 1355 insertions(+), 31 deletions(-) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADDomain/MSFT_AADDomain.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADDomain/MSFT_AADDomain.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADDomain/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADDomain/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADDomain/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADDomain/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADDomain/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADDomain.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADDomain/MSFT_AADDomain.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDomain/MSFT_AADDomain.psm1 new file mode 100644 index 0000000000..6237de9617 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDomain/MSFT_AADDomain.psm1 @@ -0,0 +1,501 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + [Parameter()] + [System.String] + $AuthenticationType, + + [Parameter()] + [System.String] + $AvailabilityStatus, + + [Parameter()] + [System.Boolean] + $IsAdminManaged, + + [Parameter()] + [System.Boolean] + $IsDefault, + + [Parameter()] + [System.Boolean] + $IsRoot, + + [Parameter()] + [System.Boolean] + $IsVerified, + + [Parameter()] + [System.UInt32] + $PasswordNotificationWindowInDays, + + [Parameter()] + [System.UInt32] + $PasswordValidityPeriodInDays, + + [Parameter()] + [System.String[]] + $SupportedServices, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters | Out-Null + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + try + { + $instance = Get-MgBetaDomain -DomainId $Id -ErrorAction SilentlyContinue + + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + Id = $instance.Id + AuthenticationType = $instance.AuthenticationType + AvailabilityStatus = $instance.AvailabilityStatus + IsAdminManaged = $instance.IsAdminManaged + IsDefault = $instance.IsDefault + IsRoot = $instance.IsRoot + IsVerified = $instance.IsVerified + PasswordNotificationWindowInDays = $instance.PasswordNotificationWindowInDays + PasswordValidityPeriodInDays = $instance.PasswordValidityPeriodInDays + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + [Parameter()] + [System.String] + $AuthenticationType, + + [Parameter()] + [System.String] + $AvailabilityStatus, + + [Parameter()] + [System.Boolean] + $IsAdminManaged, + + [Parameter()] + [System.Boolean] + $IsDefault, + + [Parameter()] + [System.Boolean] + $IsRoot, + + [Parameter()] + [System.Boolean] + $IsVerified, + + [Parameter()] + [System.UInt32] + $PasswordNotificationWindowInDays, + + [Parameter()] + [System.UInt32] + $PasswordValidityPeriodInDays, + + [Parameter()] + [System.String[]] + $SupportedServices, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + $NeedAdditionalUpdate = $false + $UpdatePasswordNotificationWindowInDays = $false + if (-not [System.String]::IsNullOrEmpty('PasswordNotificationWindowInDays')) + { + $NeedAdditionalUpdate = $true + $UpdatePasswordNotificationWindowInDays = $true + $setParameters.Remove('PasswordNotificationWindowInDays') | Out-Null + } + $UpdatePasswordValidityPeriodInDays = $false + if (-not [System.String]::IsNullOrEmpty($PasswordValidityPeriodInDays)) + { + $NeedAdditionalUpdate = $true + $UpdatePasswordValidityPeriodInDays = $true + $setParameters.Remove('PasswordValidityPeriodInDays') | Out-Null + } + + $payload = ConvertTo-Json $setParameters -Depth 10 -Compress + Write-Verbose -Message "Creating new custom domain name {$Id} with payload: `r`n$payload" + $domain = New-MgBetaDomain @setParameters + + if ($NeedAdditionalUpdate) + { + $UpdateParams = @{} + if ($UpdatePasswordNotificationWindowInDays) + { + Write-Verbose -Message "Updating PasswordNotificationWindowInDays for domain {$Id}" + $UpdateParams.Add('PasswordNotificationWindowInDays', $PasswordNotificationWindowInDays) + } + if ($UpdatePasswordValidityPeriodInDays) + { + Write-Verbose -Message "Updating PasswordValidityPeriodInDays for domain {$Id}" + $UpdateParams.Add('PasswordValidityPeriodInDays', $PasswordValidityPeriodInDays) + } + + Update-MgBetaDomain -DomainId $domain.Id @UpdateParams + } + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Updating custom domain name {$Id}" + $setParameters.Add('DomainId', $Id) + $setParameters.Remove('Id') | Out-Null + Update-MgBetaDomain @SetParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Removing custom domain name {$Id}" + Invoke-MgBetaForceDomainDelete -DomainId $Id + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + [Parameter()] + [System.String] + $AuthenticationType, + + [Parameter()] + [System.String] + $AvailabilityStatus, + + [Parameter()] + [System.Boolean] + $IsAdminManaged, + + [Parameter()] + [System.Boolean] + $IsDefault, + + [Parameter()] + [System.Boolean] + $IsRoot, + + [Parameter()] + [System.Boolean] + $IsVerified, + + [Parameter()] + [System.UInt32] + $PasswordNotificationWindowInDays, + + [Parameter()] + [System.UInt32] + $PasswordValidityPeriodInDays, + + [Parameter()] + [System.String[]] + $SupportedServices, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-MgBetaDomain -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + $displayedKey = $config.Id + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + Id = $config.Id + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADDomain/MSFT_AADDomain.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDomain/MSFT_AADDomain.schema.mof new file mode 100644 index 0000000000..3e3cea69f4 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDomain/MSFT_AADDomain.schema.mof @@ -0,0 +1,22 @@ +[ClassVersion("1.0.0.0"), FriendlyName("AADDomain")] +class MSFT_AADDomain : OMI_BaseResource +{ + [Key, Description("")] String Id; + [Write, Description("Indicates the configured authentication type for the domain. The value is either Managed or Federated. Managed indicates a cloud managed domain where Microsoft Entra ID performs user authentication. Federated indicates authentication is federated with an identity provider such as the tenant's on-premises Active Directory via Active Directory Federation Services.")] String AuthenticationType; + [Write, Description("This property is always null except when the verify action is used. When the verify action is used, a domain entity is returned in the response. The availabilityStatus property of the domain entity in the response is either AvailableImmediately or EmailVerifiedDomainTakeoverScheduled.")] String AvailabilityStatus; + [Write, Description("The value of the property is false if the DNS record management of the domain is delegated to Microsoft 365. Otherwise, the value is true. Not nullable")] Boolean IsAdminManaged; + [Write, Description("True if this is the default domain that is used for user creation. There's only one default domain per company. Not nullable.")] Boolean IsDefault; + [Write, Description("True if the domain is a verified root domain. Otherwise, false if the domain is a subdomain or unverified. Not nullable.")] Boolean IsRoot; + [Write, Description("True if the domain completed domain ownership verification. Not nullable.")] Boolean IsVerified; + [Write, Description("Specifies the number of days before a user receives notification that their password expires. If the property isn't set, a default value of 14 days is used.")] UInt32 PasswordNotificationWindowInDays; + [Write, Description("Specifies the length of time that a password is valid before it must be changed. If the property isn't set, a default value of 90 days is used.")] UInt32 PasswordValidityPeriodInDays; + [Write, Description("The capabilities assigned to the domain. Can include 0, 1 or more of following values: Email, Sharepoint, EmailInternalRelayOnly, OfficeCommunicationsOnline, SharePointDefaultDomain, FullRedelegation, SharePointPublic, OrgIdAuthentication, Yammer, Intune. The values that you can add or remove using the API include: Email, OfficeCommunicationsOnline, Yammer. Not nullable.")] String SupportedServices[]; + + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Absent","Present"}, Values{"Absent","Present"}] string Ensure; + [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADDomain/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDomain/readme.md new file mode 100644 index 0000000000..73e2845fc6 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDomain/readme.md @@ -0,0 +1,6 @@ + +# AADDomain + +## Description + +Configures custom domain names in Entra Id. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADDomain/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDomain/settings.json new file mode 100644 index 0000000000..b222367240 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDomain/settings.json @@ -0,0 +1,28 @@ +{ + "resourceName": "AADDomain", + "description": "Configures custom domain names in Entra Id.", + "roles": { + "read": [], + "update": [] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [ + { + "name": "Domain.Read.All" + } + ], + "update": [ + { + "name": "Domain.ReadWrite.All" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADDomain/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADDomain/1-Create.ps1 new file mode 100644 index 0000000000..bf3cef52d4 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADDomain/1-Create.ps1 @@ -0,0 +1,40 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADDomain "AADDomain-Contoso" + { + ApplicationId = $ApplicationId; + AuthenticationType = "Managed"; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Present"; + Id = "contoso.com"; + IsAdminManaged = $True; + IsDefault = $True; + IsRoot = $True; + IsVerified = $True; + PasswordNotificationWindowInDays = 14; + PasswordValidityPeriodInDays = 2147483647; + TenantId = $TenantId; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADDomain/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADDomain/2-Update.ps1 new file mode 100644 index 0000000000..c179744bbb --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADDomain/2-Update.ps1 @@ -0,0 +1,40 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADDomain "AADDomain-Contoso" + { + ApplicationId = $ApplicationId; + AuthenticationType = "Managed"; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Present"; + Id = "contoso.com"; + IsAdminManaged = $True; + IsDefault = $True; + IsRoot = $True; + IsVerified = $False; #Drift + PasswordNotificationWindowInDays = 14; + PasswordValidityPeriodInDays = 2147483647; + TenantId = $TenantId; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADDomain/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADDomain/3-Remove.ps1 new file mode 100644 index 0000000000..9ecf6a71ee --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADDomain/3-Remove.ps1 @@ -0,0 +1,33 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADDomain "AADDomain-Contoso" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Absent"; + Id = "contoso.com"; + TenantId = $TenantId; + } + } +} diff --git a/Modules/Microsoft365DSC/Modules/M365DSCStubsUtility.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCStubsUtility.psm1 index e843fe0807..38047897d1 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCStubsUtility.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCStubsUtility.psm1 @@ -19,7 +19,11 @@ function New-M365DSCStubFiles [Parameter()] [System.Collections.Hashtable[]] - $Workloads + $Workloads, + + [Parameter()] + [String[]] + $CmdletsList ) if ($null -eq $Credential) @@ -75,46 +79,67 @@ function New-M365DSCStubFiles @{Name = 'MicrosoftTeams'; ModuleName = 'MicrosoftTeams'; } ) } + if ($null -ne $CmdletsList -and $CmdletsList.Length -gt 0) + { + $workloads = @{Name = 'MicrosoftGraph'; ModuleName = 'Microsoft.Graph.Authentication'} + } foreach ($Module in $workloads) { - Write-Host "Connecting to {$($Module.Name)}" - $ConnectionMode = New-M365DSCConnection -Workload ($Module.Name) ` - -InboundParameters $PSBoundParameters - - Write-Host "Generating Stubs for {$($Module.ModuleName)}..." - $CurrentModuleName = $Module.ModuleName - - if ($null -eq $CurrentModuleName -or $Module.CommandName) - { - Write-Host "Loading proxy for $($Module.ModuleName)" - $foundModule = Get-Module | Where-Object -FilterScript { $_.ExportedCommands.Values.Name -ccontains $Module.CommandName } - $CurrentModuleName = $foundModule.Name - Import-Module $CurrentModuleName -Force -Global -ErrorAction SilentlyContinue - } - else + if ($null -eq $CmdletsList -or $CmdletsList.Length -eq 0) { - Import-Module $CurrentModuleName -Force -Global -ErrorAction SilentlyContinue - $ConnectionMode = New-M365DSCConnection -Workload $Module.Name ` + Write-Host "Connecting to {$($Module.Name)}" + $ConnectionMode = New-M365DSCConnection -Workload ($Module.Name) ` -InboundParameters $PSBoundParameters - } - $cmdlets = Get-Command -CommandType 'Cmdlet' | Where-Object -FilterScript { $_.Source -eq $CurrentModuleName } - if ($null -eq $cmdlets -or $Module.ModuleName -eq 'MicrosoftTeams') - { - $cmdlets += Get-Command -CommandType 'Function' -Module $CurrentModuleName - } + Write-Host "Generating Stubs for {$($Module.ModuleName)}..." + $CurrentModuleName = $Module.ModuleName - try - { - $aliases = Get-Command -CommandType 'Alias' | Where-Object -FilterScript { $_.Source -eq $CurrentModuleName } - $cmdlets += $aliases - $cmdlets = $cmdlets | Select-Object -Unique + if ($null -eq $CurrentModuleName -or $Module.CommandName) + { + Write-Host "Loading proxy for $($Module.ModuleName)" + $foundModule = Get-Module | Where-Object -FilterScript { $_.ExportedCommands.Values.Name -ccontains $Module.CommandName } + $CurrentModuleName = $foundModule.Name + Import-Module $CurrentModuleName -Force -Global -ErrorAction SilentlyContinue + } + else + { + Import-Module $CurrentModuleName -Force -Global -ErrorAction SilentlyContinue + $ConnectionMode = New-M365DSCConnection -Workload $Module.Name ` + -InboundParameters $PSBoundParameters + } + + $cmdlets = Get-Command -CommandType 'Cmdlet' | Where-Object -FilterScript { $_.Source -eq $CurrentModuleName } + if ($null -eq $cmdlets -or $Module.ModuleName -eq 'MicrosoftTeams') + { + $cmdlets += Get-Command -CommandType 'Function' -Module $CurrentModuleName + } + + try + { + $aliases = Get-Command -CommandType 'Alias' | Where-Object -FilterScript { $_.Source -eq $CurrentModuleName } + $cmdlets += $aliases + $cmdlets = $cmdlets | Select-Object -Unique + } + catch + { + Write-Verbose -Message $_ + } } - catch + else { - Write-Verbose -Message $_ + $cmdlets = @() + foreach ($entry in $CmdletsList) + { + $command = Get-Command $entry -ErrorAction SilentlyContinue + if ($null -ne $command) + { + $CurrentModuleName = $command.ModuleName + $cmdlets += $command + } + } } + $StubContent = [System.Text.StringBuilder]::New() $i = 1 foreach ($cmdlet in $cmdlets) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADDomain.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADDomain.Tests.ps1 new file mode 100644 index 0000000000..c00296242a --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADDomain.Tests.ps1 @@ -0,0 +1,229 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -GenericStubModule $GenericStubPath + +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + Mock -CommandName Invoke-MgBetaForceDomainDelete -MockWith{ + } + + Mock -CommandName New-MgBetaDomain -MockWith { + } + + Mock -CommandName Update-MgBetaDomain -MockWith { + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + Context -Name "The instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + AuthenticationType = "Managed"; + Ensure = "Present"; + Id = "contoso.com"; + IsAdminManaged = $True; + IsDefault = $True; + IsRoot = $True; + IsVerified = $True; + PasswordNotificationWindowInDays = 14; + PasswordValidityPeriodInDays = 2147483647; + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDomain -MockWith { + return $null + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should create a new instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-MgBetaDomain-Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + AuthenticationType = "Managed"; + Ensure = "Absent"; + Id = "contoso.com"; + IsAdminManaged = $True; + IsDefault = $True; + IsRoot = $True; + IsVerified = $True; + PasswordNotificationWindowInDays = 14; + PasswordValidityPeriodInDays = 2147483647; + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDomain -MockWith { + return @{ + Id = "contoso.com"; + IsAdminManaged = $True; + IsDefault = $True; + IsRoot = $True; + IsVerified = $True; + PasswordNotificationWindowInDays = 14; + PasswordValidityPeriodInDays = 2147483647; + } + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should remove the instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-MgBetaDomain -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + AuthenticationType = "Managed"; + Ensure = "Present"; + Id = "contoso.com"; + IsAdminManaged = $True; + IsDefault = $True; + IsRoot = $True; + IsVerified = $True; + PasswordNotificationWindowInDays = 14; + PasswordValidityPeriodInDays = 2147483647; + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDomain -MockWith { + return @{ + Id = "contoso.com"; + IsAdminManaged = $True; + IsDefault = $True; + IsRoot = $True; + IsVerified = $True; + PasswordNotificationWindowInDays = 14; + PasswordValidityPeriodInDays = 2147483647; + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + AuthenticationType = "Managed"; + Ensure = "Present"; + Id = "contoso.com"; + IsAdminManaged = $True; + IsDefault = $True; + IsRoot = $True; + IsVerified = $True; + PasswordNotificationWindowInDays = 14; + PasswordValidityPeriodInDays = 2147483647; + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDomain -MockWith { + return @{ + Id = "contoso.com"; + IsAdminManaged = $True; + IsDefault = $True; + IsRoot = $False; #Drift + IsVerified = $True; + PasswordNotificationWindowInDays = 14; + PasswordValidityPeriodInDays = 2147483647; + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Update-MgBetaDomain -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDomain -MockWith { + return @{ + Id = "contoso.com"; + IsAdminManaged = $True; + IsDefault = $True; + IsRoot = $False; #Drift + IsVerified = $True; + PasswordNotificationWindowInDays = 14; + PasswordValidityPeriodInDays = 2147483647; + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 9f2c2cb47c..c0e87b5d42 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -95533,3 +95533,403 @@ function Update-MgBetaOnPremisePublishingProfileConnectorGroup #endregion +function New-MgBetaDomain +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $SharedEmailDomainInvitations, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $DomainNameReferences, + + [Parameter()] + [PSObject] + $ServiceConfigurationRecords, + + [Parameter()] + [System.String[]] + $SupportedServices, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsInitial, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [PSObject] + $State, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsVerified, + + [Parameter()] + [System.Int32] + $PasswordNotificationWindowInDays, + + [Parameter()] + [PSObject] + $FederationConfiguration, + + [Parameter()] + [System.Int32] + $PasswordValidityPeriodInDays, + + [Parameter()] + [System.String] + $AvailabilityStatus, + + [Parameter()] + [PSObject] + $RootDomain, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [PSObject] + $VerificationDnsRecords, + + [Parameter()] + [System.String] + $AuthenticationType, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsRoot, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsAdminManaged, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsDefault, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Get-MgBetaDomain +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.String] + $DomainId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Update-MgBetaDomain +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $SharedEmailDomainInvitations, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $DomainNameReferences, + + [Parameter()] + [PSObject] + $ServiceConfigurationRecords, + + [Parameter()] + [System.String[]] + $SupportedServices, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsInitial, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [PSObject] + $State, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsVerified, + + [Parameter()] + [System.Int32] + $PasswordNotificationWindowInDays, + + [Parameter()] + [PSObject] + $FederationConfiguration, + + [Parameter()] + [System.Int32] + $PasswordValidityPeriodInDays, + + [Parameter()] + [System.String] + $AvailabilityStatus, + + [Parameter()] + [PSObject] + $RootDomain, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $DomainId, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [PSObject] + $VerificationDnsRecords, + + [Parameter()] + [System.String] + $AuthenticationType, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsRoot, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsAdminManaged, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsDefault, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Invoke-MgBetaForceDomainDelete +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $DisableUserAccounts, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $DomainId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} From 464fd7e1d460529533cee2f5f8878c7f76664717 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 9 Oct 2024 14:27:55 +0000 Subject: [PATCH 132/252] Updated Resources and Cmdlet documentation pages --- .../IntuneAccountProtectionPolicyWindows10.md | 236 ++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 docs/docs/resources/intune/IntuneAccountProtectionPolicyWindows10.md diff --git a/docs/docs/resources/intune/IntuneAccountProtectionPolicyWindows10.md b/docs/docs/resources/intune/IntuneAccountProtectionPolicyWindows10.md new file mode 100644 index 0000000000..b48a438afa --- /dev/null +++ b/docs/docs/resources/intune/IntuneAccountProtectionPolicyWindows10.md @@ -0,0 +1,236 @@ +# IntuneAccountProtectionPolicyWindows10 + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Description** | Write | String | Policy description | | +| **DisplayName** | Key | String | Policy name | | +| **RoleScopeTagIds** | Write | StringArray[] | List of Scope Tags for this Entity instance. | | +| **Id** | Write | String | The unique identifier for an entity. Read-only. | | +| **DeviceSettings** | Write | MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings | The policy settings for the device scope. | | +| **UserSettings** | Write | MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings | The policy settings for the user scope | | +| **Assignments** | Write | MSFT_DeviceManagementConfigurationPolicyAssignments[] | Represents the assignment to the Intune policy. | | +| **Ensure** | Write | String | Present ensures the policy exists, absent ensures it is removed. | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials of the Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **ApplicationSecret** | Write | PSCredential | Secret of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + +### MSFT_DeviceManagementConfigurationPolicyAssignments + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **dataType** | Write | String | The type of the target assignment. | `#microsoft.graph.groupAssignmentTarget`, `#microsoft.graph.allLicensedUsersAssignmentTarget`, `#microsoft.graph.allDevicesAssignmentTarget`, `#microsoft.graph.exclusionGroupAssignmentTarget`, `#microsoft.graph.configurationManagerCollectionAssignmentTarget` | +| **deviceAndAppManagementAssignmentFilterType** | Write | String | The type of filter of the target assignment i.e. Exclude or Include. Possible values are:none, include, exclude. | `none`, `include`, `exclude` | +| **deviceAndAppManagementAssignmentFilterId** | Write | String | The Id of the filter for the target assignment. | | +| **groupId** | Write | String | The group Id that is the target of the assignment. | | +| **groupDisplayName** | Write | String | The group Display Name that is the target of the assignment. | | +| **collectionId** | Write | String | The collection Id that is the target of the assignment.(ConfigMgr) | | + +### MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **LsaCfgFlags** | Write | String | Credential Guard (0: (Disabled) Turns off Credential Guard remotely if configured previously without UEFI Lock., 1: (Enabled with UEFI lock) Turns on Credential Guard with UEFI lock., 2: (Enabled without lock) Turns on Credential Guard without UEFI lock.) | `0`, `1`, `2` | +| **FacialFeaturesUseEnhancedAntiSpoofing** | Write | String | Facial Features Use Enhanced Anti Spoofing (false: Disabled, true: Enabled) | `false`, `true` | +| **EnablePinRecovery** | Write | String | Enable Pin Recovery (false: Disabled, true: Enabled) | `false`, `true` | +| **Expiration** | Write | SInt32 | Expiration | | +| **History** | Write | SInt32 | PIN History | | +| **LowercaseLetters** | Write | String | Lowercase Letters (0: Allows the use of lowercase letters in PIN., 1: Requires the use of at least one lowercase letters in PIN., 2: Does not allow the use of lowercase letters in PIN.) | `0`, `1`, `2` | +| **MaximumPINLength** | Write | SInt32 | Maximum PIN Length | | +| **MinimumPINLength** | Write | SInt32 | Minimum PIN Length | | +| **SpecialCharacters** | Write | String | Special Characters (0: Allows the use of special characters in PIN., 1: Requires the use of at least one special characters in PIN., 2: Does not allow the use of special characters in PIN.) | `0`, `1`, `2` | +| **UppercaseLetters** | Write | String | Uppercase Letters (0: Allows the use of uppercase letters in PIN., 1: Requires the use of at least one uppercase letters in PIN., 2: Does not allow the use of uppercase letters in PIN.) | `0`, `1`, `2` | +| **RequireSecurityDevice** | Write | String | Require Security Device (false: Disabled, true: Enabled) | `false`, `true` | +| **UseCertificateForOnPremAuth** | Write | String | Use Certificate For On Prem Auth (false: Disabled, true: Enabled) | `false`, `true` | +| **UsePassportForWork** | Write | String | Use Windows Hello For Business (Device) (false: Disabled, true: Enabled) | `false`, `true` | + +### MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **EnablePinRecovery** | Write | String | Enable Pin Recovery (User) (false: Disabled, true: Enabled) | `false`, `true` | +| **Expiration** | Write | SInt32 | Expiration (User) | | +| **History** | Write | SInt32 | PIN History (User) | | +| **LowercaseLetters** | Write | String | Lowercase Letters (User) (0: Allows the use of lowercase letters in PIN., 1: Requires the use of at least one lowercase letters in PIN., 2: Does not allow the use of lowercase letters in PIN.) | `0`, `1`, `2` | +| **MaximumPINLength** | Write | SInt32 | Maximum PIN Length (User) | | +| **MinimumPINLength** | Write | SInt32 | Minimum PIN Length (User) | | +| **SpecialCharacters** | Write | String | Special Characters (User) (0: Allows the use of special characters in PIN., 1: Requires the use of at least one special characters in PIN., 2: Does not allow the use of special characters in PIN.) | `0`, `1`, `2` | +| **UppercaseLetters** | Write | String | Uppercase Letters (User) (0: Allows the use of uppercase letters in PIN., 1: Requires the use of at least one uppercase letters in PIN., 2: Does not allow the use of uppercase letters in PIN.) | `0`, `1`, `2` | +| **RequireSecurityDevice** | Write | String | Require Security Device (User) (false: Disabled, true: Enabled) | `false`, `true` | +| **UsePassportForWork** | Write | String | Use Windows Hello For Business (User) (false: Disabled, true: Enabled) | `false`, `true` | + + +## Description + +Intune Account Protection Policy for Windows10 + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - DeviceManagementConfiguration.Read.All + +- **Update** + + - DeviceManagementConfiguration.ReadWrite.All + +#### Application permissions + +- **Read** + + - DeviceManagementConfiguration.Read.All + +- **Update** + + - DeviceManagementConfiguration.ReadWrite.All + +## Examples + +### Example 1 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneAccountProtectionPolicyWindows10 'myAccountProtectionPolicy' + { + DisplayName = 'test' + DeviceSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings + { + History = 10 + EnablePinRecovery = 'true' + } + UserSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings + { + History = 20 + EnablePinRecovery = 'true' + } + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} +``` + +### Example 2 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneAccountProtectionPolicyWindows10 'myAccountProtectionPolicy' + { + DisplayName = 'test' + DeviceSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings + { + History = 10 + EnablePinRecovery = 'true' + } + UserSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings + { + History = 30 # Updated property + EnablePinRecovery = 'true' + } + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} +``` + +### Example 3 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneAccountProtectionPolicyWindows10 'myAccountProtectionPolicy' + { + DisplayName = 'test' + Ensure = 'Absent' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} +``` + From df81054e16af52338adb4d0aeb9200226ecd6b77 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 9 Oct 2024 14:30:57 +0000 Subject: [PATCH 133/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 205 ++++++++++++++++++ 1 file changed, 205 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index a36dd65ab1..886e9fa990 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -19354,6 +19354,211 @@ } ] }, + { + "ClassName": "MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings", + "Parameters": [ + { + "CIMType": "String", + "Name": "LsaCfgFlags", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "FacialFeaturesUseEnhancedAntiSpoofing", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "EnablePinRecovery", + "Option": "Write" + }, + { + "CIMType": "SInt32", + "Name": "Expiration", + "Option": "Write" + }, + { + "CIMType": "SInt32", + "Name": "History", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "LowercaseLetters", + "Option": "Write" + }, + { + "CIMType": "SInt32", + "Name": "MaximumPINLength", + "Option": "Write" + }, + { + "CIMType": "SInt32", + "Name": "MinimumPINLength", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "SpecialCharacters", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "UppercaseLetters", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "RequireSecurityDevice", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "UseCertificateForOnPremAuth", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "UsePassportForWork", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings", + "Parameters": [ + { + "CIMType": "String", + "Name": "EnablePinRecovery", + "Option": "Write" + }, + { + "CIMType": "SInt32", + "Name": "Expiration", + "Option": "Write" + }, + { + "CIMType": "SInt32", + "Name": "History", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "LowercaseLetters", + "Option": "Write" + }, + { + "CIMType": "SInt32", + "Name": "MaximumPINLength", + "Option": "Write" + }, + { + "CIMType": "SInt32", + "Name": "MinimumPINLength", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "SpecialCharacters", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "UppercaseLetters", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "RequireSecurityDevice", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "UsePassportForWork", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_IntuneAccountProtectionPolicyWindows10", + "Parameters": [ + { + "CIMType": "String", + "Name": "Description", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Key" + }, + { + "CIMType": "String[]", + "Name": "RoleScopeTagIds", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Id", + "Option": "Write" + }, + { + "CIMType": "MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings", + "Name": "DeviceSettings", + "Option": "Write" + }, + { + "CIMType": "MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings", + "Name": "UserSettings", + "Option": "Write" + }, + { + "CIMType": "MSFT_DeviceManagementConfigurationPolicyAssignments[]", + "Name": "Assignments", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "ApplicationSecret", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_IntuneAntivirusPolicyWindows10SettingCatalog", "Parameters": [ From b0a5b32ea8c66ae044b1a61c95182a2b6cc522b0 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 9 Oct 2024 14:31:16 +0000 Subject: [PATCH 134/252] Updated {Create} Intune Integration Tests --- .../M365DSCIntegration.INTUNE.Create.Tests.ps1 | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 index e76c7e0a1b..f4c2a0dab7 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 @@ -88,6 +88,24 @@ TenantId = $TenantId; CertificateThumbprint = $CertificateThumbprint; } + IntuneAccountProtectionPolicyWindows10 'myAccountProtectionPolicy' + { + DisplayName = 'test' + DeviceSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings + { + History = 10 + EnablePinRecovery = 'true' + } + UserSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings + { + History = 20 + EnablePinRecovery = 'true' + } + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } IntuneAntivirusPolicyWindows10SettingCatalog 'myAVWindows10Policy' { DisplayName = 'av exclusions' From 4564f2d951763dfc6f2d3db9ea5c79f2bf8ed003 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 9 Oct 2024 10:37:15 -0400 Subject: [PATCH 135/252] Ready for review --- .../Unit/Microsoft365DSC/Microsoft365DSC.AADDomain.Tests.ps1 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADDomain.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADDomain.Tests.ps1 index c00296242a..8ecc01432d 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADDomain.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADDomain.Tests.ps1 @@ -79,7 +79,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should create a new instance from the Set method' { Set-TargetResource @testParams - Should -Invoke -CommandName New-MgBetaDomain-Exactly 1 + Should -Invoke -CommandName New-MgBetaDomain -Exactly 1 } } @@ -119,7 +119,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should remove the instance from the Set method' { Set-TargetResource @testParams - Should -Invoke -CommandName Remove-MgBetaDomain -Exactly 1 + Should -Invoke -CommandName Invoke-MgBetaForceDomainDelete -Exactly 1 } } @@ -141,6 +141,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-MgBetaDomain -MockWith { return @{ Id = "contoso.com"; + AuthenticationType = "Managed"; IsAdminManaged = $True; IsDefault = $True; IsRoot = $True; From 7434a6e020cbda4d759e8d5e279650fde6c326c1 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 9 Oct 2024 10:52:18 -0400 Subject: [PATCH 136/252] Update MSFT_AADDomain.schema.mof --- .../DSCResources/MSFT_AADDomain/MSFT_AADDomain.schema.mof | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADDomain/MSFT_AADDomain.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDomain/MSFT_AADDomain.schema.mof index 3e3cea69f4..bef859a557 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADDomain/MSFT_AADDomain.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADDomain/MSFT_AADDomain.schema.mof @@ -1,7 +1,7 @@ [ClassVersion("1.0.0.0"), FriendlyName("AADDomain")] class MSFT_AADDomain : OMI_BaseResource { - [Key, Description("")] String Id; + [Key, Description("Custom domain name.")] String Id; [Write, Description("Indicates the configured authentication type for the domain. The value is either Managed or Federated. Managed indicates a cloud managed domain where Microsoft Entra ID performs user authentication. Federated indicates authentication is federated with an identity provider such as the tenant's on-premises Active Directory via Active Directory Federation Services.")] String AuthenticationType; [Write, Description("This property is always null except when the verify action is used. When the verify action is used, a domain entity is returned in the response. The availabilityStatus property of the domain entity in the response is either AvailableImmediately or EmailVerifiedDomainTakeoverScheduled.")] String AvailabilityStatus; [Write, Description("The value of the property is false if the DNS record management of the domain is delegated to Microsoft 365. Otherwise, the value is true. Not nullable")] Boolean IsAdminManaged; From 6c738b38365c6074d8207a34ab5be3a48378d081 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 9 Oct 2024 15:07:01 +0000 Subject: [PATCH 137/252] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/azure-ad/AADDomain.md | 179 ++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 docs/docs/resources/azure-ad/AADDomain.md diff --git a/docs/docs/resources/azure-ad/AADDomain.md b/docs/docs/resources/azure-ad/AADDomain.md new file mode 100644 index 0000000000..01a98d0d24 --- /dev/null +++ b/docs/docs/resources/azure-ad/AADDomain.md @@ -0,0 +1,179 @@ +# AADDomain + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Id** | Key | String | Custom domain name. | | +| **AuthenticationType** | Write | String | Indicates the configured authentication type for the domain. The value is either Managed or Federated. Managed indicates a cloud managed domain where Microsoft Entra ID performs user authentication. Federated indicates authentication is federated with an identity provider such as the tenant's on-premises Active Directory via Active Directory Federation Services. | | +| **AvailabilityStatus** | Write | String | This property is always null except when the verify action is used. When the verify action is used, a domain entity is returned in the response. The availabilityStatus property of the domain entity in the response is either AvailableImmediately or EmailVerifiedDomainTakeoverScheduled. | | +| **IsAdminManaged** | Write | Boolean | The value of the property is false if the DNS record management of the domain is delegated to Microsoft 365. Otherwise, the value is true. Not nullable | | +| **IsDefault** | Write | Boolean | True if this is the default domain that is used for user creation. There's only one default domain per company. Not nullable. | | +| **IsRoot** | Write | Boolean | True if the domain is a verified root domain. Otherwise, false if the domain is a subdomain or unverified. Not nullable. | | +| **IsVerified** | Write | Boolean | True if the domain completed domain ownership verification. Not nullable. | | +| **PasswordNotificationWindowInDays** | Write | UInt32 | Specifies the number of days before a user receives notification that their password expires. If the property isn't set, a default value of 14 days is used. | | +| **PasswordValidityPeriodInDays** | Write | UInt32 | Specifies the length of time that a password is valid before it must be changed. If the property isn't set, a default value of 90 days is used. | | +| **SupportedServices** | Write | StringArray[] | The capabilities assigned to the domain. Can include 0, 1 or more of following values: Email, Sharepoint, EmailInternalRelayOnly, OfficeCommunicationsOnline, SharePointDefaultDomain, FullRedelegation, SharePointPublic, OrgIdAuthentication, Yammer, Intune. The values that you can add or remove using the API include: Email, OfficeCommunicationsOnline, Yammer. Not nullable. | | +| **Ensure** | Write | String | Present ensures the instance exists, absent ensures it is removed. | `Absent`, `Present` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Configures custom domain names in Entra Id. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - Domain.Read.All + +- **Update** + + - Domain.ReadWrite.All + +## Examples + +### Example 1 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADDomain "AADDomain-Contoso" + { + ApplicationId = $ApplicationId; + AuthenticationType = "Managed"; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Present"; + Id = "contoso.com"; + IsAdminManaged = $True; + IsDefault = $True; + IsRoot = $True; + IsVerified = $True; + PasswordNotificationWindowInDays = 14; + PasswordValidityPeriodInDays = 2147483647; + TenantId = $TenantId; + } + } +} +``` + +### Example 2 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADDomain "AADDomain-Contoso" + { + ApplicationId = $ApplicationId; + AuthenticationType = "Managed"; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Present"; + Id = "contoso.com"; + IsAdminManaged = $True; + IsDefault = $True; + IsRoot = $True; + IsVerified = $False; #Drift + PasswordNotificationWindowInDays = 14; + PasswordValidityPeriodInDays = 2147483647; + TenantId = $TenantId; + } + } +} +``` + +### Example 3 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADDomain "AADDomain-Contoso" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Absent"; + Id = "contoso.com"; + TenantId = $TenantId; + } + } +} +``` + From 45e913b6fdfa48456edbd42ce58da3ee6e2dcb37 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 9 Oct 2024 15:10:05 +0000 Subject: [PATCH 138/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 886e9fa990..9bfe6fc96c 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -3249,6 +3249,96 @@ } ] }, + { + "ClassName": "MSFT_AADDomain", + "Parameters": [ + { + "CIMType": "String", + "Name": "Id", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "AuthenticationType", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AvailabilityStatus", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "IsAdminManaged", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "IsDefault", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "IsRoot", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "IsVerified", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "PasswordNotificationWindowInDays", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "PasswordValidityPeriodInDays", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "SupportedServices", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_AccessPackageResourceRoleScope", "Parameters": [ From 758a28b5ffff6874c0a65b8bc039c99412d04cd1 Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Wed, 9 Oct 2024 17:26:07 +0200 Subject: [PATCH 139/252] Fix test cases --- .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 16 ++++--- ...5DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 | 43 ++++++++++++++++++- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 index c6699b0e1b..f0e7cd245e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 @@ -165,6 +165,7 @@ function Get-TargetResource $instance = Get-MgBetaDeviceAppManagementMobileApp -MobileAppId $instance.Id ` -ExpandProperty "categories" ` -ErrorAction SilentlyContinue + $Id = $instance.Id } } @@ -204,10 +205,13 @@ function Get-TargetResource } $complexMinimumSupportedOperatingSystem = @{} - $instance.AdditionalProperties.minimumSupportedOperatingSystem.GetEnumerator() | Foreach-Object { - if ($_.Value) # Values are either true or false. Only export the true value. - { - $complexMinimumSupportedOperatingSystem.Add($_.Key, $_.Value) + if ($null -ne $instance.AdditionalProperties.minimumSupportedOperatingSystem) + { + $instance.AdditionalProperties.minimumSupportedOperatingSystem.GetEnumerator() | Foreach-Object { + if ($_.Value) # Values are either true or false. Only export the true value. + { + $complexMinimumSupportedOperatingSystem.Add($_.Key, $_.Value) + } } } @@ -480,7 +484,9 @@ function Set-TargetResource $UpdateParameters.Add('@odata.type', '#microsoft.graph.macOSLobApp') Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id -BodyParameter $UpdateParameters - $delta = Compare-Object -ReferenceObject $currentInstance.Categories.DisplayName -DifferenceObject $Categories.DisplayName -PassThru + [array]$referenceObject = if ($null -ne $currentInstance.Categories.DisplayName) { $currentInstance.Categories.DisplayName } else { ,@() } + [array]$differenceObject = if ($null -ne $Categories.DisplayName) { $Categories.DisplayName } else { ,@() } + $delta = Compare-Object -ReferenceObject $referenceObject -DifferenceObject $differenceObject -PassThru foreach ($diff in $delta) { if ($diff.SideIndicator -eq '=>') diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 index 45eea18922..abfda47b65 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsMacOSLobApp.Tests.ps1 @@ -31,6 +31,12 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Confirm-M365DSCDependencies -MockWith { } + Mock -CommandName Get-PSSession -MockWith { + } + + Mock -CommandName Remove-PSSession -MockWith { + } + Mock -CommandName New-M365DSCConnection -MockWith { return "Credentials" } @@ -59,11 +65,16 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { BeforeAll { $testParams = @{ Id = "8d027f94-0682-431e-97c1-827d1879fa79" + Categories = @() Description = "TeamsForBusinessInstaller" Developer = "Contoso" DisplayName = "TeamsForBusinessInstaller" InformationUrl = "" IsFeatured = $False + MinimumSupportedOperatingSystem = [CimInstance]( + New-CimInstance -ClassName MSFT_DeviceManagementMinimumOperatingSystem -Property @{ + v11_0 = $true + } -ClientOnly) Notes = "" Owner = "" PrivacyInformationUrl = "" @@ -94,18 +105,22 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { BeforeAll { $testParams = @{ Id = "ad027f94-0682-431e-97c1-827d1879fa79" + Categories = @() Description = "TeamsForBusinessInstaller" Developer = "Contoso" DisplayName = "TeamsForBusinessInstaller" InformationUrl = "" IsFeatured = $False + MinimumSupportedOperatingSystem = [CimInstance]( + New-CimInstance -ClassName MSFT_DeviceManagementMinimumOperatingSystem -Property @{ + v11_0 = $true + } -ClientOnly) Notes = "" Owner = "" PrivacyInformationUrl = "" Publisher = "Contoso" RoleScopeTagIds = @() IgnoreVersionDetection = $True - Ensure = 'Absent' Credential = $Credential } @@ -113,6 +128,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { return @{ Id = "ad027f94-0682-431e-97c1-827d1879fa79" + Categories = @() Description = "TeamsForBusinessInstaller" Developer = "Contoso" DisplayName = "TeamsForBusinessInstaller" @@ -127,6 +143,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { IgnoreVersionDetection = $True AdditionalProperties = @{ '@odata.type' = '#microsoft.graph.macOSLobApp' + minimumSupportedOperatingSystem = @{ + v11_0 = $true + } } Ensure = 'Present' } @@ -153,11 +172,16 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { BeforeAll { $testParams = @{ Id = "8d027f94-0682-431e-97c1-827d1879fa79" + Categories = @() Description = "TeamsForBusinessInstaller" Developer = "Contoso" DisplayName = "TeamsForBusinessInstaller" InformationUrl = "" IsFeatured = $False + MinimumSupportedOperatingSystem = [CimInstance]( + New-CimInstance -ClassName MSFT_DeviceManagementMinimumOperatingSystem -Property @{ + v11_0 = $true + } -ClientOnly) Notes = "" Owner = "" PrivacyInformationUrl = "" @@ -170,6 +194,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { return @{ Id = "8d027f94-0682-431e-97c1-827d1879fa79" + Categories = @() Description = "TeamsForBusinessInstaller" Developer = "Contoso" DisplayName = "TeamsForBusinessInstaller" @@ -183,6 +208,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { RoleScopeTagIds = @() AdditionalProperties = @{ '@odata.type' = '#microsoft.graph.macOSLobApp' + minimumSupportedOperatingSystem = @{ + v11_0 = $true + } } } } @@ -200,11 +228,16 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { BeforeAll { $testParams = @{ Id = "8d027f94-0682-431e-97c1-827d1879fa79" + Categories = @() Description = "TeamsForBusinessInstaller" Developer = "Contoso" DisplayName = "TeamsForBusinessInstaller" InformationUrl = "" IsFeatured = $False + MinimumSupportedOperatingSystem = [CimInstance]( + New-CimInstance -ClassName MSFT_DeviceManagementMinimumOperatingSystem -Property @{ + v11_0 = $true + } -ClientOnly) Notes = "" Owner = "" PrivacyInformationUrl = "" @@ -217,6 +250,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { return @{ Id = "8d027f94-0682-431e-97c1-827d1879fa79" + Categories = @() Description = "TeamsForBusinessInstaller" Developer = "Contoso" DisplayName = "TeamsForBusinessInstaller drift" @@ -229,6 +263,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { PublishingState = "published" AdditionalProperties = @{ '@odata.type' = '#microsoft.graph.macOSLobApp' + minimumSupportedOperatingSystem = @{ + v11_0 = $true + } } } } @@ -260,6 +297,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { return @{ Id = "8d027f94-0682-431e-97c1-827d1879fa79" + Categories = @() Description = "TeamsForBusinessInstaller" Developer = "Contoso" DisplayName = "TeamsForBusinessInstaller drift" @@ -273,6 +311,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { RoleScopeTagIds = @() AdditionalProperties = @{ '@odata.type' = '#microsoft.graph.macOSLobApp' + minimumSupportedOperatingSystem = @{ + v11_0 = $true + } } } } From 57a37ba4ded45c32fefaec77bc8b566713790c60 Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Thu, 10 Oct 2024 01:44:12 +0530 Subject: [PATCH 140/252] first commit --- CHANGELOG.md | 2 + ...ADIdentityGovernanceLifecycleWorkflow.psm1 | 724 ++++++++++++++++++ ...tityGovernanceLifecycleWorkflow.schema.mof | 62 ++ .../readme.md | 6 + .../settings.json | 40 + .../1-Create.ps1 | 64 ++ .../2-Update.ps1 | 67 ++ .../3-Remove.ps1 | 64 ++ ...ntityGovernanceLifecycleWorkflow.Tests.ps1 | 240 ++++++ Tests/Unit/Stubs/Microsoft365.psm1 | 560 ++++++++++++++ 10 files changed, 1829 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityGovernanceLifecycleWorkflow/MSFT_AADIdentityGovernanceLifecycleWorkflow.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityGovernanceLifecycleWorkflow/MSFT_AADIdentityGovernanceLifecycleWorkflow.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityGovernanceLifecycleWorkflow/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityGovernanceLifecycleWorkflow/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADIdentityGovernanceLifecycleWorkflow/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADIdentityGovernanceLifecycleWorkflow/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADIdentityGovernanceLifecycleWorkflow/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADIdentityGovernanceLifecycleWorkflow.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b285f71d3..9587dcb3ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ * Initial release. * AADEntitlementManagementSettings * Added support for ApplicationSecret +* AADIdentityGovernanceLifecycleWorkflow + * Initial release. * ADOPermissionGroupSettings * Initial release. * M365DSCDRGUtil diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityGovernanceLifecycleWorkflow/MSFT_AADIdentityGovernanceLifecycleWorkflow.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityGovernanceLifecycleWorkflow/MSFT_AADIdentityGovernanceLifecycleWorkflow.psm1 new file mode 100644 index 0000000000..1e3a213421 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityGovernanceLifecycleWorkflow/MSFT_AADIdentityGovernanceLifecycleWorkflow.psm1 @@ -0,0 +1,724 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $Category, + + [Parameter()] + [System.Boolean] + $IsEnabled, + + [Parameter()] + [System.Boolean] + $IsSchedulingEnabled, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Tasks, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $ExecutionConditions, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters | Out-Null + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + try + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.DisplayName -eq $DisplayName} + } + else + { + $instance = Get-MgBetaIdentityGovernanceLifecycleWorkflow -Filter "DisplayName eq '$DisplayName'" + } + if ($null -eq $instance) + { + return $nullResult + } + + $instance = Get-MgBetaIdentityGovernanceLifecycleWorkflow -WorkflowId $instance.Id + if($null -ne $instance) { + $executionConditionsResults = Get-M365DSCIdentityGovernanceWorkflowExecutionConditions -WorkflowId $instance.Id + $taskResults = Get-M365DSCIdentityGovernanceTasks -WorkflowId $instance.Id + } + + $results = @{ + DisplayName = $DisplayName; + Description = $instance.Description; + Category = $instance.Category; + IsEnabled = $instance.IsEnabled; + IsSchedulingEnabled = $instance.IsSchedulingEnabled; + Tasks = [Array]$taskResults + ExecutionConditions = $executionConditionsResults + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Host -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $Category, + + [Parameter()] + [System.Boolean] + $IsEnabled, + + [Parameter()] + [System.Boolean] + $IsSchedulingEnabled, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Tasks, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $ExecutionConditions, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + if ($null -ne $ExecutionConditions){ + $executionConditionsResult = @{ + Scope = @{ + Rule = $ExecutionConditions.ScopeValue.Rule + "@odata.type" = $ExecutionConditions.ScopeValue.ODataType + } + Trigger = @{ + OffsetInDays = $ExecutionConditions.TriggerValue.OffsetInDays + TimeBasedAttribute = $ExecutionConditions.TriggerValue.TimeBasedAttribute + "@odata.type" = $ExecutionConditions.TriggerValue.ODataType + } + "@odata.type" = $ExecutionConditions.ODataType + } + + $setParameters.Remove('ExecutionConditions') + $setParameters.Add('executionConditions', $executionConditionsResult) + } + + if ($null -ne $Tasks) { + $taskList = @() + + # Loop through each task and create a hashtable + foreach ($task in $Tasks) { + [Array]$argumentsArray = @() + + if ($task.Arguments) { + foreach ($arg in $task.Arguments) { + # Create a hashtable for each argument + $argumentsArray += @{ + Name = $arg.Name.ToString() + Value = $arg.Value.ToString() + } + } + } + $taskHashtable = @{ + DisplayName = $task.DisplayName.ToString() + Description = $task.Description.ToString() + Category = $task.Category.ToString() + IsEnabled = $task.IsEnabled + ExecutionSequence = $task.ExecutionSequence + ContinueOnError = $task.ContinueOnError + TaskDefinitionId = $task.TaskDefinitionId + + # If Arguments exist, populate the hashtable + Arguments = [Array]$argumentsArray + } + + # Add the task hashtable to the task list + $taskList += $taskHashtable + } + + $setParameters.Remove('Tasks') + $setParameters.Add('Tasks', $taskList) + } + + $UpdateParameters = ([Hashtable]$setParameters).clone() + + $newParams = @{} + $newParams.Add('workflow', $UpdateParameters) + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + New-MgBetaIdentityGovernanceLifecycleWorkflow @SetParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + $instance = Get-MgBetaIdentityGovernanceLifecycleWorkflow -Filter "DisplayName eq '$DisplayName'" + $instance = Get-MgBetaIdentityGovernanceLifecycleWorkflow -WorkflowId $instance.Id + + New-MgBetaIdentityGovernanceLifecycleWorkflowNewVersion -WorkflowId $instance.Id -BodyParameter $newParams -ErrorAction Stop + + # the below implementation of Update cmdlet can't be used for updating parameters other than basic parameters like display name, + # description, isEnabled, isSchedulingEnabled. Hence using the new version cmdlet for exhaustive update scenarios. + # Update-MgBetaIdentityGovernanceLifecycleWorkflow @setParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + $instance = Get-MgBetaIdentityGovernanceLifecycleWorkflow -Filter "DisplayName eq '$DisplayName'" + Remove-MgBetaIdentityGovernanceLifecycleWorkflow -WorkflowId $instance.Id + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $Category, + + [Parameter()] + [System.Boolean] + $IsEnabled, + + [Parameter()] + [System.Boolean] + $IsSchedulingEnabled, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Tasks, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $ExecutionConditions, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $testTargetResource = $true + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + #Compare Cim instances + foreach ($key in $PSBoundParameters.Keys) + { + $source = $PSBoundParameters.$key + $target = $CurrentValues.$key + if ($null -ne $source -and $source.GetType().Name -like '*CimInstance*') + { + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + if (-not $testResult) + { + $testTargetResource = $false + } + else { + $ValuesToCheck.Remove($key) | Out-Null + } + } + } + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + + $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys ` + -IncludedDrifts $driftedParams + + if(-not $TestResult) + { + $testTargetResource = $false + } + + Write-Verbose -Message "Test-TargetResource returned $testTargetResource" + + return $testTargetResource +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-MgBetaIdentityGovernanceLifecycleWorkflow -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + $displayedKey = $config.DisplayName + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + DisplayName = $config.DisplayName + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + if ($null -ne $Results.Tasks) + { + $Results.Tasks = Get-M365DSCIdentityGovernanceTasksAsString $Results.Tasks + } + + if ($null -ne $Results.ExecutionConditions) + { + $Results.ExecutionConditions = Get-M365DSCIdentityGovernanceWorkflowExecutionConditionsAsString $Results.ExecutionConditions + } + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + if ($null -ne $Results.Tasks) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock ` + -ParameterName 'Tasks' + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock ` + -ParameterName 'ExecutionConditions' + } + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +function Get-M365DSCIdentityGovernanceTasks +{ + [CmdletBinding()] + [OutputType([Array])] + param( + [Parameter(Mandatory = $true)] + $WorkflowId + ) + + + # Get the tasks from the specified workflow + $tasks = Get-MgBetaIdentityGovernanceLifecycleWorkflowTask -WorkflowId $WorkflowId + + # Initialize an array to hold the hashtables + $taskList = @() + + if($null -eq $tasks) + { + return $taskList + } + + # Loop through each task and create a hashtable + foreach ($task in $tasks) { + [Array]$argumentsArray = @() + + if ($task.Arguments) { + foreach ($arg in $task.Arguments) { + # Create a hashtable for each argument + $argumentsArray += @{ + Name = $arg.Name.ToString() + Value = $arg.Value.ToString() + } + } + } + $taskHashtable = @{ + DisplayName = $task.DisplayName.ToString() + Description = $task.Description.ToString() + Category = $task.Category.ToString() + IsEnabled = $task.IsEnabled + ExecutionSequence = $task.ExecutionSequence + ContinueOnError = $task.ContinueOnError + TaskDefinitionId = $task.TaskDefinitionId + + # If Arguments exist, populate the hashtable + Arguments = [Array]$argumentsArray + } + + # Add the task hashtable to the task list + $taskList += $taskHashtable + } + + return $taskList +} + +function Get-M365DSCIdentityGovernanceTasksAsString +{ + [CmdletBinding()] + [OutputType([System.String])] + param( + [Parameter(Mandatory = $true)] + [System.Collections.ArrayList] + $Tasks + ) + + $StringContent = [System.Text.StringBuilder]::new() + $StringContent.Append('@(') | Out-Null + + foreach ($task in $Tasks) + { + $StringContent.Append("`n MSFT_AADIdentityGovernanceTask {`r`n") | Out-Null + $StringContent.Append(" DisplayName = '" + $task.DisplayName + "'`r`n") | Out-Null + $StringContent.Append(" Description = '" + $task.Description.replace("'","''") + "'`r`n") | Out-Null + $StringContent.Append(" Category = '" + $task.Category + "'`r`n") | Out-Null + $StringContent.Append(" IsEnabled = $" + $task.IsEnabled + "`r`n") | Out-Null + $StringContent.Append(" ExecutionSequence = " + $task.ExecutionSequence + "`r`n") | Out-Null + $StringContent.Append(" ContinueOnError = $" + $task.ContinueOnError + "`r`n") | Out-Null + $StringContent.Append(" TaskDefinitionId = '" + $task.TaskDefinitionId + "'`r`n") | Out-Null + + if ($task.Arguments.Length -gt 0) + { + $StringContent.Append(" Arguments = @(`r`n") | Out-Null + foreach ($argument in $task.Arguments) + { + $StringContent.Append(" MSFT_AADIdentityGovernanceTaskArguments {`r`n") | Out-Null + $StringContent.Append(" Name = '" + $argument.Name + "'`r`n") | Out-Null + $StringContent.Append(" Value = '" + $argument.Value + "'`r`n") | Out-Null + $StringContent.Append(" }`r`n") | Out-Null + } + $StringContent.Append(" )`r`n") | Out-Null + } + else + { + $StringContent.Append(" Arguments = @()`r`n") | Out-Null + } + + $StringContent.Append(" }`r`n") | Out-Null + } + + $StringContent.Append(' )') | Out-Null + return $StringContent.ToString() +} + +function Get-M365DSCIdentityGovernanceWorkflowExecutionConditions +{ + [CmdletBinding()] + [OutputType([Hashtable])] + param( + [Parameter(Mandatory = $true)] + $WorkflowId + ) + + $instance = Get-MgBetaIdentityGovernanceLifecycleWorkflow -WorkflowId $WorkflowId + $executionConditionsResult = @{} + + if($null -ne $instance -and $null -ne $instance.ExecutionConditions){ + $executionConditions = $instance.ExecutionConditions.AdditionalProperties + $executionConditionsResult = @{ + ScopeValue = @{ + Rule = $ExecutionConditions['scope']['rule'] + OdataType = $ExecutionConditions['scope']['@odata.type'] + } + TriggerValue = @{ + OffsetInDays = $ExecutionConditions['trigger']['offsetInDays'] + TimeBasedAttribute = $ExecutionConditions['trigger']['timeBasedAttribute'] + ODataType = $ExecutionConditions['trigger']['@odata.type'] + } + OdataType = $ExecutionConditions['@odata.type'] + } + } + + return $executionConditionsResult +} + +function Get-M365DSCIdentityGovernanceWorkflowExecutionConditionsAsString { + [CmdletBinding()] + [OutputType([System.String])] + param ( + [Parameter(Mandatory = $true)] + [hashtable] $ExecutionConditions + ) + + $StringContent = [System.Text.StringBuilder]::new() + + # Start of execution conditions + $StringContent.Append("MSFT_IdentityGovernanceWorkflowExecutionConditions {`r`n") | Out-Null + + # Scope section + if ($null -ne $ExecutionConditions.ScopeValue) { + $StringContent.Append(" ScopeValue = MSFT_IdentityGovernanceScope {`r`n") | Out-Null + $StringContent.Append(" Rule = '" + $ExecutionConditions.ScopeValue.Rule.replace("'","''") + "'`r`n") | Out-Null + $StringContent.Append(" ODataType = '" + $ExecutionConditions.ScopeValue.ODataType + "'`r`n") | Out-Null + $StringContent.Append(" }`r`n") | Out-Null + } + + # Trigger section + if ($null -ne $ExecutionConditions.TriggerValue) { + $StringContent.Append(" TriggerValue = MSFT_IdentityGovernanceTrigger {`r`n") | Out-Null + $StringContent.Append(" OffsetInDays = " + $ExecutionConditions.TriggerValue.OffsetInDays + "`r`n") | Out-Null + $StringContent.Append(" TimeBasedAttribute = '" + $ExecutionConditions.TriggerValue.TimeBasedAttribute + "'`r`n") | Out-Null + $StringContent.Append(" ODataType = '" + $ExecutionConditions.TriggerValue.OdataType + "'`r`n") | Out-Null + $StringContent.Append(" }`r`n") | Out-Null + } + + # OdataType for executionConditions + if ($null -ne $ExecutionConditions.ODataType) { + $StringContent.Append(" ODataType = '" + $ExecutionConditions.ODataType + "'`r`n") | Out-Null + } + + # End of execution conditions + $StringContent.Append(" }") | Out-Null + + return $StringContent.ToString() +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityGovernanceLifecycleWorkflow/MSFT_AADIdentityGovernanceLifecycleWorkflow.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityGovernanceLifecycleWorkflow/MSFT_AADIdentityGovernanceLifecycleWorkflow.schema.mof new file mode 100644 index 0000000000..6af12f51bb --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityGovernanceLifecycleWorkflow/MSFT_AADIdentityGovernanceLifecycleWorkflow.schema.mof @@ -0,0 +1,62 @@ +[ClassVersion("1.0.0")] +class MSFT_IdentityGovernanceScope +{ + [Write, Description("The @odata.type for the Scope.")] String OdataType; + [Write, Description("The rule associated with the Scope.")] String Rule; +}; + +[ClassVersion("1.0.0")] +class MSFT_IdentityGovernanceTrigger +{ + [Write, Description("The @odata.type for the Trigger.")] String OdataType; + [Write, Description("The time-based attribute for the Trigger.")] String TimeBasedAttribute; + [Write, Description("The offset in days for the Trigger.")] SInt32 OffsetInDays; +}; + +[ClassVersion("1.0.0")] +class MSFT_IdentityGovernanceWorkflowExecutionConditions +{ + [Write, Description("The @odata.type for the Workflow Execution Conditions.")] String OdataType; + [Write, Description("The scope for the Workflow Execution Conditions."), EmbeddedInstance("MSFT_IdentityGovernanceScope")] String ScopeValue; + [Write, Description("The trigger for the Workflow Execution Conditions."), EmbeddedInstance("MSFT_IdentityGovernanceTrigger")] String TriggerValue; +}; + +[ClassVersion("1.0.0")] +class MSFT_AADIdentityGovernanceTaskArguments +{ + [Key, Description("The name of the key")] String Name; + [Write, Description("The value associated with the key")] String Value; +}; + +[ClassVersion("1.0.0")] +class MSFT_AADIdentityGovernanceTask +{ + [Write, Description("Specifies the display name of the Workflow Task")] String DisplayName; + [Write, Description("Description of the Workflow Task")] String Description; + [Write, Description("Category of the Workflow Task")] String Category; + [Write, Description("Indicates if the Workflow Task is enabled or not")] Boolean IsEnabled; + [Write, Description("The sequence in which the task is executed")] SInt32 ExecutionSequence; + [Write, Description("Specifies whether the task should continue on error")] Boolean ContinueOnError; + [Write, Description("ID of the task definition associated with this Workflow Task")] String TaskDefinitionId; + [Write, Description("Arguments for the Workflow Task"), EmbeddedInstance("MSFT_AADIdentityGovernanceTaskArguments")] String Arguments[]; +}; + +[ClassVersion("1.0.0.0"), FriendlyName("AADIdentityGovernanceLifecycleWorkflow")] +class MSFT_AADIdentityGovernanceLifecycleWorkflow : OMI_BaseResource +{ + [Key, Description("Specifies the Display Name of the Workflow")] String DisplayName; + [Write, Description("Description of the Workflow")] String Description; + [Write, Description("Category of the Workflow")] String Category; + [Write, Description("Indicates if the Workflow is enabled")] Boolean IsEnabled; + [Write, Description("Indicates if scheduling is enabled for the Workflow")] Boolean IsSchedulingEnabled; + [Write, Description("Tasks associated with this workflow"), EmbeddedInstance("MSFT_AADIdentityGovernanceTask")] String Tasks[]; + [Write, Description("ExecutionConditions for this workflow"), EmbeddedInstance("MSFT_IdentityGovernanceWorkflowExecutionConditions")] String ExecutionConditions; + + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Absent","Present"}, Values{"Absent","Present"}] string Ensure; + [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityGovernanceLifecycleWorkflow/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityGovernanceLifecycleWorkflow/readme.md new file mode 100644 index 0000000000..37e7f8f0ac --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityGovernanceLifecycleWorkflow/readme.md @@ -0,0 +1,6 @@ + +# AADIdentityGovernanceLifecycleWorkflow + +## Description + +Use this resource to manage Lifecycle workflows. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityGovernanceLifecycleWorkflow/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityGovernanceLifecycleWorkflow/settings.json new file mode 100644 index 0000000000..927836ff9b --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityGovernanceLifecycleWorkflow/settings.json @@ -0,0 +1,40 @@ +{ + "resourceName": "AADIdentityGovernanceLifecycleWorkflow", + "description": "Use this resource to manage Lifecycle workflows.", + "roles": { + "read": [ + "Security Reader" + ], + "update": [ + "Security Administrator" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [ + { + "name": "LifecycleWorkflows.Read.All" + } + ], + "update": [ + { + "name": "LifecycleWorkflows.ReadWrite.All" + } + ] + }, + "application": { + "read": [ + { + "name": "LifecycleWorkflows.Read.All" + } + ], + "update": [ + { + "name": "LifecycleWorkflows.ReadWrite.All" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADIdentityGovernanceLifecycleWorkflow/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADIdentityGovernanceLifecycleWorkflow/1-Create.ps1 new file mode 100644 index 0000000000..201fdda338 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADIdentityGovernanceLifecycleWorkflow/1-Create.ps1 @@ -0,0 +1,64 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADIdentityGovernanceLifecycleWorkflow "AADIdentityGovernanceLifecycleWorkflow-Onboard pre-hire employee updated version" + { + Category = "joiner"; + Credential = $Credscredential; + Description = "Description the onboard of prehire employee"; + DisplayName = "Onboard pre-hire employee updated version"; + Ensure = "Present"; + ExecutionConditions = MSFT_IdentityGovernanceWorkflowExecutionConditions { + ScopeValue = MSFT_IdentityGovernanceScope { + Rule = '(not (country eq ''Brazil''))' + ODataType = '#microsoft.graph.identityGovernance.ruleBasedSubjectSet' + } + TriggerValue = MSFT_IdentityGovernanceTrigger { + OffsetInDays = 4 + TimeBasedAttribute = 'employeeHireDate' + ODataType = '#microsoft.graph.identityGovernance.timeBasedAttributeTrigger' + } + ODataType = '#microsoft.graph.identityGovernance.triggerAndScopeBasedConditions' + }; + IsEnabled = $True; + IsSchedulingEnabled = $False; + Tasks = @( + MSFT_AADIdentityGovernanceTask { + DisplayName = 'Add user to groups' + Description = 'Add user to selected groups' + Category = 'joiner,leaver,mover' + IsEnabled = $True + ExecutionSequence = 1 + ContinueOnError = $True + TaskDefinitionId = '22085229-5809-45e8-97fd-270d28d66910' + Arguments = @( + MSFT_AADIdentityGovernanceTaskArguments { + Name = 'groupID' + Value = '7ad01e00-8c3a-42a6-baaf-39f2390b2565' + } + ) + } + ); + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADIdentityGovernanceLifecycleWorkflow/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADIdentityGovernanceLifecycleWorkflow/2-Update.ps1 new file mode 100644 index 0000000000..1ed9701969 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADIdentityGovernanceLifecycleWorkflow/2-Update.ps1 @@ -0,0 +1,67 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADIdentityGovernanceLifecycleWorkflow "AADIdentityGovernanceLifecycleWorkflow-Onboard pre-hire employee updated version" + { + Category = "joiner"; + Credential = $Credscredential; + #updated description + Description = "Updated description the onboard of prehire employee"; + DisplayName = "Onboard pre-hire employee updated version"; + Ensure = "Present"; + ExecutionConditions = MSFT_IdentityGovernanceWorkflowExecutionConditions { + ScopeValue = MSFT_IdentityGovernanceScope { + #updated rule + Rule = '(not (country eq ''America''))' + ODataType = '#microsoft.graph.identityGovernance.ruleBasedSubjectSet' + } + TriggerValue = MSFT_IdentityGovernanceTrigger { + OffsetInDays = 4 + TimeBasedAttribute = 'employeeHireDate' + ODataType = '#microsoft.graph.identityGovernance.timeBasedAttributeTrigger' + } + ODataType = '#microsoft.graph.identityGovernance.triggerAndScopeBasedConditions' + }; + IsEnabled = $True; + IsSchedulingEnabled = $False; + Tasks = @( + MSFT_AADIdentityGovernanceTask { + DisplayName = 'Add user to groups' + #updated description + Description = 'Add user to selected groups updated' + Category = 'joiner,leaver,mover' + IsEnabled = $True + ExecutionSequence = 1 + ContinueOnError = $True + TaskDefinitionId = '22085229-5809-45e8-97fd-270d28d66910' + Arguments = @( + MSFT_AADIdentityGovernanceTaskArguments { + Name = 'groupID' + Value = '7ad01e00-8c3a-42a6-baaf-39f2390b2565' + } + ) + } + ); + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADIdentityGovernanceLifecycleWorkflow/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADIdentityGovernanceLifecycleWorkflow/3-Remove.ps1 new file mode 100644 index 0000000000..fa2840fe12 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADIdentityGovernanceLifecycleWorkflow/3-Remove.ps1 @@ -0,0 +1,64 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADIdentityGovernanceLifecycleWorkflow "AADIdentityGovernanceLifecycleWorkflow-Onboard pre-hire employee updated version" + { + Category = "joiner"; + Credential = $Credscredential; + Description = "Updated description the onboard of prehire employee"; + DisplayName = "Onboard pre-hire employee updated version"; + Ensure = "Absent"; + ExecutionConditions = MSFT_IdentityGovernanceWorkflowExecutionConditions { + ScopeValue = MSFT_IdentityGovernanceScope { + Rule = '(not (country eq ''America''))' + ODataType = '#microsoft.graph.identityGovernance.ruleBasedSubjectSet' + } + TriggerValue = MSFT_IdentityGovernanceTrigger { + OffsetInDays = 4 + TimeBasedAttribute = 'employeeHireDate' + ODataType = '#microsoft.graph.identityGovernance.timeBasedAttributeTrigger' + } + ODataType = '#microsoft.graph.identityGovernance.triggerAndScopeBasedConditions' + }; + IsEnabled = $True; + IsSchedulingEnabled = $False; + Tasks = @( + MSFT_AADIdentityGovernanceTask { + DisplayName = 'Add user to groups' + Description = 'Add user to selected groups updated' + Category = 'joiner,leaver,mover' + IsEnabled = $True + ExecutionSequence = 1 + ContinueOnError = $True + TaskDefinitionId = '22085229-5809-45e8-97fd-270d28d66910' + Arguments = @( + MSFT_AADIdentityGovernanceTaskArguments { + Name = 'groupID' + Value = '7ad01e00-8c3a-42a6-baaf-39f2390b2565' + } + ) + } + ); + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADIdentityGovernanceLifecycleWorkflow.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADIdentityGovernanceLifecycleWorkflow.Tests.ps1 new file mode 100644 index 0000000000..98152b6d9f --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADIdentityGovernanceLifecycleWorkflow.Tests.ps1 @@ -0,0 +1,240 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -GenericStubModule $GenericStubPath + +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + Mock -CommandName Update-MgBetaIdentityGovernanceLifecycleWorkflow -MockWith { + } + + Mock -CommandName Remove-MgBetaIdentityGovernanceLifecycleWorkflow -MockWith { + } + + Mock -CommandName New-MgBetaIdentityGovernanceLifecycleWorkflow -MockWith { + } + + Mock -CommandName New-MgBetaIdentityGovernanceLifecycleWorkflowNewVersion -MockWith { + } + + Mock -CommandName Get-MgBetaIdentityGovernanceLifecycleWorkflow -MockWith { + } + + Mock -CommandName Get-MgBetaIdentityGovernanceLifecycleWorkflowTask -MockWith { + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + Context -Name "The instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + Category = "joiner"; + Description = "Description the onboard of prehire employee"; + DisplayName = "Onboard pre-hire employee updated version"; + IsEnabled = $True; + IsSchedulingEnabled = $False; + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-MgBetaIdentityGovernanceLifecycleWorkflow to return $null + Mock -CommandName Get-MgBetaIdentityGovernanceLifecycleWorkflow -MockWith { + return $null + } + Mock -CommandName Get-MgBetaIdentityGovernanceLifecycleWorkflowTask -MockWith { + return $null + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should create a new instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-MgBetaIdentityGovernanceLifecycleWorkflow -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + Category = "joiner"; + Description = "Description the onboard of prehire employee"; + DisplayName = "Onboard pre-hire employee updated version"; + IsEnabled = $True; + IsSchedulingEnabled = $False; + Ensure = 'Absent' + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaIdentityGovernanceLifecycleWorkflow -MockWith { + return @{ + Id = "random guid" + Category = "joiner"; + Description = "Description the onboard of prehire employee"; + DisplayName = "Onboard pre-hire employee updated version"; + IsEnabled = $True; + IsSchedulingEnabled = $False; + } + } + Mock -CommandName Get-MgBetaIdentityGovernanceLifecycleWorkflowTask -MockWith { + return $null + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should remove the instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-MgBetaIdentityGovernanceLifecycleWorkflow -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Category = "joiner"; + Description = "Description the onboard of prehire employee"; + DisplayName = "Onboard pre-hire employee updated version"; + IsEnabled = $True; + IsSchedulingEnabled = $False; + Tasks = $null + ExecutionConditions = (New-CimInstance -ClassName MSFT_IdentityGovernanceWorkflowExecutionConditions -Property @{ + } -ClientOnly) + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaIdentityGovernanceLifecycleWorkflow -MockWith { + return @{ + Id = "random guid" + Category = "joiner"; + Description = "Description the onboard of prehire employee"; + DisplayName = "Onboard pre-hire employee updated version"; + IsEnabled = $True; + IsSchedulingEnabled = $False; + } + } + Mock -CommandName Get-MgBetaIdentityGovernanceLifecycleWorkflowTask -MockWith { + return $null + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Category = "joiner"; + Description = "Description the onboard of prehire employee"; + DisplayName = "Onboard pre-hire employee updated version"; + IsEnabled = $True; + IsSchedulingEnabled = $False; + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaIdentityGovernanceLifecycleWorkflow -MockWith { + return @{ + Id = "random guid" + Category = "joiner"; + Description = "Drifted Description the onboard of prehire employee"; + DisplayName = "Onboard pre-hire employee updated version"; + IsEnabled = $True; + IsSchedulingEnabled = $False; + } + } + Mock -CommandName Get-MgBetaIdentityGovernanceLifecycleWorkflowTask -MockWith { + return $null + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-MgBetaIdentityGovernanceLifecycleWorkflowNewVersion -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaIdentityGovernanceLifecycleWorkflow -MockWith { + return @{ + Category = "joiner"; + Description = "Description the onboard of prehire employee"; + DisplayName = "Onboard pre-hire employee updated version"; + IsEnabled = $True; + IsSchedulingEnabled = $False; + } + } + Mock -CommandName Get-MgBetaIdentityGovernanceLifecycleWorkflowTask -MockWith { + return $null + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index bbc1300dac..37f917d882 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -30578,6 +30578,566 @@ function Get-MgBetaEntitlementManagementConnectedOrganizationInternalSponsor $HttpPipelineAppend ) } + +function Get-MgBetaIdentityGovernanceLifecycleWorkflow +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $WorkflowId, + + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Get-MgBetaIdentityGovernanceLifecycleWorkflowTask +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $WorkflowId, + + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [System.String] + $TaskId, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function New-MgBetaIdentityGovernanceLifecycleWorkflow +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.DateTime] + $LastModifiedDateTime, + + [Parameter()] + [System.DateTime] + $CreatedDateTime, + + [Parameter()] + [PSObject] + $TaskReports, + + [Parameter()] + [System.DateTime] + $NextScheduleRunDateTime, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Collections.Hashtable] + $ExecutionConditions, + + [Parameter()] + [PSObject] + $Runs, + + [Parameter()] + [PSObject] + $Versions, + + [Parameter()] + [System.Int32] + $Version, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [PSObject] + $UserProcessingResults, + + [Parameter()] + [PSObject] + $CreatedBy, + + [Parameter()] + [PSObject] + $ExecutionScope, + + [Parameter()] + [System.String] + $Category, + + [Parameter()] + [PSObject] + $LastModifiedBy, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $Tasks, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsSchedulingEnabled, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.DateTime] + $DeletedDateTime, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsEnabled, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function New-MgBetaIdentityGovernanceLifecycleWorkflowNewVersion +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $WorkflowId, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [PSObject] + $Workflow, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} +function Remove-MgBetaIdentityGovernanceLifecycleWorkflow +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.String] + $IfMatch, + + [Parameter()] + [System.String] + $WorkflowId, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} + +function Update-MgBetaIdentityGovernanceLifecycleWorkflow +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.DateTime] + $LastModifiedDateTime, + + [Parameter()] + [System.String] + $WorkflowId, + + [Parameter()] + [System.DateTime] + $CreatedDateTime, + + [Parameter()] + [PSObject] + $TaskReports, + + [Parameter()] + [System.DateTime] + $NextScheduleRunDateTime, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Collections.Hashtable] + $ExecutionConditions, + + [Parameter()] + [PSObject] + $Runs, + + [Parameter()] + [PSObject] + $Versions, + + [Parameter()] + [System.Int32] + $Version, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [PSObject] + $UserProcessingResults, + + [Parameter()] + [PSObject] + $CreatedBy, + + [Parameter()] + [PSObject] + $ExecutionScope, + + [Parameter()] + [System.String] + $Category, + + [Parameter()] + [PSObject] + $LastModifiedBy, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $Tasks, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsSchedulingEnabled, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.DateTime] + $DeletedDateTime, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsEnabled, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} function Get-MgBetaRoleManagementDirectory { [CmdletBinding()] From b4e8783c08802f16e4c588f7bb9d2ce1989d0df2 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 9 Oct 2024 17:04:36 -0400 Subject: [PATCH 141/252] Added Support for Application Template --- CHANGELOG.md | 1 + .../MSFT_AADApplication.psm1 | 69 ++++++++++++++++--- .../MSFT_AADApplication.schema.mof | 1 + 3 files changed, 62 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8275a583fb..ad6175a1d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * AADApplication * Fixed an issue trying to retrieve the beta instance. * Added support for OnPremisesPublishing. + * Added support for ApplicationTemplate. * AADAuthenticationRequirement * Initial release. * AADConnectorGroupApplicationProxy diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index e2834628f8..426d13a171 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -92,6 +92,10 @@ function Get-TargetResource [Microsoft.Management.Infrastructure.CimInstance] $OnPremisesPublishing, + [Parameter()] + [System.String] + $ApplicationTemplateId, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -157,7 +161,7 @@ function Get-TargetResource } else { - $AADApp = Get-MgApplication -Filter "AppId eq '$AppId'" + $AADApp = Get-MgBetaApplication -Filter "AppId eq '$AppId'" } } } @@ -176,7 +180,7 @@ function Get-TargetResource } else { - $AADApp = Get-MgApplication -Filter "DisplayName eq '$($DisplayName)'" + $AADApp = Get-MgBetaApplication -Filter "DisplayName eq '$($DisplayName)'" } } if ($null -ne $AADApp -and $AADApp.Count -gt 1) @@ -192,8 +196,7 @@ function Get-TargetResource { Write-Verbose -Message 'An instance of Azure AD App was retrieved.' - - $AADBetaApp= Get-MgBetaApplication -Property "id,displayName,appId,authenticationBehaviors" -ApplicationId $AADApp.Id -ErrorAction SilentlyContinue + $AADBetaApp= Get-MgBetaApplication -Property "id,displayName,appId,authenticationBehaviors,additionalProperties" -ApplicationId $AADApp.Id -ErrorAction SilentlyContinue $AADAppKeyCredentials = Get-MgApplication -Property "keyCredentials" -ApplicationId $AADApp.Id -ErrorAction SilentlyContinue $complexAuthenticationBehaviors = @{} @@ -475,7 +478,8 @@ function Get-TargetResource PasswordCredentials = $complexPasswordCredentials AppRoles = $complexAppRoles Permissions = $permissionsObj - OnPremisesPublishing = $onPremisesPublishingValue + OnPremisesPublishing = $onPremisesPublishingValue + ApplicationTemplateId = $AADApp.AdditionalProperties.applicationTemplateId Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId @@ -601,6 +605,10 @@ function Set-TargetResource [Microsoft.Management.Infrastructure.CimInstance] $OnPremisesPublishing, + [Parameter()] + [System.String] + $ApplicationTemplateId, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -806,10 +814,43 @@ function Set-TargetResource Write-Verbose -Message "Multiple instances of a deleted application with name {$DisplayName} wehre found. Creating a new instance since we can't determine what instance to restore." } } + + # Create from Template + $createdFromTemplate = $false + if ($Ensure -eq 'Present' -and $currentAADApp.Ensure -eq 'Absent' -and -not $skipToUpdate -and ` + $ApplicationTemplateId -ne '8adf8e6e-67b2-4cf2-a259-e3dc5476c621') + { + $skipToUpdate = $true + Write-Verbose -Message "Creating application {$DisplayName} from Application Template {$ApplicationTemplateId}" + $newApp = Invoke-MgBetaInstantiateApplicationTemplate -DisplayName $DisplayName ` + -ApplicationTemplateId $ApplicationTemplateId + $currentAADApp = @{ + AppId = $newApp.Application.AppId + Id = $newApp.Application.AppId + DisplayName = $newApp.Application.DisplayName + ObjectId = $newApp.Application.AdditionalProperties.objectId + } + + $createdFromTemplate = $true + + do + { + Write-Verbose -Message 'Waiting for 10 seconds' + Start-Sleep -Seconds 10 + $appEntity = Get-MgApplication -ApplicationId $currentAADApp.AppId -ErrorAction SilentlyContinue + $tries++ + } until ($null -eq $appEntity -or $tries -le 12) + } + Write-Host "Ensure = $Ensure" + Write-Host "ApplicationTemplateId = $ApplicationTemplateId" + Write-Host "skipToUpdate = $skipToUpdate" + Write-Host "currentAADApp.Ensure = $($currentAADApp.Ensure))" if ($Ensure -eq 'Present' -and $currentAADApp.Ensure -eq 'Absent' -and -not $skipToUpdate) { - Write-Verbose -Message "Creating New AzureAD Application {$DisplayName} with values:`r`n$($currentParameters | Out-String)" $currentParameters.Remove('ObjectId') | Out-Null + $currentParameters.Remove('ApplicationTemplateId') | Out-Null + Write-Verbose -Message "Creating New AzureAD Application {$DisplayName} with values:`r`n$($currentParameters | Out-String)" + $currentAADApp = New-MgApplication @currentParameters Write-Verbose -Message "Azure AD Application {$DisplayName} was successfully created" $needToUpdatePermissions = $true @@ -831,15 +872,21 @@ function Set-TargetResource elseif (($Ensure -eq 'Present' -and $currentAADApp.Ensure -eq 'Present') -or $skipToUpdate) { $currentParameters.Remove('ObjectId') | Out-Null + $currentParameters.Remove('ApplicationTemplateId') | Out-Null - if (-not $skipToUpdate) + if (-not $skipToUpdate -or $createdFromTemplate) { $AppIdValue = $currentAADApp.ObjectId } + $currentParameters.Add('ApplicationId', $AppIdValue) Write-Verbose -Message "Updating existing AzureAD Application {$DisplayName} with values:`r`n$($currentParameters | Out-String)" Update-MgApplication @currentParameters - $currentAADApp.Add('ID', $AppIdValue) + + if (-not $currentAADApp.ContainsKey('ID')) + { + $currentAADApp.Add('ID', $AppIdValue) + } $needToUpdatePermissions = $true $needToUpdateAuthenticationBehaviors = $true $needToUpdateKeyCredentials = $true @@ -1188,6 +1235,10 @@ function Test-TargetResource [Microsoft.Management.Infrastructure.CimInstance] $OnPremisesPublishing, + [Parameter()] + [System.String] + $ApplicationTemplateId, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -1383,7 +1434,7 @@ function Export-TargetResource try { $Script:ExportMode = $true - [array] $Script:exportedInstances = Get-MgApplication -Filter $Filter -All -ErrorAction Stop + [array] $Script:exportedInstances = Get-MgBetaApplication -Filter $Filter -All -ErrorAction Stop foreach ($AADApp in $Script:exportedInstances) { if ($null -ne $Global:M365DSCExportResourceInstancesCount) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof index ae3c0625d2..21e278cc40 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof @@ -155,6 +155,7 @@ class MSFT_AADApplication : OMI_BaseResource [Write, Description("Specifies the URLs that user tokens are sent to for sign in, or the redirect URIs that OAuth 2.0 authorization codes and access tokens are sent to.")] String ReplyURLs[]; [Write, Description("UPN or ObjectID values of the app's owners.")] String Owners[]; [Write, Description("Represents the set of properties required for configuring Application Proxy for this application. Configuring these properties allows you to publish your on-premises application for secure remote access."), EmbeddedInstance("MSFT_AADApplicationOnPremisesPublishing")] String OnPremisesPublishing; + [Write, Description("Identifier of the associated Application Template.")] String ApplicationTemplateId; [Write, Description("Specify if the Azure AD App should exist or not."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; [Write, Description("Credentials for the Microsoft Graph delegated permissions."), EmbeddedInstance("MSFT_Credential")] string Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; From 7dc39d912700c55a8c630e72debf1e369832181e Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 9 Oct 2024 19:15:11 -0400 Subject: [PATCH 142/252] Fixes UT --- .../MSFT_AADApplication.psm1 | 6 +- .../Microsoft365DSC.AADApplication.Tests.ps1 | 63 +++++++------------ 2 files changed, 26 insertions(+), 43 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index 426d13a171..4b4c6f68e7 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -180,7 +180,7 @@ function Get-TargetResource } else { - $AADApp = Get-MgBetaApplication -Filter "DisplayName eq '$($DisplayName)'" + $AADApp = [Array](Get-MgBetaApplication -Filter "DisplayName eq '$($DisplayName)'") } } if ($null -ne $AADApp -and $AADApp.Count -gt 1) @@ -197,7 +197,7 @@ function Get-TargetResource Write-Verbose -Message 'An instance of Azure AD App was retrieved.' $AADBetaApp= Get-MgBetaApplication -Property "id,displayName,appId,authenticationBehaviors,additionalProperties" -ApplicationId $AADApp.Id -ErrorAction SilentlyContinue - $AADAppKeyCredentials = Get-MgApplication -Property "keyCredentials" -ApplicationId $AADApp.Id -ErrorAction SilentlyContinue + $AADAppKeyCredentials = Get-MgBetaApplication -Property "keyCredentials" -ApplicationId $AADApp.Id -ErrorAction SilentlyContinue $complexAuthenticationBehaviors = @{} if ($null -ne $AADBetaApp.authenticationBehaviors.blockAzureADGraphAccess) @@ -818,6 +818,7 @@ function Set-TargetResource # Create from Template $createdFromTemplate = $false if ($Ensure -eq 'Present' -and $currentAADApp.Ensure -eq 'Absent' -and -not $skipToUpdate -and ` + -not [System.String]::IsNullOrEmpty($ApplicationTemplateId) -and ` $ApplicationTemplateId -ne '8adf8e6e-67b2-4cf2-a259-e3dc5476c621') { $skipToUpdate = $true @@ -1356,7 +1357,6 @@ function Test-TargetResource $ValuesToCheck.Remove('AppId') | Out-Null $ValuesToCheck.Remove('Permissions') | Out-Null - $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` -Source $($MyInvocation.MyCommand.Source) ` -DesiredValues $PSBoundParameters ` diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 index 55637d70cd..2a713b43f4 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 @@ -90,14 +90,14 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential } - Mock -CommandName Get-MgApplication -MockWith { + Mock -CommandName Get-MgBetaApplication -MockWith { return $null } } It 'Should return values from the get method' { (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' - Should -Invoke -CommandName 'Get-MgApplication' -Exactly 1 + Should -Invoke -CommandName 'Get-MgBetaApplication' -Exactly 1 } It 'Should return false from the test method' { Test-TargetResource @testParams | Should -Be $false @@ -126,7 +126,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential } - Mock -CommandName Get-MgApplication -MockWith { + Mock -CommandName Get-MgBetaApplication -MockWith { $AADApp = New-Object PSCustomObject $AADApp | Add-Member -MemberType NoteProperty -Name DisplayName -Value 'App1' $AADApp | Add-Member -MemberType NoteProperty -Name Id -Value '5dcb2237-c61b-4258-9c85-eae2aaeba9d6' @@ -147,7 +147,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should return values from the get method' { (Get-TargetResource @testParams).Ensure | Should -Be 'Present' - Should -Invoke -CommandName 'Get-MgApplication' -Exactly 2 + Should -Invoke -CommandName 'Get-MgBetaApplication' -Exactly 3 } It 'Should return false from the test method' { @@ -248,25 +248,12 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { PermissionIds = @('12345-12345-12345-12345-12345') } -ClientOnly ) - + } -ClientOnly Ensure = 'Present' Credential = $Credential } - Mock -CommandName Get-MgBetaApplication -MockWith { - $AADApp = New-Object PSCustomObject - $AADApp | Add-Member -MemberType NoteProperty -Name DisplayName -Value 'App1' - $AADApp | Add-Member -MemberType NoteProperty -Name Id -Value '5dcb2237-c61b-4258-9c85-eae2aaeba9d6' - $AADApp | Add-Member -MemberType NoteProperty -Name AppId -Value '5dcb2237-c61b-4258-9c85-eae2aaeba9d6' - $AADApp | Add-Member -MemberType NoteProperty -Name AuthenticationBehaviors -Value @{ - blockAzureADGraphAccess = $false - removeUnverifiedEmailClaim = $true - requireClientServicePrincipal = $false - } - return $AADApp - } - Mock -CommandName Get-MgApplication -MockWith { $AADApp = New-Object PSCustomObject $AADApp | Add-Member -MemberType NoteProperty -Name DisplayName -Value 'App1' $AADApp | Add-Member -MemberType NoteProperty -Name Id -Value '5dcb2237-c61b-4258-9c85-eae2aaeba9d6' @@ -349,13 +336,18 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $AADApp | Add-Member -MemberType NoteProperty -Name IdentifierUris -Value 'https://app.contoso.com' $AADApp | Add-Member -MemberType NoteProperty -Name Oauth2RequirePostResponse -Value $false $AADApp | Add-Member -MemberType NoteProperty -Name PublicClient -Value $false + $AADApp | Add-Member -MemberType NoteProperty -Name AuthenticationBehaviors -Value @{ + blockAzureADGraphAccess = $false + removeUnverifiedEmailClaim = $true + requireClientServicePrincipal = $false + } return $AADApp } } It 'Should return Values from the get method' { Get-TargetResource @testParams - Should -Invoke -CommandName 'Get-MgApplication' -Exactly 2 + Should -Invoke -CommandName 'Get-MgBetaApplication' -Exactly 3 } It 'Should return true from the test method' { @@ -380,7 +372,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential } - Mock -CommandName Get-MgApplication -MockWith { + Mock -CommandName Get-MgBetaApplication -MockWith { $AADApp = New-Object PSCustomObject $AADApp | Add-Member -MemberType NoteProperty -Name DisplayName -Value 'App1' $AADApp | Add-Member -MemberType NoteProperty -Name Id -Value '5dcb2237-c61b-4258-9c85-eae2aaeba9d6' @@ -400,7 +392,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should return values from the get method' { Get-TargetResource @testParams - Should -Invoke -CommandName 'Get-MgApplication' -Exactly 2 + Should -Invoke -CommandName 'Get-MgBetaApplication' -Exactly 3 } It 'Should return false from the test method' { @@ -434,28 +426,20 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential } - Mock -CommandName Get-MgApplication -MockWith { - return $null - } - Mock -CommandName Get-MgBetaApplication -MockWith { - return @{ - id = '12345-12345-12345-12345-12345' - appId = '12345-12345-12345-12345-12345' - DisplayName = 'App1' - AuthenticationBehaviours = @{ - blockAzureADGraphAccess = $false - removeUnverifiedEmailClaim = $true - requireClientServicePrincipal = $false + return @( + @{ + id = '12345-12345-12345-12345-12345' + appId = '12345-12345-12345-12345-12345' + DisplayName = 'App1' } - - } + ) } } It 'Should return values from the get method' { Get-TargetResource @testParams - Should -Invoke -CommandName 'Get-MgApplication' -Exactly 1 + Should -Invoke -CommandName 'Get-MgBetaApplication' -Exactly 3 } It 'Should return false from the test method' { @@ -464,7 +448,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should call the new method' { Set-TargetResource @testParams - Should -Invoke -CommandName 'New-MgApplication' -Exactly 1 Should -Invoke -CommandName 'Update-MgBetaApplication' -Exactly 1 } @@ -505,14 +488,14 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential } - Mock -CommandName Get-MgApplication -MockWith { + Mock -CommandName Get-MgBetaApplication -MockWith { return $null } } It 'Should return values from the get method' { Get-TargetResource @testParams - Should -Invoke -CommandName 'Get-MgApplication' -Exactly 1 + Should -Invoke -CommandName 'Get-MgBetaApplication' -Exactly 1 } It 'Should return false from the test method' { @@ -533,7 +516,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential } - Mock -CommandName Get-MgApplication -MockWith { + Mock -CommandName Get-MgBetaApplication -MockWith { $AADApp = New-Object PSCustomObject $AADApp | Add-Member -MemberType NoteProperty -Name DisplayName -Value 'App1' $AADApp | Add-Member -MemberType NoteProperty -Name Id -Value '5dcb2237-c61b-4258-9c85-eae2aaeba9d6' From cfa471c3e7540ade104e9bf848153b13b1aed53b Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Wed, 9 Oct 2024 16:25:17 -0700 Subject: [PATCH 143/252] Delete the accidental merge from topic branches. --- .../MSFT_IntuneMobileAppsAndroidLobApp.psm1 | 408 ------------------ ...T_IntuneMobileAppsAndroidLobApp.schema.mof | 15 - .../readme.md | 3 - .../settings.json | 32 -- .../MSFT_IntuneMobileAppsIOSLobApp.psm1 | 408 ------------------ .../MSFT_IntuneMobileAppsIOSLobApp.schema.mof | 15 - .../MSFT_IntuneMobileAppsIOSLobApp/readme.md | 3 - .../settings.json | 32 -- .../MSFT_IntuneMobileAppsWin32LobApp.psm1 | 408 ------------------ ...SFT_IntuneMobileAppsWin32LobApp.schema.mof | 15 - .../readme.md | 5 - .../settings.json | 32 -- .../IntuneDerivedCredential/1-Create.ps1 | 31 -- .../IntuneDerivedCredential/2-Update.ps1 | 31 -- .../IntuneDerivedCredential/3-Remove.ps1 | 32 -- .../1-Create.ps1 | 32 -- .../2-Update.ps1 | 32 -- .../3-Remove.ps1 | 32 -- .../IntuneMobileAppsIOSLobApp/1-Create.ps1 | 32 -- .../IntuneMobileAppsIOSLobApp/2-Update.ps1 | 32 -- .../IntuneMobileAppsIOSLobApp/3-Remove.ps1 | 32 -- .../IntuneMobileAppsWin32LobApp/1-Create.ps1 | 29 -- .../IntuneMobileAppsWin32LobApp/2-Update.ps1 | 29 -- .../IntuneMobileAppsWin32LobApp/3-Remove.ps1 | 28 -- ...ft365DSC.IntuneDerivedCredential.Tests.ps1 | 197 --------- ...65DSC.IntuneMobileAppWin32LOBApp.Tests.ps1 | 189 -------- ...SC.IntuneMobileAppsAndroidLobApp.Tests.ps1 | 189 -------- ...365DSC.IntuneMobileAppsIOSLobApp.Tests.ps1 | 189 -------- 28 files changed, 2512 deletions(-) delete mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/MSFT_IntuneMobileAppsAndroidLobApp.psm1 delete mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/MSFT_IntuneMobileAppsAndroidLobApp.schema.mof delete mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/readme.md delete mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/settings.json delete mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/MSFT_IntuneMobileAppsIOSLobApp.psm1 delete mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/MSFT_IntuneMobileAppsIOSLobApp.schema.mof delete mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/readme.md delete mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/settings.json delete mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/MSFT_IntuneMobileAppsWin32LobApp.psm1 delete mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/MSFT_IntuneMobileAppsWin32LobApp.schema.mof delete mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/readme.md delete mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/settings.json delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/1-Create.ps1 delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/2-Update.ps1 delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/3-Remove.ps1 delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsAndroidLobApp/1-Create.ps1 delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsAndroidLobApp/2-Update.ps1 delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsAndroidLobApp/3-Remove.ps1 delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsIOSLobApp/1-Create.ps1 delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsIOSLobApp/2-Update.ps1 delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsIOSLobApp/3-Remove.ps1 delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWin32LobApp/1-Create.ps1 delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWin32LobApp/2-Update.ps1 delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWin32LobApp/3-Remove.ps1 delete mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDerivedCredential.Tests.ps1 delete mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppWin32LOBApp.Tests.ps1 delete mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsAndroidLobApp.Tests.ps1 delete mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsIOSLobApp.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/MSFT_IntuneMobileAppsAndroidLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/MSFT_IntuneMobileAppsAndroidLobApp.psm1 deleted file mode 100644 index e5e0c6b7da..0000000000 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/MSFT_IntuneMobileAppsAndroidLobApp.psm1 +++ /dev/null @@ -1,408 +0,0 @@ -function Get-TargetResource -{ - [CmdletBinding()] - [OutputType([System.Collections.Hashtable])] - param - ( - #region Intune params - - [Parameter()] - [System.String] - $Id, - - [Parameter(Mandatory = $true)] - [System.String] - $DisplayName, - - #endregion Intune params - - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present', - - [Parameter()] - [System.Management.Automation.PSCredential] - $Credential, - - [Parameter()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint, - - [Parameter()] - [System.Management.Automation.PSCredential] - $ApplicationSecret, - - [Parameter()] - [Switch] - $ManagedIdentity, - - [Parameter()] - [System.String[]] - $AccessTokens - ) - - New-M365DSCConnection -Workload 'MicrosoftGraph' ` - -InboundParameters $PSBoundParameters | Out-Null - - #Ensure the proper dependencies are installed in the current environment. - Confirm-M365DSCDependencies - - #region Telemetry - $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') - $CommandName = $MyInvocation.MyCommand - $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` - -CommandName $CommandName ` - -Parameters $PSBoundParameters - Add-M365DSCTelemetryEvent -Data $data - #endregion - - $nullResult = $PSBoundParameters - $nullResult.Ensure = 'Absent' - - try - { - $instance = $null - if ($null -ne $Script:exportedInstances -and $Script:ExportMode) - { - $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Id -eq $Id} - } - - if ($null -eq $instance) - { - $instance = Get-MgBetaDeviceAppManagementMobileApp -MobileAppId $Id -ErrorAction Stop - - if ($null -eq $instance) - { - Write-Verbose -Message "Could not find MobileApp by Id {$Id}." - - if (-Not [string]::IsNullOrEmpty($DisplayName)) - { - $instance = Get-MgBetaDeviceAppManagementMobileAppConfiguration ` - -Filter "DisplayName eq '$DisplayName'" ` - -ErrorAction SilentlyContinue - } - } - - if ($null -eq $instance) - { - Write-Verbose -Message "Could not find MobileApp by DisplayName {$DisplayName}." - return $nullResult - } - } - - $results = @{ - Id = $instance.Id - DisplayName = $instance.DisplayName - Ensure = 'Present' - Credential = $Credential - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - ApplicationSecret = $ApplicationSecret - ManagedIdentity = $ManagedIdentity.IsPresent - AccessTokens = $AccessTokens - } - return [System.Collections.Hashtable] $results - } - catch - { - Write-Verbose -Message $_ - New-M365DSCLogEntry -Message 'Error retrieving data:' ` - -Exception $_ ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential - - return $nullResult - } -} - -function Set-TargetResource -{ - [CmdletBinding()] - param - ( - #region Intune params - - [Parameter()] - [System.String] - $Id, - - [Parameter(Mandatory = $true)] - [System.String] - $DisplayName, - - #endregion Intune params - - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present', - - [Parameter()] - [System.Management.Automation.PSCredential] - $Credential, - - [Parameter()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint, - - [Parameter()] - [System.Management.Automation.PSCredential] - $ApplicationSecret, - - [Parameter()] - [Switch] - $ManagedIdentity, - - [Parameter()] - [System.String[]] - $AccessTokens - ) - - #Ensure the proper dependencies are installed in the current environment. - Confirm-M365DSCDependencies - - #region Telemetry - $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') - $CommandName = $MyInvocation.MyCommand - $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` - -CommandName $CommandName ` - -Parameters $PSBoundParameters - Add-M365DSCTelemetryEvent -Data $data - #endregion - - $currentInstance = Get-TargetResource @PSBoundParameters - - $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters - $setParameters.remove('Id') | Out-Null - $setParameters.remove('Ensure') | Out-Null - - # CREATE - if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') - { - New-MgBetaDeviceAppManagementMobileApp @SetParameters - } - # UPDATE - elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') - { - Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id @SetParameters - } - # REMOVE - elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') - { - Remove-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id -Confirm:$false - } -} - -function Test-TargetResource -{ - [CmdletBinding()] - [OutputType([System.Boolean])] - param - ( - #region Intune params - - [Parameter()] - [System.String] - $Id, - - [Parameter(Mandatory = $true)] - [System.String] - $DisplayName, - - #endregion Intune params - - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present', - - [Parameter()] - [System.Management.Automation.PSCredential] - $Credential, - - [Parameter()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint, - - [Parameter()] - [System.Management.Automation.PSCredential] - $ApplicationSecret, - - [Parameter()] - [Switch] - $ManagedIdentity, - - [Parameter()] - [System.String[]] - $AccessTokens - ) - - #Ensure the proper dependencies are installed in the current environment. - Confirm-M365DSCDependencies - - #region Telemetry - $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') - $CommandName = $MyInvocation.MyCommand - $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` - -CommandName $CommandName ` - -Parameters $PSBoundParameters - Add-M365DSCTelemetryEvent -Data $data - #endregion - - $CurrentValues = Get-TargetResource @PSBoundParameters - $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() - - Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" - Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" - - $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` - -Source $($MyInvocation.MyCommand.Source) ` - -DesiredValues $PSBoundParameters ` - -ValuesToCheck $ValuesToCheck.Keys - - Write-Verbose -Message "Test-TargetResource returned $testResult" - - return $testResult -} - -function Export-TargetResource -{ - [CmdletBinding()] - [OutputType([System.String])] - param - ( - [Parameter()] - [System.Management.Automation.PSCredential] - $Credential, - - [Parameter()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint, - - [Parameter()] - [System.Management.Automation.PSCredential] - $ApplicationSecret, - - [Parameter()] - [Switch] - $ManagedIdentity, - - [Parameter()] - [System.String[]] - $AccessTokens - ) - - $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` - -InboundParameters $PSBoundParameters - - #Ensure the proper dependencies are installed in the current environment. - Confirm-M365DSCDependencies - - #region Telemetry - $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') - $CommandName = $MyInvocation.MyCommand - $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` - -CommandName $CommandName ` - -Parameters $PSBoundParameters - Add-M365DSCTelemetryEvent -Data $data - #endregion - - try - { - $Script:ExportMode = $true - [array] $Script:exportedInstances = Get-MgBetaDeviceAppManagementMobileApp -ErrorAction Stop - - $i = 1 - $dscContent = '' - if ($Script:exportedInstances.Length -eq 0) - { - Write-Host $Global:M365DSCEmojiGreenCheckMark - } - else - { - Write-Host "`r`n" -NoNewline - } - foreach ($config in $Script:exportedInstances) - { - $displayedKey = $config.Id - Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline - $params = @{ - Id = $config.Id - DisplayName = $config.DisplayName - Ensure = 'Present' - Credential = $Credential - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - ApplicationSecret = $ApplicationSecret - ManagedIdentity = $ManagedIdentity.IsPresent - AccessTokens = $AccessTokens - } - - $Results = Get-TargetResource @Params - $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` - -Results $Results - - $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` - -ConnectionMode $ConnectionMode ` - -ModulePath $PSScriptRoot ` - -Results $Results ` - -Credential $Credential - $dscContent += $currentDSCBlock - Save-M365DSCPartialExport -Content $currentDSCBlock ` - -FileName $Global:PartialExportFileName - $i++ - Write-Host $Global:M365DSCEmojiGreenCheckMark - } - return $dscContent - } - catch - { - Write-Host $Global:M365DSCEmojiRedX - - New-M365DSCLogEntry -Message 'Error during Export:' ` - -Exception $_ ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential - - return '' - } -} - -Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/MSFT_IntuneMobileAppsAndroidLobApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/MSFT_IntuneMobileAppsAndroidLobApp.schema.mof deleted file mode 100644 index f637f5d71b..0000000000 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/MSFT_IntuneMobileAppsAndroidLobApp.schema.mof +++ /dev/null @@ -1,15 +0,0 @@ -[ClassVersion("1.0.0.0"), FriendlyName("IntuneMobileAppsAndroidLobApp")] -class MSFT_IntuneMobileAppsAndroidLobApp : OMI_BaseResource -{ - [Key, Description("The name of the app.")] String DisplayName; - [Write, Description("The unique identifier for an entity. Read-only.")] String Id; - - [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] string Ensure; - [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; - [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; - [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; - [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; - [Write, Description("Secret of the Azure Active Directory tenant used for authentication."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; - [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; - [Write, Description("Access token used for authentication.")] String AccessTokens[]; -}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/readme.md deleted file mode 100644 index 99fc165230..0000000000 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/readme.md +++ /dev/null @@ -1,3 +0,0 @@ -# IntuneMobileAppsAndroidLobApp - -## Description diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/settings.json deleted file mode 100644 index 439af65889..0000000000 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsAndroidLobApp/settings.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "resourceName": "IntuneMobileAppsAndroidLobApp", - "description": "This resource configures an Intune mobile app.", - "permissions": { - "graph": { - "delegated": { - "read": [ - { - "name": "DeviceManagementApps.Read.All" - } - ], - "update": [ - { - "name": "DeviceManagementApps.ReadWrite.All" - } - ] - }, - "application": { - "read": [ - { - "name": "DeviceManagementApps.Read.All" - } - ], - "update": [ - { - "name": "DeviceManagementApps.ReadWrite.All" - } - ] - } - } - } -} diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/MSFT_IntuneMobileAppsIOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/MSFT_IntuneMobileAppsIOSLobApp.psm1 deleted file mode 100644 index e5e0c6b7da..0000000000 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/MSFT_IntuneMobileAppsIOSLobApp.psm1 +++ /dev/null @@ -1,408 +0,0 @@ -function Get-TargetResource -{ - [CmdletBinding()] - [OutputType([System.Collections.Hashtable])] - param - ( - #region Intune params - - [Parameter()] - [System.String] - $Id, - - [Parameter(Mandatory = $true)] - [System.String] - $DisplayName, - - #endregion Intune params - - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present', - - [Parameter()] - [System.Management.Automation.PSCredential] - $Credential, - - [Parameter()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint, - - [Parameter()] - [System.Management.Automation.PSCredential] - $ApplicationSecret, - - [Parameter()] - [Switch] - $ManagedIdentity, - - [Parameter()] - [System.String[]] - $AccessTokens - ) - - New-M365DSCConnection -Workload 'MicrosoftGraph' ` - -InboundParameters $PSBoundParameters | Out-Null - - #Ensure the proper dependencies are installed in the current environment. - Confirm-M365DSCDependencies - - #region Telemetry - $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') - $CommandName = $MyInvocation.MyCommand - $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` - -CommandName $CommandName ` - -Parameters $PSBoundParameters - Add-M365DSCTelemetryEvent -Data $data - #endregion - - $nullResult = $PSBoundParameters - $nullResult.Ensure = 'Absent' - - try - { - $instance = $null - if ($null -ne $Script:exportedInstances -and $Script:ExportMode) - { - $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Id -eq $Id} - } - - if ($null -eq $instance) - { - $instance = Get-MgBetaDeviceAppManagementMobileApp -MobileAppId $Id -ErrorAction Stop - - if ($null -eq $instance) - { - Write-Verbose -Message "Could not find MobileApp by Id {$Id}." - - if (-Not [string]::IsNullOrEmpty($DisplayName)) - { - $instance = Get-MgBetaDeviceAppManagementMobileAppConfiguration ` - -Filter "DisplayName eq '$DisplayName'" ` - -ErrorAction SilentlyContinue - } - } - - if ($null -eq $instance) - { - Write-Verbose -Message "Could not find MobileApp by DisplayName {$DisplayName}." - return $nullResult - } - } - - $results = @{ - Id = $instance.Id - DisplayName = $instance.DisplayName - Ensure = 'Present' - Credential = $Credential - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - ApplicationSecret = $ApplicationSecret - ManagedIdentity = $ManagedIdentity.IsPresent - AccessTokens = $AccessTokens - } - return [System.Collections.Hashtable] $results - } - catch - { - Write-Verbose -Message $_ - New-M365DSCLogEntry -Message 'Error retrieving data:' ` - -Exception $_ ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential - - return $nullResult - } -} - -function Set-TargetResource -{ - [CmdletBinding()] - param - ( - #region Intune params - - [Parameter()] - [System.String] - $Id, - - [Parameter(Mandatory = $true)] - [System.String] - $DisplayName, - - #endregion Intune params - - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present', - - [Parameter()] - [System.Management.Automation.PSCredential] - $Credential, - - [Parameter()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint, - - [Parameter()] - [System.Management.Automation.PSCredential] - $ApplicationSecret, - - [Parameter()] - [Switch] - $ManagedIdentity, - - [Parameter()] - [System.String[]] - $AccessTokens - ) - - #Ensure the proper dependencies are installed in the current environment. - Confirm-M365DSCDependencies - - #region Telemetry - $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') - $CommandName = $MyInvocation.MyCommand - $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` - -CommandName $CommandName ` - -Parameters $PSBoundParameters - Add-M365DSCTelemetryEvent -Data $data - #endregion - - $currentInstance = Get-TargetResource @PSBoundParameters - - $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters - $setParameters.remove('Id') | Out-Null - $setParameters.remove('Ensure') | Out-Null - - # CREATE - if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') - { - New-MgBetaDeviceAppManagementMobileApp @SetParameters - } - # UPDATE - elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') - { - Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id @SetParameters - } - # REMOVE - elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') - { - Remove-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id -Confirm:$false - } -} - -function Test-TargetResource -{ - [CmdletBinding()] - [OutputType([System.Boolean])] - param - ( - #region Intune params - - [Parameter()] - [System.String] - $Id, - - [Parameter(Mandatory = $true)] - [System.String] - $DisplayName, - - #endregion Intune params - - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present', - - [Parameter()] - [System.Management.Automation.PSCredential] - $Credential, - - [Parameter()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint, - - [Parameter()] - [System.Management.Automation.PSCredential] - $ApplicationSecret, - - [Parameter()] - [Switch] - $ManagedIdentity, - - [Parameter()] - [System.String[]] - $AccessTokens - ) - - #Ensure the proper dependencies are installed in the current environment. - Confirm-M365DSCDependencies - - #region Telemetry - $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') - $CommandName = $MyInvocation.MyCommand - $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` - -CommandName $CommandName ` - -Parameters $PSBoundParameters - Add-M365DSCTelemetryEvent -Data $data - #endregion - - $CurrentValues = Get-TargetResource @PSBoundParameters - $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() - - Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" - Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" - - $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` - -Source $($MyInvocation.MyCommand.Source) ` - -DesiredValues $PSBoundParameters ` - -ValuesToCheck $ValuesToCheck.Keys - - Write-Verbose -Message "Test-TargetResource returned $testResult" - - return $testResult -} - -function Export-TargetResource -{ - [CmdletBinding()] - [OutputType([System.String])] - param - ( - [Parameter()] - [System.Management.Automation.PSCredential] - $Credential, - - [Parameter()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint, - - [Parameter()] - [System.Management.Automation.PSCredential] - $ApplicationSecret, - - [Parameter()] - [Switch] - $ManagedIdentity, - - [Parameter()] - [System.String[]] - $AccessTokens - ) - - $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` - -InboundParameters $PSBoundParameters - - #Ensure the proper dependencies are installed in the current environment. - Confirm-M365DSCDependencies - - #region Telemetry - $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') - $CommandName = $MyInvocation.MyCommand - $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` - -CommandName $CommandName ` - -Parameters $PSBoundParameters - Add-M365DSCTelemetryEvent -Data $data - #endregion - - try - { - $Script:ExportMode = $true - [array] $Script:exportedInstances = Get-MgBetaDeviceAppManagementMobileApp -ErrorAction Stop - - $i = 1 - $dscContent = '' - if ($Script:exportedInstances.Length -eq 0) - { - Write-Host $Global:M365DSCEmojiGreenCheckMark - } - else - { - Write-Host "`r`n" -NoNewline - } - foreach ($config in $Script:exportedInstances) - { - $displayedKey = $config.Id - Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline - $params = @{ - Id = $config.Id - DisplayName = $config.DisplayName - Ensure = 'Present' - Credential = $Credential - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - ApplicationSecret = $ApplicationSecret - ManagedIdentity = $ManagedIdentity.IsPresent - AccessTokens = $AccessTokens - } - - $Results = Get-TargetResource @Params - $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` - -Results $Results - - $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` - -ConnectionMode $ConnectionMode ` - -ModulePath $PSScriptRoot ` - -Results $Results ` - -Credential $Credential - $dscContent += $currentDSCBlock - Save-M365DSCPartialExport -Content $currentDSCBlock ` - -FileName $Global:PartialExportFileName - $i++ - Write-Host $Global:M365DSCEmojiGreenCheckMark - } - return $dscContent - } - catch - { - Write-Host $Global:M365DSCEmojiRedX - - New-M365DSCLogEntry -Message 'Error during Export:' ` - -Exception $_ ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential - - return '' - } -} - -Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/MSFT_IntuneMobileAppsIOSLobApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/MSFT_IntuneMobileAppsIOSLobApp.schema.mof deleted file mode 100644 index 28add1ac2a..0000000000 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/MSFT_IntuneMobileAppsIOSLobApp.schema.mof +++ /dev/null @@ -1,15 +0,0 @@ -[ClassVersion("1.0.0.0"), FriendlyName("IntuneMobileAppsIOSLobApp")] -class MSFT_IntuneMobileAppsIOSLobApp : OMI_BaseResource -{ - [Key, Description("The name of the app category.")] String DisplayName; - [Write, Description("The unique identifier for an entity. Read-only.")] String Id; - - [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] string Ensure; - [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; - [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; - [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; - [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; - [Write, Description("Secret of the Azure Active Directory tenant used for authentication."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; - [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; - [Write, Description("Access token used for authentication.")] String AccessTokens[]; -}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/readme.md deleted file mode 100644 index b41aeb8da9..0000000000 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/readme.md +++ /dev/null @@ -1,3 +0,0 @@ -# IntuneMobileAppsIOSLobApp - -## Description diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/settings.json deleted file mode 100644 index e09fcf3ab7..0000000000 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsIOSLobApp/settings.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "resourceName": "IntuneMobileAppsIOSLobApp", - "description": "Configures a resource for navigation property for Intune mobile app categories.", - "permissions": { - "graph": { - "delegated": { - "read": [ - { - "name": "DeviceManagementApps.Read.All" - } - ], - "update": [ - { - "name": "DeviceManagementApps.ReadWrite.All" - } - ] - }, - "application": { - "read": [ - { - "name": "DeviceManagementApps.Read.All" - } - ], - "update": [ - { - "name": "DeviceManagementApps.ReadWrite.All" - } - ] - } - } - } -} diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/MSFT_IntuneMobileAppsWin32LobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/MSFT_IntuneMobileAppsWin32LobApp.psm1 deleted file mode 100644 index e5e0c6b7da..0000000000 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/MSFT_IntuneMobileAppsWin32LobApp.psm1 +++ /dev/null @@ -1,408 +0,0 @@ -function Get-TargetResource -{ - [CmdletBinding()] - [OutputType([System.Collections.Hashtable])] - param - ( - #region Intune params - - [Parameter()] - [System.String] - $Id, - - [Parameter(Mandatory = $true)] - [System.String] - $DisplayName, - - #endregion Intune params - - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present', - - [Parameter()] - [System.Management.Automation.PSCredential] - $Credential, - - [Parameter()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint, - - [Parameter()] - [System.Management.Automation.PSCredential] - $ApplicationSecret, - - [Parameter()] - [Switch] - $ManagedIdentity, - - [Parameter()] - [System.String[]] - $AccessTokens - ) - - New-M365DSCConnection -Workload 'MicrosoftGraph' ` - -InboundParameters $PSBoundParameters | Out-Null - - #Ensure the proper dependencies are installed in the current environment. - Confirm-M365DSCDependencies - - #region Telemetry - $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') - $CommandName = $MyInvocation.MyCommand - $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` - -CommandName $CommandName ` - -Parameters $PSBoundParameters - Add-M365DSCTelemetryEvent -Data $data - #endregion - - $nullResult = $PSBoundParameters - $nullResult.Ensure = 'Absent' - - try - { - $instance = $null - if ($null -ne $Script:exportedInstances -and $Script:ExportMode) - { - $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Id -eq $Id} - } - - if ($null -eq $instance) - { - $instance = Get-MgBetaDeviceAppManagementMobileApp -MobileAppId $Id -ErrorAction Stop - - if ($null -eq $instance) - { - Write-Verbose -Message "Could not find MobileApp by Id {$Id}." - - if (-Not [string]::IsNullOrEmpty($DisplayName)) - { - $instance = Get-MgBetaDeviceAppManagementMobileAppConfiguration ` - -Filter "DisplayName eq '$DisplayName'" ` - -ErrorAction SilentlyContinue - } - } - - if ($null -eq $instance) - { - Write-Verbose -Message "Could not find MobileApp by DisplayName {$DisplayName}." - return $nullResult - } - } - - $results = @{ - Id = $instance.Id - DisplayName = $instance.DisplayName - Ensure = 'Present' - Credential = $Credential - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - ApplicationSecret = $ApplicationSecret - ManagedIdentity = $ManagedIdentity.IsPresent - AccessTokens = $AccessTokens - } - return [System.Collections.Hashtable] $results - } - catch - { - Write-Verbose -Message $_ - New-M365DSCLogEntry -Message 'Error retrieving data:' ` - -Exception $_ ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential - - return $nullResult - } -} - -function Set-TargetResource -{ - [CmdletBinding()] - param - ( - #region Intune params - - [Parameter()] - [System.String] - $Id, - - [Parameter(Mandatory = $true)] - [System.String] - $DisplayName, - - #endregion Intune params - - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present', - - [Parameter()] - [System.Management.Automation.PSCredential] - $Credential, - - [Parameter()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint, - - [Parameter()] - [System.Management.Automation.PSCredential] - $ApplicationSecret, - - [Parameter()] - [Switch] - $ManagedIdentity, - - [Parameter()] - [System.String[]] - $AccessTokens - ) - - #Ensure the proper dependencies are installed in the current environment. - Confirm-M365DSCDependencies - - #region Telemetry - $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') - $CommandName = $MyInvocation.MyCommand - $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` - -CommandName $CommandName ` - -Parameters $PSBoundParameters - Add-M365DSCTelemetryEvent -Data $data - #endregion - - $currentInstance = Get-TargetResource @PSBoundParameters - - $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters - $setParameters.remove('Id') | Out-Null - $setParameters.remove('Ensure') | Out-Null - - # CREATE - if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') - { - New-MgBetaDeviceAppManagementMobileApp @SetParameters - } - # UPDATE - elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') - { - Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id @SetParameters - } - # REMOVE - elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') - { - Remove-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id -Confirm:$false - } -} - -function Test-TargetResource -{ - [CmdletBinding()] - [OutputType([System.Boolean])] - param - ( - #region Intune params - - [Parameter()] - [System.String] - $Id, - - [Parameter(Mandatory = $true)] - [System.String] - $DisplayName, - - #endregion Intune params - - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present', - - [Parameter()] - [System.Management.Automation.PSCredential] - $Credential, - - [Parameter()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint, - - [Parameter()] - [System.Management.Automation.PSCredential] - $ApplicationSecret, - - [Parameter()] - [Switch] - $ManagedIdentity, - - [Parameter()] - [System.String[]] - $AccessTokens - ) - - #Ensure the proper dependencies are installed in the current environment. - Confirm-M365DSCDependencies - - #region Telemetry - $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') - $CommandName = $MyInvocation.MyCommand - $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` - -CommandName $CommandName ` - -Parameters $PSBoundParameters - Add-M365DSCTelemetryEvent -Data $data - #endregion - - $CurrentValues = Get-TargetResource @PSBoundParameters - $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() - - Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" - Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" - - $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` - -Source $($MyInvocation.MyCommand.Source) ` - -DesiredValues $PSBoundParameters ` - -ValuesToCheck $ValuesToCheck.Keys - - Write-Verbose -Message "Test-TargetResource returned $testResult" - - return $testResult -} - -function Export-TargetResource -{ - [CmdletBinding()] - [OutputType([System.String])] - param - ( - [Parameter()] - [System.Management.Automation.PSCredential] - $Credential, - - [Parameter()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint, - - [Parameter()] - [System.Management.Automation.PSCredential] - $ApplicationSecret, - - [Parameter()] - [Switch] - $ManagedIdentity, - - [Parameter()] - [System.String[]] - $AccessTokens - ) - - $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` - -InboundParameters $PSBoundParameters - - #Ensure the proper dependencies are installed in the current environment. - Confirm-M365DSCDependencies - - #region Telemetry - $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') - $CommandName = $MyInvocation.MyCommand - $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` - -CommandName $CommandName ` - -Parameters $PSBoundParameters - Add-M365DSCTelemetryEvent -Data $data - #endregion - - try - { - $Script:ExportMode = $true - [array] $Script:exportedInstances = Get-MgBetaDeviceAppManagementMobileApp -ErrorAction Stop - - $i = 1 - $dscContent = '' - if ($Script:exportedInstances.Length -eq 0) - { - Write-Host $Global:M365DSCEmojiGreenCheckMark - } - else - { - Write-Host "`r`n" -NoNewline - } - foreach ($config in $Script:exportedInstances) - { - $displayedKey = $config.Id - Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline - $params = @{ - Id = $config.Id - DisplayName = $config.DisplayName - Ensure = 'Present' - Credential = $Credential - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - ApplicationSecret = $ApplicationSecret - ManagedIdentity = $ManagedIdentity.IsPresent - AccessTokens = $AccessTokens - } - - $Results = Get-TargetResource @Params - $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` - -Results $Results - - $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` - -ConnectionMode $ConnectionMode ` - -ModulePath $PSScriptRoot ` - -Results $Results ` - -Credential $Credential - $dscContent += $currentDSCBlock - Save-M365DSCPartialExport -Content $currentDSCBlock ` - -FileName $Global:PartialExportFileName - $i++ - Write-Host $Global:M365DSCEmojiGreenCheckMark - } - return $dscContent - } - catch - { - Write-Host $Global:M365DSCEmojiRedX - - New-M365DSCLogEntry -Message 'Error during Export:' ` - -Exception $_ ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential - - return '' - } -} - -Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/MSFT_IntuneMobileAppsWin32LobApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/MSFT_IntuneMobileAppsWin32LobApp.schema.mof deleted file mode 100644 index f0d45d3874..0000000000 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/MSFT_IntuneMobileAppsWin32LobApp.schema.mof +++ /dev/null @@ -1,15 +0,0 @@ -[ClassVersion("1.0.0.0"), FriendlyName("IntuneMobileAppsWin32LobApp")] -class MSFT_IntuneMobileAppsWin32LobApp : OMI_BaseResource -{ - [Key, Description("The name of the app.")] String DisplayName; - [Write, Description("The unique identifier for an entity. Read-only.")] String Id; - - [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] string Ensure; - [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; - [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; - [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; - [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; - [Write, Description("Secret of the Azure Active Directory tenant used for authentication."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; - [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; - [Write, Description("Access token used for authentication.")] String AccessTokens[]; -}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/readme.md deleted file mode 100644 index 4485083c7e..0000000000 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/readme.md +++ /dev/null @@ -1,5 +0,0 @@ -# IntuneMobileAppsWin32LobApp - -## Description - -Configures a resource for navigation property for Intune mobile app. Default app cannot be renamed. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/settings.json deleted file mode 100644 index 3845518060..0000000000 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWin32LobApp/settings.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "resourceName": "IntuneMobileAppsWin32LobApp", - "description": "Configures a resource for navigation property for Intune mobile app.", - "permissions": { - "graph": { - "delegated": { - "read": [ - { - "name": "DeviceManagementApps.Read.All" - } - ], - "update": [ - { - "name": "DeviceManagementApps.ReadWrite.All" - } - ] - }, - "application": { - "read": [ - { - "name": "DeviceManagementApps.Read.All" - } - ], - "update": [ - { - "name": "DeviceManagementApps.ReadWrite.All" - } - ] - } - } - } -} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/1-Create.ps1 deleted file mode 100644 index 07f1840e08..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/1-Create.ps1 +++ /dev/null @@ -1,31 +0,0 @@ -<# This example is used to test new resources and showcase the usage of new resources being worked on. It is not meant to use as a production baseline. #> -Configuration Example { - param( - [Parameter()] - [System.String] $ApplicationId, - - [Parameter()] - [System.String] $TenantId, - - [Parameter()] - [System.String] $CertificateThumbprint - ) - - Import-DscResource -ModuleName Microsoft365DSC - - node localhost { - IntuneDerivedCredential "IntuneDerivedCredential-DataManagement" { - Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606" - DisplayName = "Custom Data Management" - Ensure = "Present" - HelpUrl = "https://www.microsoft.com" - Issuer = "DISA Purebred" - NotificationType = "Email" - ThresholdPercentage = 0 - Header = @( - [PSCustomObject]@{ Key = 'HeaderKey1'; Value = 'HeaderValue1' } - [PSCustomObject]@{ Key = 'HeaderKey2'; Value = 'HeaderValue2' } - ) - } - } -} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/2-Update.ps1 deleted file mode 100644 index 07f1840e08..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/2-Update.ps1 +++ /dev/null @@ -1,31 +0,0 @@ -<# This example is used to test new resources and showcase the usage of new resources being worked on. It is not meant to use as a production baseline. #> -Configuration Example { - param( - [Parameter()] - [System.String] $ApplicationId, - - [Parameter()] - [System.String] $TenantId, - - [Parameter()] - [System.String] $CertificateThumbprint - ) - - Import-DscResource -ModuleName Microsoft365DSC - - node localhost { - IntuneDerivedCredential "IntuneDerivedCredential-DataManagement" { - Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606" - DisplayName = "Custom Data Management" - Ensure = "Present" - HelpUrl = "https://www.microsoft.com" - Issuer = "DISA Purebred" - NotificationType = "Email" - ThresholdPercentage = 0 - Header = @( - [PSCustomObject]@{ Key = 'HeaderKey1'; Value = 'HeaderValue1' } - [PSCustomObject]@{ Key = 'HeaderKey2'; Value = 'HeaderValue2' } - ) - } - } -} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/3-Remove.ps1 deleted file mode 100644 index a6c927219e..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/3-Remove.ps1 +++ /dev/null @@ -1,32 +0,0 @@ -<# This example is used to test new resources and showcase the usage of new resources being worked on. It is not meant to use as a production baseline. #> -Configuration Example { - param( - [Parameter()] - [System.String] $ApplicationId, - - [Parameter()] - [System.String] $TenantId, - - [Parameter()] - [System.String] $CertificateThumbprint - ) - - Import-DscResource -ModuleName Microsoft365DSC - - node localhost { - IntuneDerivedCredential "IntuneDerivedCredential-DataManagement" { - Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606" - DisplayName = "Custom Data Management" - Ensure = "Present" - HelpUrl = "https://www.microsoft.com" - Issuer = "DISA Purebred" - NotificationType = "Email" - ThresholdPercentage = 0 - Header = @( - [PSCustomObject]@{ Key = 'HeaderKey1'; Value = 'HeaderValue1' } - [PSCustomObject]@{ Key = 'HeaderKey2'; Value = 'HeaderValue2' } - ) - } - } -} - diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsAndroidLobApp/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsAndroidLobApp/1-Create.ps1 deleted file mode 100644 index 6d10550d7e..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsAndroidLobApp/1-Create.ps1 +++ /dev/null @@ -1,32 +0,0 @@ -<# -This example is used to test new resources and showcase the usage of new resources being worked on. -It is not meant to use as a production baseline. -#> - -Configuration Example -{ - param( - [Parameter()] - [System.String] - $Id, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint - ) - - Import-DscResource -ModuleName Microsoft365DSC - node localhost - { - IntuneMobileAppsAndroidLobApp "IntuneMobileAppsAndroidLobApp-Data Management" - { - Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Custom Data Management"; - Ensure = "Present"; - } - } -} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsAndroidLobApp/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsAndroidLobApp/2-Update.ps1 deleted file mode 100644 index a7d50d91bb..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsAndroidLobApp/2-Update.ps1 +++ /dev/null @@ -1,32 +0,0 @@ -<# -This example is used to test new resources and showcase the usage of new resources being worked on. -It is not meant to use as a production baseline. -#> - -Configuration Example -{ - param( - [Parameter()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint - ) - - Import-DscResource -ModuleName Microsoft365DSC - node localhost - { - IntuneMobileAppsAndroidLobApp "IntuneMobileAppsAndroidLobApp-Data Management" - { - Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Custom Data Management updated"; - Ensure = "Present"; - } - } -} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsAndroidLobApp/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsAndroidLobApp/3-Remove.ps1 deleted file mode 100644 index f9f09c6d16..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsAndroidLobApp/3-Remove.ps1 +++ /dev/null @@ -1,32 +0,0 @@ -<# -This example is used to test new resources and showcase the usage of new resources being worked on. -It is not meant to use as a production baseline. -#> - -Configuration Example -{ - param( - [Parameter()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $Id, - - [Parameter()] - [System.String] - $CertificateThumbprint - ) - - Import-DscResource -ModuleName Microsoft365DSC - node localhost - { - IntuneMobileAppsAndroidLobApp "IntuneMobileAppsAndroidLobApp-Data Management" - { - Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Custom Data Management"; - Ensure = "Absent"; - } - } -} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsIOSLobApp/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsIOSLobApp/1-Create.ps1 deleted file mode 100644 index af89f735c1..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsIOSLobApp/1-Create.ps1 +++ /dev/null @@ -1,32 +0,0 @@ -<# -This example is used to test new resources and showcase the usage of new resources being worked on. -It is not meant to use as a production baseline. -#> - -Configuration Example -{ - param( - [Parameter()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint - ) - - Import-DscResource -ModuleName Microsoft365DSC - node localhost - { - IntuneMobileAppsIOSLobApp "IntuneMobileAppsIOSLobApp-Data Management" - { - Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Custom Data Management"; - Ensure = "Present"; - } - } -} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsIOSLobApp/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsIOSLobApp/2-Update.ps1 deleted file mode 100644 index 15243d392f..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsIOSLobApp/2-Update.ps1 +++ /dev/null @@ -1,32 +0,0 @@ -<# -This example is used to test new resources and showcase the usage of new resources being worked on. -It is not meant to use as a production baseline. -#> - -Configuration Example -{ - param( - [Parameter()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint - ) - - Import-DscResource -ModuleName Microsoft365DSC - node localhost - { - IntuneMobileAppsIOSLobApp "IntuneMobileAppsIOSLobApp-Data Management" - { - Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Custom Data Management updated"; - Ensure = "Present"; - } - } -} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsIOSLobApp/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsIOSLobApp/3-Remove.ps1 deleted file mode 100644 index c480aed510..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsIOSLobApp/3-Remove.ps1 +++ /dev/null @@ -1,32 +0,0 @@ -<# -This example is used to test new resources and showcase the usage of new resources being worked on. -It is not meant to use as a production baseline. -#> - -Configuration Example -{ - param( - [Parameter()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint - ) - - Import-DscResource -ModuleName Microsoft365DSC - node localhost - { - IntuneMobileAppsIOSLobApp "IntuneMobileAppsIOSLobApp-Data Management" - { - Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Custom Data Management"; - Ensure = "Absent"; - } - } -} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWin32LobApp/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWin32LobApp/1-Create.ps1 deleted file mode 100644 index 3c39a8f5d3..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWin32LobApp/1-Create.ps1 +++ /dev/null @@ -1,29 +0,0 @@ -<# -This example is used to test new resources and showcase the usage of new resources being worked on. -It is not meant to use as a production baseline. -#> - -Configuration Example -{ - param( - [Parameter()] - [System.String] - $Id, - - [Parameter()] - [System.String] - $DisplayName - - ) - - Import-DscResource -ModuleName Microsoft365DSC - node localhost - { - IntuneMobileAppsWin32LobApp "IntuneMobileAppsWin32LobApp-Data Management" - { - Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Custom Data Management"; - Ensure = "Present"; - } - } -} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWin32LobApp/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWin32LobApp/2-Update.ps1 deleted file mode 100644 index 232b82854e..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWin32LobApp/2-Update.ps1 +++ /dev/null @@ -1,29 +0,0 @@ -<# -This example is used to test new resources and showcase the usage of new resources being worked on. -It is not meant to use as a production baseline. -#> - -Configuration Example -{ - param( - [Parameter()] - [System.String] - $Id, - - [Parameter()] - [System.String] - $DisplayName - - ) - - Import-DscResource -ModuleName Microsoft365DSC - node localhost - { - IntuneMobileAppsWin32LobApp "IntuneMobileAppsWin32LobApp-Data Management" - { - Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Custom Data Management updated"; - Ensure = "Present"; - } - } -} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWin32LobApp/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWin32LobApp/3-Remove.ps1 deleted file mode 100644 index 07a910e21b..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWin32LobApp/3-Remove.ps1 +++ /dev/null @@ -1,28 +0,0 @@ -<# -This example is used to test new resources and showcase the usage of new resources being worked on. -It is not meant to use as a production baseline. -#> - -Configuration Example -{ - param( - [Parameter()] - [System.String] - $Id, - - [Parameter()] - [System.String] - $DisplayName - ) - - Import-DscResource -ModuleName Microsoft365DSC - node localhost - { - IntuneMobileAppsWin32LobApp "IntuneMobileAppsWin32LobApp-Data Management" - { - Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Custom Data Management"; - Ensure = "Absent"; - } - } -} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDerivedCredential.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDerivedCredential.Tests.ps1 deleted file mode 100644 index 1df65bd189..0000000000 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDerivedCredential.Tests.ps1 +++ /dev/null @@ -1,197 +0,0 @@ -[CmdletBinding()] -param( -) -$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` - -ChildPath '..\..\Unit' ` - -Resolve -$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` - -ChildPath '\Stubs\Microsoft365.psm1' ` - -Resolve) -$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` - -ChildPath '\Stubs\Generic.psm1' ` - -Resolve) -Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` - -ChildPath '\UnitTestHelper.psm1' ` - -Resolve) - -$CurrentScriptPath = $PSCommandPath.Split('\') -$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] -$ResourceName = $CurrentScriptName.Split('.')[1] -$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` - -DscResource $ResourceName -GenericStubModule $GenericStubPath - -Describe -Name $Global:DscHelper.DescribeHeader -Fixture { - InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { - Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope - BeforeAll { - - $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force - $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) - - Mock -CommandName Confirm-M365DSCDependencies -MockWith { - } - - Mock -CommandName New-M365DSCConnection -MockWith { - return "Credentials" - } - - # Mock Write-Host to hide output during the tests - Mock -CommandName Write-Host -MockWith { - } - - Mock -CommandName Get-MgBetaDeviceManagementDerivedCredentialy -MockWith { - } - Mock -CommandName New-MgBetaDeviceManagementDerivedCredential -MockWith { - } - Mock -CommandName Update-MgBetaDeviceManagementDerivedCredential -MockWith { - } - Mock -CommandName Remove-MgBetaDeviceManagementDerivedCredential -MockWith { - } - $Script:exportedInstances =$null - $Script:ExportMode = $false - } - # Test contexts - Context -Name "The instance should exist but it DOES NOT" -Fixture { - BeforeAll { - $testParams = @{ - Ensure = 'Present' - Id = $instance.Id - DisplayName = $instance.DisplayName - HelpUrl = $HelpUrl - Issuer = $Issuer - NotificationType = $NotificationType - ThresholdPercentage = $ThresholdPercentage - Header = $Header - } - - Mock -CommandName Get-MgBetaDeviceManagementDerivedCredential -MockWith { - return $null - } - } - It 'Should return Values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' - } - It 'Should return false from the Test method' { - Test-TargetResource @testParams | Should -Be $false - } - - It 'Should create a new instance from the Set method' { - Set-TargetResource @testParams - Should -Invoke -CommandName New-MgBetaDeviceManagementDerivedCredential -Exactly 1 - } - } - - Context -Name "The instance exists but it SHOULD NOT" -Fixture { - BeforeAll { - $testParams = @{ - Ensure = 'Present' - Id = $instance.Id - DisplayName = $instance.DisplayName - HelpUrl = $HelpUrl - Issuer = $Issuer - NotificationType = $NotificationType - ThresholdPercentage = $ThresholdPercentage - Header = $Header - } - - Mock -CommandName Get-MgBetaDeviceManagementDerivedCredential -MockWith { - return @{ - - } - } - } - It 'Should return Values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Present' - } - It 'Should return false from the Test method' { - Test-TargetResource @testParams | Should -Be $false - } - - It 'Should remove the instance from the Set method' { - Set-TargetResource @testParams - Should -Invoke -CommandName Remove-MgBetaDeviceManagementDerivedCredential -Exactly 1 - } - } - - Context -Name "The instance exists and values are already in the desired state" -Fixture { - BeforeAll { - $testParams = @{ - Ensure = 'Present' - Id = $instance.Id - DisplayName = $instance.DisplayName - HelpUrl = $HelpUrl - Issuer = $Issuer - NotificationType = $NotificationType - ThresholdPercentage = $ThresholdPercentage - Header = $Header - } - - Mock -CommandName Get-MgBetaDeviceManagementDerivedCredential -MockWith { - return @{ - - } - } - } - - It 'Should return true from the Test method' { - Test-TargetResource @testParams | Should -Be $true - } - } - - Context -Name "The instance exists and values are NOT in the desired state" -Fixture { - BeforeAll { - $testParams = @{ - Ensure = 'Present' - Id = $instance.Id - DisplayName = $instance.DisplayName - HelpUrl = $HelpUrl - Issuer = $Issuer - NotificationType = $NotificationType - ThresholdPercentage = $ThresholdPercentage - Header = $Header - } - - Mock -CommandName Get-MgBetaDeviceManagementDerivedCredential -MockWith { - return @{ - - } - } - } - - It 'Should return Values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Present' - } - - It 'Should return false from the Test method' { - Test-TargetResource @testParams | Should -Be $false - } - - It 'Should call the Set method' { - Set-TargetResource @testParams - Should -Invoke -CommandName Update-MgBetaDeviceManagementDerivedCredential -Exactly 1 - } - } - - Context -Name 'ReverseDSC Tests' -Fixture { - BeforeAll { - $Global:CurrentModeIsExport = $true - $Global:PartialExportFileName = "$(New-Guid).partial.ps1" - $testParams = @{ - Credential = $Credential; - } - - Mock -CommandName Get-MgBetaDeviceManagementDerivedCredential -MockWith { - return @{ - - } - } - } - It 'Should Reverse Engineer resource from the Export method' { - $result = Export-TargetResource @testParams - $result | Should -Not -BeNullOrEmpty - } - } - } -} - -Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppWin32LOBApp.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppWin32LOBApp.Tests.ps1 deleted file mode 100644 index a3503a7a3d..0000000000 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppWin32LOBApp.Tests.ps1 +++ /dev/null @@ -1,189 +0,0 @@ -[CmdletBinding()] -param( -) -$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` - -ChildPath '..\..\Unit' ` - -Resolve -$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` - -ChildPath '\Stubs\Microsoft365.psm1' ` - -Resolve) -$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` - -ChildPath '\Stubs\Generic.psm1' ` - -Resolve) -Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` - -ChildPath '\UnitTestHelper.psm1' ` - -Resolve) - -$CurrentScriptPath = $PSCommandPath.Split('\') -$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] -$ResourceName = $CurrentScriptName.Split('.')[1] -$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` - -DscResource $ResourceName -GenericStubModule $GenericStubPath - -Describe -Name $Global:DscHelper.DescribeHeader -Fixture { - InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { - Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope - BeforeAll { - - $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force - $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) - - Mock -CommandName Confirm-M365DSCDependencies -MockWith { - } - - Mock -CommandName New-M365DSCConnection -MockWith { - return "Credentials" - } - - # Mock Write-Host to hide output during the tests - Mock -CommandName Write-Host -MockWith { - } - - Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { - } - Mock -CommandName New-MgBetaDeviceAppManagementMobileApp -MockWith { - } - Mock -CommandName Update-MgBetaDeviceAppManagementMobileApp -MockWith { - } - Mock -CommandName Remove-MgBetaDeviceAppManagementMobileApp -MockWith { - } - - $Script:exportedInstances =$null - $Script:ExportMode = $false - } - - #Test contexts - - Context -Name '1. The instance should exist but it DOES NOT' -Fixture { - BeforeAll { - $testParams = @{ - Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' - DisplayName = 'Data Management' - Ensure = 'Present' - Credential = $Credential - } - - Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { - return $null - } - } - - It '1.1 Should return Values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' - } - It '1.2 Should return false from the Test method' { - Test-TargetResource @testParams | Should -Be $false - } - It '1.3 Should create a new instance from the Set method' { - Set-TargetResource @testParams - Should -Invoke -CommandName New-MgBetaDeviceAppManagementMobileApp -Exactly 1 - } - } - - Context -Name '2. The instance exists but it SHOULD NOT' -Fixture { - BeforeAll { - $testParams = @{ - Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' - DisplayName = 'Data Management' - Ensure = 'Absent' - Credential = $Credential - } - - Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { - return @{ - Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' - DisplayName = 'Data Management' - } - } - } - - It '2.1 Should return values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Present' - } - It '2.2 Should return false from the Test method' { - Test-TargetResource @testParams | Should -Be $false - } - It '2.3 Should remove the instance from the Set method' { - Set-TargetResource @testParams - Should -Invoke -CommandName Remove-MgBetaDeviceAppManagementMobileApp -Exactly 1 - } - } - - Context -Name '3. The instance exists and values are already in the desired state' -Fixture { - BeforeAll { - $testParams = @{ - Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' - DisplayName = 'Data Management' - Ensure = 'Present' - Credential = $Credential - } - - Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { - return @{ - Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' - DisplayName = 'Data Management' - } - } - } - - It '3.0 Should return true from the Test method' { - Test-TargetResource @testParams | Should -Be $true - } - } - - Context -Name '4. The instance exists and values are NOT in the desired state' -Fixture { - BeforeAll { - $testParams = @{ - Id = "046e0b16-76ce-4b49-bf1b-1cc5bd94fb47" - DisplayName = "Data Management" - Ensure = 'Present' - Credential = $Credential - } - - Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { - return @{ - Id = "046e0b16-76ce-4b49-bf1b-1cc5bd94fb47" - DisplayName = "Data Management 1" #drift - } - } - } - - It '4.1 Should return Values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Present' - } - - It '4.2 Should return false from the Test method' { - Test-TargetResource @testParams | Should -Be $false - } - - It '4.3 Should call the Set method' { - Set-TargetResource @testParams - Should -Invoke -CommandName Update-MgBetaDeviceAppManagementMobileApp -Exactly 1 - } - } - - Context -Name '5. ReverseDSC Tests' -Fixture { - BeforeAll { - $Global:CurrentModeIsExport = $true - $Global:PartialExportFileName = "$(New-Guid).partial.ps1" - $testParams = @{ - Credential = $Credential - } - - Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { - return @{ - Id = "046e0b16-76ce-4b49-bf1b-1cc5bd94fb47" - DisplayName = "Data Management" - } - } - } - - It '5.1 Should Reverse Engineer resource from the Export method' { - $result = Export-TargetResource @testParams - $result | Should -Not -BeNullOrEmpty - } - } - } -} - -Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsAndroidLobApp.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsAndroidLobApp.Tests.ps1 deleted file mode 100644 index a3503a7a3d..0000000000 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsAndroidLobApp.Tests.ps1 +++ /dev/null @@ -1,189 +0,0 @@ -[CmdletBinding()] -param( -) -$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` - -ChildPath '..\..\Unit' ` - -Resolve -$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` - -ChildPath '\Stubs\Microsoft365.psm1' ` - -Resolve) -$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` - -ChildPath '\Stubs\Generic.psm1' ` - -Resolve) -Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` - -ChildPath '\UnitTestHelper.psm1' ` - -Resolve) - -$CurrentScriptPath = $PSCommandPath.Split('\') -$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] -$ResourceName = $CurrentScriptName.Split('.')[1] -$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` - -DscResource $ResourceName -GenericStubModule $GenericStubPath - -Describe -Name $Global:DscHelper.DescribeHeader -Fixture { - InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { - Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope - BeforeAll { - - $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force - $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) - - Mock -CommandName Confirm-M365DSCDependencies -MockWith { - } - - Mock -CommandName New-M365DSCConnection -MockWith { - return "Credentials" - } - - # Mock Write-Host to hide output during the tests - Mock -CommandName Write-Host -MockWith { - } - - Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { - } - Mock -CommandName New-MgBetaDeviceAppManagementMobileApp -MockWith { - } - Mock -CommandName Update-MgBetaDeviceAppManagementMobileApp -MockWith { - } - Mock -CommandName Remove-MgBetaDeviceAppManagementMobileApp -MockWith { - } - - $Script:exportedInstances =$null - $Script:ExportMode = $false - } - - #Test contexts - - Context -Name '1. The instance should exist but it DOES NOT' -Fixture { - BeforeAll { - $testParams = @{ - Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' - DisplayName = 'Data Management' - Ensure = 'Present' - Credential = $Credential - } - - Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { - return $null - } - } - - It '1.1 Should return Values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' - } - It '1.2 Should return false from the Test method' { - Test-TargetResource @testParams | Should -Be $false - } - It '1.3 Should create a new instance from the Set method' { - Set-TargetResource @testParams - Should -Invoke -CommandName New-MgBetaDeviceAppManagementMobileApp -Exactly 1 - } - } - - Context -Name '2. The instance exists but it SHOULD NOT' -Fixture { - BeforeAll { - $testParams = @{ - Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' - DisplayName = 'Data Management' - Ensure = 'Absent' - Credential = $Credential - } - - Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { - return @{ - Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' - DisplayName = 'Data Management' - } - } - } - - It '2.1 Should return values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Present' - } - It '2.2 Should return false from the Test method' { - Test-TargetResource @testParams | Should -Be $false - } - It '2.3 Should remove the instance from the Set method' { - Set-TargetResource @testParams - Should -Invoke -CommandName Remove-MgBetaDeviceAppManagementMobileApp -Exactly 1 - } - } - - Context -Name '3. The instance exists and values are already in the desired state' -Fixture { - BeforeAll { - $testParams = @{ - Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' - DisplayName = 'Data Management' - Ensure = 'Present' - Credential = $Credential - } - - Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { - return @{ - Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' - DisplayName = 'Data Management' - } - } - } - - It '3.0 Should return true from the Test method' { - Test-TargetResource @testParams | Should -Be $true - } - } - - Context -Name '4. The instance exists and values are NOT in the desired state' -Fixture { - BeforeAll { - $testParams = @{ - Id = "046e0b16-76ce-4b49-bf1b-1cc5bd94fb47" - DisplayName = "Data Management" - Ensure = 'Present' - Credential = $Credential - } - - Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { - return @{ - Id = "046e0b16-76ce-4b49-bf1b-1cc5bd94fb47" - DisplayName = "Data Management 1" #drift - } - } - } - - It '4.1 Should return Values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Present' - } - - It '4.2 Should return false from the Test method' { - Test-TargetResource @testParams | Should -Be $false - } - - It '4.3 Should call the Set method' { - Set-TargetResource @testParams - Should -Invoke -CommandName Update-MgBetaDeviceAppManagementMobileApp -Exactly 1 - } - } - - Context -Name '5. ReverseDSC Tests' -Fixture { - BeforeAll { - $Global:CurrentModeIsExport = $true - $Global:PartialExportFileName = "$(New-Guid).partial.ps1" - $testParams = @{ - Credential = $Credential - } - - Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { - return @{ - Id = "046e0b16-76ce-4b49-bf1b-1cc5bd94fb47" - DisplayName = "Data Management" - } - } - } - - It '5.1 Should Reverse Engineer resource from the Export method' { - $result = Export-TargetResource @testParams - $result | Should -Not -BeNullOrEmpty - } - } - } -} - -Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsIOSLobApp.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsIOSLobApp.Tests.ps1 deleted file mode 100644 index a3503a7a3d..0000000000 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsIOSLobApp.Tests.ps1 +++ /dev/null @@ -1,189 +0,0 @@ -[CmdletBinding()] -param( -) -$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` - -ChildPath '..\..\Unit' ` - -Resolve -$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` - -ChildPath '\Stubs\Microsoft365.psm1' ` - -Resolve) -$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` - -ChildPath '\Stubs\Generic.psm1' ` - -Resolve) -Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` - -ChildPath '\UnitTestHelper.psm1' ` - -Resolve) - -$CurrentScriptPath = $PSCommandPath.Split('\') -$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] -$ResourceName = $CurrentScriptName.Split('.')[1] -$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` - -DscResource $ResourceName -GenericStubModule $GenericStubPath - -Describe -Name $Global:DscHelper.DescribeHeader -Fixture { - InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { - Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope - BeforeAll { - - $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force - $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) - - Mock -CommandName Confirm-M365DSCDependencies -MockWith { - } - - Mock -CommandName New-M365DSCConnection -MockWith { - return "Credentials" - } - - # Mock Write-Host to hide output during the tests - Mock -CommandName Write-Host -MockWith { - } - - Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { - } - Mock -CommandName New-MgBetaDeviceAppManagementMobileApp -MockWith { - } - Mock -CommandName Update-MgBetaDeviceAppManagementMobileApp -MockWith { - } - Mock -CommandName Remove-MgBetaDeviceAppManagementMobileApp -MockWith { - } - - $Script:exportedInstances =$null - $Script:ExportMode = $false - } - - #Test contexts - - Context -Name '1. The instance should exist but it DOES NOT' -Fixture { - BeforeAll { - $testParams = @{ - Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' - DisplayName = 'Data Management' - Ensure = 'Present' - Credential = $Credential - } - - Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { - return $null - } - } - - It '1.1 Should return Values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' - } - It '1.2 Should return false from the Test method' { - Test-TargetResource @testParams | Should -Be $false - } - It '1.3 Should create a new instance from the Set method' { - Set-TargetResource @testParams - Should -Invoke -CommandName New-MgBetaDeviceAppManagementMobileApp -Exactly 1 - } - } - - Context -Name '2. The instance exists but it SHOULD NOT' -Fixture { - BeforeAll { - $testParams = @{ - Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' - DisplayName = 'Data Management' - Ensure = 'Absent' - Credential = $Credential - } - - Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { - return @{ - Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' - DisplayName = 'Data Management' - } - } - } - - It '2.1 Should return values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Present' - } - It '2.2 Should return false from the Test method' { - Test-TargetResource @testParams | Should -Be $false - } - It '2.3 Should remove the instance from the Set method' { - Set-TargetResource @testParams - Should -Invoke -CommandName Remove-MgBetaDeviceAppManagementMobileApp -Exactly 1 - } - } - - Context -Name '3. The instance exists and values are already in the desired state' -Fixture { - BeforeAll { - $testParams = @{ - Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' - DisplayName = 'Data Management' - Ensure = 'Present' - Credential = $Credential - } - - Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { - return @{ - Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' - DisplayName = 'Data Management' - } - } - } - - It '3.0 Should return true from the Test method' { - Test-TargetResource @testParams | Should -Be $true - } - } - - Context -Name '4. The instance exists and values are NOT in the desired state' -Fixture { - BeforeAll { - $testParams = @{ - Id = "046e0b16-76ce-4b49-bf1b-1cc5bd94fb47" - DisplayName = "Data Management" - Ensure = 'Present' - Credential = $Credential - } - - Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { - return @{ - Id = "046e0b16-76ce-4b49-bf1b-1cc5bd94fb47" - DisplayName = "Data Management 1" #drift - } - } - } - - It '4.1 Should return Values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Present' - } - - It '4.2 Should return false from the Test method' { - Test-TargetResource @testParams | Should -Be $false - } - - It '4.3 Should call the Set method' { - Set-TargetResource @testParams - Should -Invoke -CommandName Update-MgBetaDeviceAppManagementMobileApp -Exactly 1 - } - } - - Context -Name '5. ReverseDSC Tests' -Fixture { - BeforeAll { - $Global:CurrentModeIsExport = $true - $Global:PartialExportFileName = "$(New-Guid).partial.ps1" - $testParams = @{ - Credential = $Credential - } - - Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { - return @{ - Id = "046e0b16-76ce-4b49-bf1b-1cc5bd94fb47" - DisplayName = "Data Management" - } - } - } - - It '5.1 Should Reverse Engineer resource from the Export method' { - $result = Export-TargetResource @testParams - $result | Should -Not -BeNullOrEmpty - } - } - } -} - -Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope From 4a47b46cdc90ce571471e841479af685ff9eb2c8 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 9 Oct 2024 23:32:10 +0000 Subject: [PATCH 144/252] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/azure-ad/AADApplication.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/docs/resources/azure-ad/AADApplication.md b/docs/docs/resources/azure-ad/AADApplication.md index ffd452c3b2..8b9cf78dde 100644 --- a/docs/docs/resources/azure-ad/AADApplication.md +++ b/docs/docs/resources/azure-ad/AADApplication.md @@ -25,6 +25,7 @@ | **ReplyURLs** | Write | StringArray[] | Specifies the URLs that user tokens are sent to for sign in, or the redirect URIs that OAuth 2.0 authorization codes and access tokens are sent to. | | | **Owners** | Write | StringArray[] | UPN or ObjectID values of the app's owners. | | | **OnPremisesPublishing** | Write | MSFT_AADApplicationOnPremisesPublishing | Represents the set of properties required for configuring Application Proxy for this application. Configuring these properties allows you to publish your on-premises application for secure remote access. | | +| **ApplicationTemplateId** | Write | String | Identifier of the associated Application Template. | | | **Ensure** | Write | String | Specify if the Azure AD App should exist or not. | `Present`, `Absent` | | **Credential** | Write | PSCredential | Credentials for the Microsoft Graph delegated permissions. | | | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | From c9690f8316341764f42cf2a54ee0df3e356a6690 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 9 Oct 2024 23:34:59 +0000 Subject: [PATCH 145/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 9bfe6fc96c..96a76faf8f 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -757,6 +757,11 @@ "Name": "OnPremisesPublishing", "Option": "Write" }, + { + "CIMType": "String", + "Name": "ApplicationTemplateId", + "Option": "Write" + }, { "CIMType": "String", "Name": "Ensure", From e7e02f5f26ef71a592ebd2824b3fbc2095b58bc2 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 9 Oct 2024 20:37:03 -0400 Subject: [PATCH 146/252] EXOATPBuiltInProtectionRule - Initial Release --- .../MSFT_EXOATPBuiltInProtectionRule.psm1 | 379 ++++++++++++++++++ ...SFT_EXOATPBuiltInProtectionRule.schema.mof | 17 + .../readme.md | 6 + .../settings.json | 20 + .../EXOATPBuiltInProtectionRule/2-Update.ps1 | 26 ++ ...5DSC.EXOATPBuiltInProtectionRule.Tests.ps1 | 178 ++++++++ 6 files changed, 626 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPBuiltInProtectionRule/MSFT_EXOATPBuiltInProtectionRule.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPBuiltInProtectionRule/MSFT_EXOATPBuiltInProtectionRule.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPBuiltInProtectionRule/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPBuiltInProtectionRule/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOATPBuiltInProtectionRule/2-Update.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOATPBuiltInProtectionRule.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPBuiltInProtectionRule/MSFT_EXOATPBuiltInProtectionRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPBuiltInProtectionRule/MSFT_EXOATPBuiltInProtectionRule.psm1 new file mode 100644 index 0000000000..d7544cdbab --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPBuiltInProtectionRule/MSFT_EXOATPBuiltInProtectionRule.psm1 @@ -0,0 +1,379 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.String] + $Comments, + + [Parameter()] + [System.String[]] + $ExceptIfRecipientDomainIs, + + [Parameter()] + [System.String[]] + $ExceptIfSentTo, + + [Parameter()] + [System.String[]] + $ExceptIfSentToMemberOf, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'ExchangeOnline' ` + -InboundParameters $PSBoundParameters | Out-Null + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + try + { + $instance = Get-ATPBuiltInProtectionRule -Identity $Id -ErrorAction SilentlyContinue + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + Identity = $instance.Identity + ExceptIfRecipientDomainIs = [Array]$instance.ExceptIfRecipientDomainIs + ExceptIfSentTo = [Array]$instance.ExceptIfSentTo + ExceptIfSentToMemberOf = [Array]$instance.ExceptIfSentToMemberOf + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.String] + $Comments, + + [Parameter()] + [System.String[]] + $ExceptIfRecipientDomainIs, + + [Parameter()] + [System.String[]] + $ExceptIfSentTo, + + [Parameter()] + [System.String[]] + $ExceptIfSentToMemberOf, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + $setParameters.Remove('Identity') | Out-Null + + Write-Verbose -Message "Updating ATP Built-In Protection Rule {$Identity}" + Set-ATPBuiltInProtectionRule @setParameters +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.String] + $Comments, + + [Parameter()] + [System.String[]] + $ExceptIfRecipientDomainIs, + + [Parameter()] + [System.String[]] + $ExceptIfSentTo, + + [Parameter()] + [System.String[]] + $ExceptIfSentToMemberOf, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + ##TODO - Replace workload + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-ATPBuiltInProtectionRule -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + $displayedKey = $config.Id + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + Identity = $config.Identity + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPBuiltInProtectionRule/MSFT_EXOATPBuiltInProtectionRule.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPBuiltInProtectionRule/MSFT_EXOATPBuiltInProtectionRule.schema.mof new file mode 100644 index 0000000000..eaec047205 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPBuiltInProtectionRule/MSFT_EXOATPBuiltInProtectionRule.schema.mof @@ -0,0 +1,17 @@ +[ClassVersion("1.0.0.0"), FriendlyName("EXOATPBuiltInProtectionRule")] +class MSFT_EXOATPBuiltInProtectionRule : OMI_BaseResource +{ + [Key, Description("The Identity parameter specifies the rule that you want to modify. You can use any value that uniquely identifies the rule. ")] String Identity; + [Write, Description("The Comments parameter specifies informative comments for the rule, such as what the rule is used for or how it has changed over time. The length of the comment can't exceed 1024 characters.")] String Comments; + [Write, Description("The ExceptIfRecipientDomainIs parameter specifies an exception that looks for recipients with email addresses in the specified domains. You can specify multiple domains separated by commas.")] String ExceptIfRecipientDomainIs[]; + [Write, Description("The ExceptIfSentTo parameter specifies an exception that looks for recipients in messages. You can use any value that uniquely identifies the recipient.")] String ExceptIfSentTo[]; + [Write, Description("The ExceptIfSentToMemberOf parameter specifies an exception that looks for messages sent to members of groups. You can use any value that uniquely identifies the group.")] String ExceptIfSentToMemberOf[]; + + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Absent","Present"}, Values{"Absent","Present"}] string Ensure; + [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPBuiltInProtectionRule/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPBuiltInProtectionRule/readme.md new file mode 100644 index 0000000000..8d9c4188eb --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPBuiltInProtectionRule/readme.md @@ -0,0 +1,6 @@ + +# EXOATPBuiltInProtectionRule + +## Description + +Configures Defender ATP built-in protection rules. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPBuiltInProtectionRule/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPBuiltInProtectionRule/settings.json new file mode 100644 index 0000000000..7ab1550394 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPBuiltInProtectionRule/settings.json @@ -0,0 +1,20 @@ +{ + "resourceName": "EXOATPBuiltInProtectionRule", + "description": "Configures Defender ATP built-in protection rules.", + "roles": { + "read": [], + "update": [] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOATPBuiltInProtectionRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOATPBuiltInProtectionRule/2-Update.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOATPBuiltInProtectionRule/2-Update.ps1 @@ -0,0 +1,26 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOATPBuiltInProtectionRule.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOATPBuiltInProtectionRule.Tests.ps1 new file mode 100644 index 0000000000..780e0f343d --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOATPBuiltInProtectionRule.Tests.ps1 @@ -0,0 +1,178 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -GenericStubModule $GenericStubPath + +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + ##TODO - Mock any Remove/Set/New cmdlets + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + Context -Name "The instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return $null + Mock -CommandName Get-Cmdlet -MockWith { + return $null + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should create a new instance from the Set method' { + ##TODO - Replace the New-Cmdlet by the appropriate one + Set-TargetResource @testParams + Should -Invoke -CommandName New-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Absent' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should remove the instance from the Set method' { + Set-TargetResource @testParams + ##TODO - Replace the Remove-Cmdlet by the appropriate one + Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return the desired values + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return a drift + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + ##TODO - Replace the Update-Cmdlet by the appropriate one + Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope From 34578f1f6d8023eb68f394c685cecf40bcde06f0 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 9 Oct 2024 20:42:12 -0400 Subject: [PATCH 147/252] Update MSFT_EXOATPBuiltInProtectionRule.psm1 --- .../MSFT_EXOATPBuiltInProtectionRule.psm1 | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPBuiltInProtectionRule/MSFT_EXOATPBuiltInProtectionRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPBuiltInProtectionRule/MSFT_EXOATPBuiltInProtectionRule.psm1 index d7544cdbab..81087e37ee 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPBuiltInProtectionRule/MSFT_EXOATPBuiltInProtectionRule.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPBuiltInProtectionRule/MSFT_EXOATPBuiltInProtectionRule.psm1 @@ -170,7 +170,6 @@ function Set-TargetResource $currentInstance = Get-TargetResource @PSBoundParameters $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters - $setParameters.Remove('Identity') | Out-Null Write-Verbose -Message "Updating ATP Built-In Protection Rule {$Identity}" Set-ATPBuiltInProtectionRule @setParameters From 25933b67eb203db41482beba571847bb0f068d2a Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 9 Oct 2024 20:43:25 -0400 Subject: [PATCH 148/252] Update --- CHANGELOG.md | 2 ++ .../Resources/EXOATPBuiltInProtectionRule/2-Update.ps1 | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad6175a1d8..13d7238494 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,8 @@ * Initial release. * ADOPermissionGroupSettings * Initial release. +* EXOATPBuiltInProtectionRule + * Initial release. * EXOMigrationEndpoint * Initial Release * IntuneAccountProtectionPolicy diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOATPBuiltInProtectionRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOATPBuiltInProtectionRule/2-Update.ps1 index b516274848..3c3fc7ea9c 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOATPBuiltInProtectionRule/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOATPBuiltInProtectionRule/2-Update.ps1 @@ -21,6 +21,13 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + EXOATPBuiltInProtectionRule "EXOATPBuiltInProtectionRule" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + ExceptIfRecipientDomainIs = @("contoso.com","fabrikam.com"); + Identity = "ATP Built-In Protection Rule"; + TenantId = $TenantId; + } } } From e92e22c1c74f2658013718db7da79696639f66c0 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Wed, 9 Oct 2024 17:49:21 -0700 Subject: [PATCH 149/252] Fixed UTs. --- .../MSFT_IntuneDerivedCredential.psm1 | 1 + Tests/Unit/Stubs/Microsoft365.psm1 | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.psm1 index 4c004cfee1..af4ecd222e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.psm1 @@ -239,6 +239,7 @@ function Set-TargetResource { { New-MgBetaDeviceManagementDerivedCredential @SetParameters } + # UPDATE is not supported API, it always creates a new Derived Credential instance # REMOVE elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index d3fdd470e7..9679364d43 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -19348,7 +19348,7 @@ function Get-MgBetaDeviceManagementGroupPolicyConfigurationAssignment ) } -New-MgBetaDeviceManagementDerivedCredential { +function New-MgBetaDeviceManagementDerivedCredential { [CmdletBinding()] param ( @@ -19376,7 +19376,7 @@ New-MgBetaDeviceManagementDerivedCredential { ) } -Get-MgBetaDeviceManagementDerivedCredential { +function Get-MgBetaDeviceManagementDerivedCredential { [CmdletBinding()] param ( [Parameter()] @@ -19403,7 +19403,7 @@ Get-MgBetaDeviceManagementDerivedCredential { ) } -Remove-MgBetaDeviceManagementDerivedCredential +function Remove-MgBetaDeviceManagementDerivedCredential { [CmdletBinding()] param( From ad22aa691e5487c651adcd8bc4ddeea8418eebe8 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Wed, 9 Oct 2024 18:24:47 -0700 Subject: [PATCH 150/252] Fixed param names in UT stubs. --- .../Microsoft365DSC.IntuneDerivedCredential.Tests.ps1 | 7 ++----- Tests/Unit/Stubs/Microsoft365.psm1 | 6 +++--- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDerivedCredential.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDerivedCredential.Tests.ps1 index 479cb308f4..1d23b82ab7 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDerivedCredential.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDerivedCredential.Tests.ps1 @@ -45,6 +45,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } Mock -CommandName Remove-MgBetaDeviceManagementDerivedCredential -MockWith { } + $Script:exportedInstances =$null $Script:ExportMode = $false } @@ -82,7 +83,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name " 2. The instance exists but it SHOULD NOT" -Fixture { BeforeAll { $testParams = @{ - Ensure = 'Present' + Ensure = 'Absent' DisplayName = "K5"; HelpUrl = "http://www.ff.com/"; Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; @@ -175,10 +176,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } # Update is not allowed on DerivedCredential resource so it should be called 0 times. - It ' 4.3 Should call the Set method' { - Set-TargetResource @testParams - Should -Invoke -CommandName Update-MgBetaDeviceManagementDerivedCredential -Exactly 0 - } } Context -Name ' 5. ReverseDSC Tests' -Fixture { diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 9679364d43..f13aae42ff 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -19381,7 +19381,7 @@ function Get-MgBetaDeviceManagementDerivedCredential { param ( [Parameter()] [System.String] - $Id, + $DeviceManagementDerivedCredentialSettingsId, [Parameter()] [System.String] @@ -19409,7 +19409,7 @@ function Remove-MgBetaDeviceManagementDerivedCredential param( [Parameter()] [System.String] - $DerivedCredentialId, + $DeviceManagementDerivedCredentialSettingsId, [Parameter()] [System.Boolean] @@ -19422,7 +19422,7 @@ function New-MgBetaDeviceAppManagementMobileApp { param ( [Parameter()] [System.String] - $Id, + $DeviceManagementDerivedCredentialSettingsId, [Parameter()] [System.String] From 57c9974142ef0d0fd758fc18793d2071f648af2f Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 10 Oct 2024 06:39:22 -0400 Subject: [PATCH 151/252] Ready for review --- ...5DSC.EXOATPBuiltInProtectionRule.Tests.ps1 | 95 ++++--------------- 1 file changed, 19 insertions(+), 76 deletions(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOATPBuiltInProtectionRule.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOATPBuiltInProtectionRule.Tests.ps1 index 780e0f343d..ccbf521cb5 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOATPBuiltInProtectionRule.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOATPBuiltInProtectionRule.Tests.ps1 @@ -35,7 +35,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { return "Credentials" } - ##TODO - Mock any Remove/Set/New cmdlets + Mock -CommandName Set-ATPBuiltInProtectionRule -MockWith { + + } # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { @@ -44,74 +46,19 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $Script:ExportMode = $false } # Test contexts - Context -Name "The instance should exist but it DOES NOT" -Fixture { - BeforeAll { - $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; - } - - ##TODO - Mock the Get-Cmdlet to return $null - Mock -CommandName Get-Cmdlet -MockWith { - return $null - } - } - It 'Should return Values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' - } - It 'Should return false from the Test method' { - Test-TargetResource @testParams | Should -Be $false - } - - It 'Should create a new instance from the Set method' { - ##TODO - Replace the New-Cmdlet by the appropriate one - Set-TargetResource @testParams - Should -Invoke -CommandName New-Cmdlet -Exactly 1 - } - } - - Context -Name "The instance exists but it SHOULD NOT" -Fixture { - BeforeAll { - $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Absent' - Credential = $Credential; - } - - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { - return @{ - - } - } - } - It 'Should return Values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Present' - } - It 'Should return false from the Test method' { - Test-TargetResource @testParams | Should -Be $false - } - - It 'Should remove the instance from the Set method' { - Set-TargetResource @testParams - ##TODO - Replace the Remove-Cmdlet by the appropriate one - Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 - } - } Context -Name "The instance exists and values are already in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; + ExceptIfRecipientDomainIs = @("contoso.com","fabrikam.com"); + Identity = "ATP Built-In Protection Rule"; + Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return the desired values - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-ATPBuiltInProtectionRule -MockWith { return @{ - + ExceptIfRecipientDomainIs = @("contoso.com","fabrikam.com"); + Identity = "ATP Built-In Protection Rule"; } } } @@ -124,22 +71,19 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance exists and values are NOT in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; + ExceptIfRecipientDomainIs = @("fabrikam.com"); # Drift + Identity = "ATP Built-In Protection Rule"; + Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return a drift - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-ATPBuiltInProtectionRule -MockWith { return @{ - + ExceptIfRecipientDomainIs = @("contoso.com","fabrikam.com"); + Identity = "ATP Built-In Protection Rule"; } } } - It 'Should return Values from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Present' - } It 'Should return false from the Test method' { Test-TargetResource @testParams | Should -Be $false @@ -147,8 +91,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should call the Set method' { Set-TargetResource @testParams - ##TODO - Replace the Update-Cmdlet by the appropriate one - Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + Should -Invoke -CommandName Set-ATPBuiltInProtectionRule -Exactly 1 } } @@ -160,10 +103,10 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-ATPBuiltInProtectionRule -MockWith { return @{ - + ExceptIfRecipientDomainIs = @("contoso.com","fabrikam.com"); + Identity = "ATP Built-In Protection Rule"; } } } From 88435fc198ee726f5a49e5b4829404e44cefcd2f Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 10 Oct 2024 06:39:31 -0400 Subject: [PATCH 152/252] Update Microsoft365.psm1 --- Tests/Unit/Stubs/Microsoft365.psm1 | 42 ++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index c0e87b5d42..8f67cc4e02 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -95933,3 +95933,45 @@ function Invoke-MgBetaForceDomainDelete $HttpPipelineAppend ) } +function Get-ATPBuiltInProtectionRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Object] + $State + ) +} +function Set-ATPBuiltInProtectionRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Comments, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Object[]] + $ExceptIfRecipientDomainIs, + + [Parameter()] + [System.Object[]] + $ExceptIfSentTo, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object[]] + $ExceptIfSentToMemberOf + ) +} From 7fe1979fe5215218bbfa91588399278c641562d2 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 10 Oct 2024 10:56:06 +0000 Subject: [PATCH 153/252] Updated Resources and Cmdlet documentation pages --- .../exchange/EXOATPBuiltInProtectionRule.md | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 docs/docs/resources/exchange/EXOATPBuiltInProtectionRule.md diff --git a/docs/docs/resources/exchange/EXOATPBuiltInProtectionRule.md b/docs/docs/resources/exchange/EXOATPBuiltInProtectionRule.md new file mode 100644 index 0000000000..66e58b2ed8 --- /dev/null +++ b/docs/docs/resources/exchange/EXOATPBuiltInProtectionRule.md @@ -0,0 +1,88 @@ +# EXOATPBuiltInProtectionRule + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Identity** | Key | String | The Identity parameter specifies the rule that you want to modify. You can use any value that uniquely identifies the rule. | | +| **Comments** | Write | String | The Comments parameter specifies informative comments for the rule, such as what the rule is used for or how it has changed over time. The length of the comment can't exceed 1024 characters. | | +| **ExceptIfRecipientDomainIs** | Write | StringArray[] | The ExceptIfRecipientDomainIs parameter specifies an exception that looks for recipients with email addresses in the specified domains. You can specify multiple domains separated by commas. | | +| **ExceptIfSentTo** | Write | StringArray[] | The ExceptIfSentTo parameter specifies an exception that looks for recipients in messages. You can use any value that uniquely identifies the recipient. | | +| **ExceptIfSentToMemberOf** | Write | StringArray[] | The ExceptIfSentToMemberOf parameter specifies an exception that looks for messages sent to members of groups. You can use any value that uniquely identifies the group. | | +| **Ensure** | Write | String | Present ensures the instance exists, absent ensures it is removed. | `Absent`, `Present` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Configures Defender ATP built-in protection rules. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - None + +- **Update** + + - None + +## Examples + +### Example 1 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOATPBuiltInProtectionRule "EXOATPBuiltInProtectionRule" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + ExceptIfRecipientDomainIs = @("contoso.com","fabrikam.com"); + Identity = "ATP Built-In Protection Rule"; + TenantId = $TenantId; + } + } +} +``` + From e9a96225d3291a7572e935b4c5eb54663c7d00e0 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 10 Oct 2024 10:58:38 +0000 Subject: [PATCH 154/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 96a76faf8f..27d0a9feb6 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -7499,6 +7499,71 @@ } ] }, + { + "ClassName": "MSFT_EXOATPBuiltInProtectionRule", + "Parameters": [ + { + "CIMType": "String", + "Name": "Identity", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "Comments", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "ExceptIfRecipientDomainIs", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "ExceptIfSentTo", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "ExceptIfSentToMemberOf", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_EXOAtpPolicyForO365", "Parameters": [ From 3bcece0d63eaf50939cb260ad258752bd189b3cf Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 10 Oct 2024 10:59:50 +0000 Subject: [PATCH 155/252] Updated {Update} EXO Integration Tests --- .../M365DSCIntegration.EXO.Update.Tests.ps1 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 index 4a382c8f63..30dc923214 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 @@ -140,6 +140,14 @@ CertificateThumbprint = $CertificateThumbprint; ApplicationId = $ApplicationId; } + EXOATPBuiltInProtectionRule 'EXOATPBuiltInProtectionRule' + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + ExceptIfRecipientDomainIs = @("contoso.com","fabrikam.com"); + Identity = "ATP Built-In Protection Rule"; + TenantId = $TenantId; + } EXOAtpPolicyForO365 'ConfigureAntiPhishPolicy' { IsSingleInstance = "Yes" From 579594e0738939327ff1a47a4a1cd1658d70ab24 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 10 Oct 2024 12:28:55 -0400 Subject: [PATCH 156/252] AADCustomSecurityAttributeDefinition - Initial Release --- ..._AADCustomSecurityAttributeDefinition.psm1 | 486 ++++++++++++++++++ ...stomSecurityAttributeDefinition.schema.mof | 21 + .../readme.md | 6 + .../settings.json | 32 ++ .../1-Create.ps1 | 40 ++ .../2-Update.ps1 | 40 ++ .../3-Remove.ps1 | 40 ++ ...ustomSecurityAttributeDefinition.Tests.ps1 | 245 +++++++++ 8 files changed, 910 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/MSFT_AADCustomSecurityAttributeDefinition.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/MSFT_AADCustomSecurityAttributeDefinition.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADCustomSecurityAttributeDefinition/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADCustomSecurityAttributeDefinition/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADCustomSecurityAttributeDefinition/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADCustomSecurityAttributeDefinition.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/MSFT_AADCustomSecurityAttributeDefinition.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/MSFT_AADCustomSecurityAttributeDefinition.psm1 new file mode 100644 index 0000000000..e8090ba85e --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/MSFT_AADCustomSecurityAttributeDefinition.psm1 @@ -0,0 +1,486 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter(Mandatory = $true)] + [System.String] + $AttributeSet, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.Boolean] + $IsCollection, + + [Parameter()] + [System.Boolean] + $IsSearchable, + + [Parameter()] + [System.String] + $Status, + + [Parameter()] + [System.String] + $Type, + + [Parameter()] + [System.Boolean] + $UsePreDefinedValuesOnly, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters | Out-Null + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + try + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + if (-not [System.String]::IsNullOrEmpty($Id)) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Id -eq $Id} + } + if ($null -eq $instance) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Name -eq $Name} + } + } + else + { + if (-not [System.String]::IsNullOrEmpty($Id)) + { + $instance = Get-MgBetaDirectoryCustomSecurityAttributeDefinition -CustomSecurityAttributeDefinitionId $Id ` + -ErrorAction SilentlyContinue + } + if ($null -eq $instance) + { + $instance = Get-MgBetaDirectoryCustomSecurityAttributeDefinition -Filter "Name eq '$Name'" ` + -ErrorAction SilentlyContinue + } + } + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + Name = $instance.Name + AttributeSet = $instance.AttributeSet + Id = $instance.Id + Description = $instance.Description + IsCollection = $instance.IsCollection + IsSearchable = $instance.IsSearchable + Status = $instance.Status + Type = $instance.Type + UsePreDefinedValuesOnly = $instance.UsePreDefinedValuesOnly + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter(Mandatory = $true)] + [System.String] + $AttributeSet, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.Boolean] + $IsCollection, + + [Parameter()] + [System.Boolean] + $IsSearchable, + + [Parameter()] + [System.String] + $Status, + + [Parameter()] + [System.String] + $Type, + + [Parameter()] + [System.Boolean] + $UsePreDefinedValuesOnly, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + $setParameters.Remove('Id') | Out-Null + Write-Verbose -Message "Creating new Atribute Definition {$Name}" + New-MgBetaDirectoryCustomSecurityAttributeDefinition @SetParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Updating Atribute Definition {$Name}" + $setParameters.Add('CustomSecurityAttributeDefinitionId', $currentInstance.Id) + $setParameters.Remove('Id') | Out-Null + $setParameters.Remove('AttributeSet') | Out-Null + $setParameters.Remove('IsCollection') | Out-Null + $setParameters.Remove('IsSearchable') | Out-Null + $setParameters.Remove('Name') | Out-Null + $setParameters.Remove('Type') | Out-Null + Update-MgBetaDirectoryCustomSecurityAttributeDefinition @SetParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Removing Atribute Definition {$Name}. Setting its status to 'Deprecated'" + Update-MgBetaDirectoryCustomSecurityAttributeDefinition -CustomSecurityAttributeDefinitionId $currentInstance.Id ` + -Status 'Deprecated' + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter(Mandatory = $true)] + [System.String] + $AttributeSet, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.Boolean] + $IsCollection, + + [Parameter()] + [System.Boolean] + $IsSearchable, + + [Parameter()] + [System.String] + $Status, + + [Parameter()] + [System.String] + $Type, + + [Parameter()] + [System.Boolean] + $UsePreDefinedValuesOnly, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-MgBetaDirectoryCustomSecurityAttributeDefinition -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + $displayedKey = $config.Id + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + Id = $config.Id + Name = $config.Name + AttributeSet = $config.AttributeSet + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/MSFT_AADCustomSecurityAttributeDefinition.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/MSFT_AADCustomSecurityAttributeDefinition.schema.mof new file mode 100644 index 0000000000..6aebad09ae --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/MSFT_AADCustomSecurityAttributeDefinition.schema.mof @@ -0,0 +1,21 @@ +[ClassVersion("1.0.0.0"), FriendlyName("AADCustomSecurityAttributeDefinition")] +class MSFT_AADCustomSecurityAttributeDefinition : OMI_BaseResource +{ + [Key, Description("Name of the custom security attribute. Must be unique within an attribute set. Can be up to 32 characters long and include Unicode characters. Can't contain spaces or special characters. Can't be changed later. Case sensitive.")] String Name; + [Write, Description("Name of the attribute set. Case sensitive.")] String AttributeSet; + [Write, Description("Unique identifier of the Attribute Definition.")] String Id; + [Write, Description("Description of the custom security attribute. Can be up to 128 characters long and include Unicode characters. Can't contain spaces or special characters. Can be changed later. ")] String Description; + [Write, Description("Indicates whether multiple values can be assigned to the custom security attribute. Can't be changed later. If type is set to Boolean, isCollection can't be set to true.")] Boolean IsCollection; + [Write, Description("Indicates whether custom security attribute values are indexed for searching on objects that are assigned attribute values. Can't be changed later.")] Boolean IsSearchable; + [Write, Description("Specifies whether the custom security attribute is active or deactivated. Acceptable values are Available and Deprecated. Can be changed later.")] String Status; + [Write, Description("Data type for the custom security attribute values. Supported types are: Boolean, Integer, and String. Can't be changed later.")] String Type; + [Write, Description("Indicates whether only predefined values can be assigned to the custom security attribute. If set to false, free-form values are allowed. Can later be changed from true to false, but can't be changed from false to true. If type is set to Boolean, usePreDefinedValuesOnly can't be set to true.")] Boolean UsePreDefinedValuesOnly; + + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Absent","Present"}, Values{"Absent","Present"}] string Ensure; + [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/readme.md new file mode 100644 index 0000000000..32e0e7fb27 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/readme.md @@ -0,0 +1,6 @@ + +# ResourceName + +## Description + +##TODO - Provide a short description of what the resource is set to configure. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/settings.json new file mode 100644 index 0000000000..edf14b05e4 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName": "ResourceName", + "description": "Description of what the resource is about.", + "roles": { + "read": [ + "Role" + ], + "update": [ + "Role" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [ + { + "name": "Permission for Monitoring and Export" + } + ], + "update": [ + { + "name": "Permission for deploying" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADCustomSecurityAttributeDefinition/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADCustomSecurityAttributeDefinition/1-Create.ps1 new file mode 100644 index 0000000000..7aa18c60ea --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADCustomSecurityAttributeDefinition/1-Create.ps1 @@ -0,0 +1,40 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADCustomSecurityAttributeDefinition "AADCustomSecurityAttributeDefinition-ShoeSize" + { + ApplicationId = $ApplicationId; + AttributeSet = "TestAttributeSet"; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Present"; + IsCollection = $False; + IsSearchable = $True; + Name = "ShoeSize"; + Status = "Available"; + TenantId = $TenantId; + Type = "String"; + UsePreDefinedValuesOnly = $False; + Description = "What size of shoe is the person wearing?" + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADCustomSecurityAttributeDefinition/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADCustomSecurityAttributeDefinition/2-Update.ps1 new file mode 100644 index 0000000000..273be2450a --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADCustomSecurityAttributeDefinition/2-Update.ps1 @@ -0,0 +1,40 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADCustomSecurityAttributeDefinition "AADCustomSecurityAttributeDefinition-ShoeSize" + { + ApplicationId = $ApplicationId; + AttributeSet = "TestAttributeSet"; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Present"; + IsCollection = $False; + IsSearchable = $True; + Name = "ShoeSize"; + Status = "Available"; + TenantId = $TenantId; + Type = "String"; + UsePreDefinedValuesOnly = $False; + Description = "What size of shoe is the person wearing? Drifted" # Drift + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADCustomSecurityAttributeDefinition/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADCustomSecurityAttributeDefinition/3-Remove.ps1 new file mode 100644 index 0000000000..9e94cd62e5 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADCustomSecurityAttributeDefinition/3-Remove.ps1 @@ -0,0 +1,40 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADCustomSecurityAttributeDefinition "AADCustomSecurityAttributeDefinition-ShoeSize" + { + ApplicationId = $ApplicationId; + AttributeSet = "TestAttributeSet"; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Absent"; + IsCollection = $False; + IsSearchable = $True; + Name = "ShoeSize"; + Status = "Available"; + TenantId = $TenantId; + Type = "String"; + UsePreDefinedValuesOnly = $False; + Description = "What size of shoe is the person wearing?" + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADCustomSecurityAttributeDefinition.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADCustomSecurityAttributeDefinition.Tests.ps1 new file mode 100644 index 0000000000..1d91bcc2b5 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADCustomSecurityAttributeDefinition.Tests.ps1 @@ -0,0 +1,245 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -GenericStubModule $GenericStubPath + +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + Mock -CommandName New-MgBetaDirectoryCustomSecurityAttributeDefinition -MockWith{} + + Mock -CommandName Update-MgBetaDirectoryCustomSecurityAttributeDefinition -MockWith{} + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + Context -Name "The instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + ApplicationId = $ApplicationId; + AttributeSet = "ContosoSet"; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Present"; + IsCollection = $False; + IsSearchable = $True; + Name = "ShoeSize"; + Status = "Available"; + TenantId = $TenantId; + Type = "String"; + UsePreDefinedValuesOnly = $False; + Description = "What size of shoe is the person wearing?" + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDirectoryCustomSecurityAttributeDefinition -MockWith { + return $null + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should create a new instance from the Set method' { + ##TODO - Replace the New-Cmdlet by the appropriate one + Set-TargetResource @testParams + Should -Invoke -CommandName New-MgBetaDirectoryCustomSecurityAttributeDefinition -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + ApplicationId = $ApplicationId; + AttributeSet = "ContosoSet"; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Absent"; + IsCollection = $False; + IsSearchable = $True; + Name = "ShoeSize"; + Status = "Available"; + TenantId = $TenantId; + Type = "String"; + UsePreDefinedValuesOnly = $False; + Description = "What size of shoe is the person wearing?" + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDirectoryCustomSecurityAttributeDefinition -MockWith { + return @{ + AttributeSet = 'ContosoSet' + IsCollection = $false + IsSearchable = $true + Name = "ShoeSize"; + Status = "Available"; + Type = "String"; + UsePreDefinedValuesOnly = $False; + Description = "What size of shoe is the person wearing?" + Id = "ContosoSet_ShoeSize" + } + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should remove the instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Update-MgBetaDirectoryCustomSecurityAttributeDefinition -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ApplicationId = $ApplicationId; + AttributeSet = "ContosoSet"; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Present"; + IsCollection = $False; + IsSearchable = $True; + Name = "ShoeSize"; + Status = "Available"; + TenantId = $TenantId; + Type = "String"; + UsePreDefinedValuesOnly = $False; + Description = "What size of shoe is the person wearing?" + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDirectoryCustomSecurityAttributeDefinition -MockWith { + return @{ + AttributeSet = 'ContosoSet' + IsCollection = $false + IsSearchable = $true + Name = "ShoeSize"; + Status = "Available"; + Type = "String"; + UsePreDefinedValuesOnly = $False; + Description = "What size of shoe is the person wearing?" + Id = "ContosoSet_ShoeSize" + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ApplicationId = $ApplicationId; + AttributeSet = "ContosoSet"; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Absent"; + IsCollection = $False; + IsSearchable = $True; + Name = "ShoeSize"; + Status = "Available"; + TenantId = $TenantId; + Type = "String"; + UsePreDefinedValuesOnly = $False; + Description = "What size of shoe is the person wearing? Drift" # drift + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDirectoryCustomSecurityAttributeDefinition -MockWith { + return @{ + AttributeSet = 'ContosoSet' + IsCollection = $false + IsSearchable = $true + Name = "ShoeSize"; + Status = "Available"; + Type = "String"; + UsePreDefinedValuesOnly = $False; + Description = "What size of shoe is the person wearing?" + Id = "ContosoSet_ShoeSize" + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Update-MgBetaDirectoryCustomSecurityAttributeDefinition -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDirectoryCustomSecurityAttributeDefinition -MockWith { + return @{ + AttributeSet = 'ContosoSet' + IsCollection = $false + IsSearchable = $true + Name = "ShoeSize"; + Status = "Available"; + Type = "String"; + UsePreDefinedValuesOnly = $False; + Description = "What size of shoe is the person wearing?" + Id = "ContosoSet_ShoeSize" + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope From 45666c69bdcc770e37dd14c7c573385909791afd Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 10 Oct 2024 12:29:03 -0400 Subject: [PATCH 157/252] Updates --- CHANGELOG.md | 2 + Tests/Unit/Stubs/Microsoft365.psm1 | 187 +++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13d7238494..df501deccd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ * Initial release. * AADConnectorGroupApplicationProxy * Initial release. +* AADCustomSecurityAttributeDefinition + * Initial release. * AADDeviceRegistrationPolicy * Initial release. * AADEntitlementManagementSettings diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 8f67cc4e02..d222e03e89 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -95975,3 +95975,190 @@ function Set-ATPBuiltInProtectionRule $ExceptIfSentToMemberOf ) } + +function Update-MgBetaDirectoryCustomSecurityAttributeDefinition +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [PSObject] + $AllowedValues, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $UsePreDefinedValuesOnly, + + [Parameter()] + [System.String] + $AttributeSet, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsSearchable, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $Status, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsCollection, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.String] + $CustomSecurityAttributeDefinitionId, + + [Parameter()] + [System.String] + $Type, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function New-MgBetaDirectoryCustomSecurityAttributeDefinition +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [PSObject] + $AllowedValues, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $UsePreDefinedValuesOnly, + + [Parameter()] + [System.String] + $AttributeSet, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsSearchable, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $Status, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.String] + $Type, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsCollection, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} From 9718e60ea21972f3683e57a905e891a1d913d648 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 10 Oct 2024 12:46:57 -0400 Subject: [PATCH 158/252] Fixes permissions --- .../readme.md | 4 ++-- .../settings.json | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/readme.md index 32e0e7fb27..79eaf29c71 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/readme.md @@ -1,6 +1,6 @@ -# ResourceName +# AADCustomSecurityAttributeDefinition ## Description -##TODO - Provide a short description of what the resource is set to configure. +Configures custom security attribute definitions in Entra Id. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/settings.json index edf14b05e4..9381adbf42 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/settings.json @@ -1,12 +1,12 @@ { - "resourceName": "ResourceName", - "description": "Description of what the resource is about.", + "resourceName": "AADCustomSecurityAttributeDefinition", + "description": "Configures custom security attribute definitions in Entra Id.", "roles": { "read": [ - "Role" + "Attribute Definition Reader" ], "update": [ - "Role" + "Attribute Definition Administrator" ] }, "permissions": { @@ -18,12 +18,12 @@ "application": { "read": [ { - "name": "Permission for Monitoring and Export" + "name": "CustomSecAttributeDefinition.Read.All" } ], "update": [ { - "name": "Permission for deploying" + "name": "CustomSecAttributeDefinition.ReadWrite.All" } ] } From 077416cf58e815bc1facb8c52711a4ed138ea2d2 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 10 Oct 2024 16:52:01 +0000 Subject: [PATCH 159/252] Updated Resources and Cmdlet documentation pages --- .../intune/IntuneMobileAppsMacOSLobApp.md | 96 +++++++++++-------- 1 file changed, 54 insertions(+), 42 deletions(-) diff --git a/docs/docs/resources/intune/IntuneMobileAppsMacOSLobApp.md b/docs/docs/resources/intune/IntuneMobileAppsMacOSLobApp.md index de60700954..42df970079 100644 --- a/docs/docs/resources/intune/IntuneMobileAppsMacOSLobApp.md +++ b/docs/docs/resources/intune/IntuneMobileAppsMacOSLobApp.md @@ -14,13 +14,14 @@ | **Owner** | Write | String | The owner of the app. Inherited from mobileApp. | | | **PrivacyInformationUrl** | Write | String | The privacy statement Url. Inherited from mobileApp. | | | **Publisher** | Write | String | The publisher of the app. Inherited from mobileApp. | | -| **PublishingState** | Write | String | The publishing state for the app. The app cannot be assigned unless the app is published. Inherited from mobileApp. | `notPublished`, `processing`, `published` | | **BundleId** | Write | String | The bundleId of the app. | | | **BuildNumber** | Write | String | The build number of the app. | | | **VersionNumber** | Write | String | The version number of the app. | | | **RoleScopeTagIds** | Write | StringArray[] | List of Scope Tag IDs for mobile app. | | -| **IgnoreVersionDetection** | Write | Boolean | Wether to ignore the version of the app or not. | | +| **IgnoreVersionDetection** | Write | Boolean | Whether to ignore the version of the app or not. | | +| **InstallAsManaged** | Write | Boolean | Install the app as managed. Requires macOS 11.0. | | | **LargeIcon** | Write | MSFT_DeviceManagementMimeContent | The icon for this app. | | +| **MinimumSupportedOperatingSystem** | Write | MSFT_DeviceManagementMinimumOperatingSystem | The minimum supported operating system to install the app. | | | **Categories** | Write | MSFT_DeviceManagementMobileAppCategory[] | The list of categories for this app. | | | **Assignments** | Write | MSFT_DeviceManagementMobileAppAssignment[] | The list of assignments for this app. | | | **ChildApps** | Write | MSFT_DeviceManagementMobileAppChildApp[] | The list of child apps for this app package. | | @@ -33,47 +34,66 @@ | **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | | **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | -### MSFT_DeviceManagementMimeContent +### MSFT_DeviceManagementMobileAppAssignment #### Parameters | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | -| **type** | Write | String | Indicates the type of content mime. | | -| **value** | Write | StringArray[] | The byte array that contains the actual content. | | +| **dataType** | Write | String | The type of the target assignment. | `#microsoft.graph.groupAssignmentTarget`, `#microsoft.graph.allLicensedUsersAssignmentTarget`, `#microsoft.graph.allDevicesAssignmentTarget`, `#microsoft.graph.exclusionGroupAssignmentTarget`, `#microsoft.graph.mobileAppAssignment` | +| **deviceAndAppManagementAssignmentFilterId** | Write | String | The Id of the filter for the target assignment. | | +| **deviceAndAppManagementAssignmentFilterType** | Write | String | The type of filter of the target assignment i.e. Exclude or Include. Possible values are: none, include, exclude. | `none`, `include`, `exclude` | +| **groupId** | Write | String | The group Id that is the target of the assignment. | | +| **groupDisplayName** | Write | String | The group Display Name that is the target of the assignment. | | +| **intent** | Write | String | Possible values for the install intent chosen by the admin. | `available`, `required`, `uninstall`, `availableWithoutEnrollment` | -### MSFT_DeviceManagementMobileAppCategory +### MSFT_DeviceManagementMinimumOperatingSystem #### Parameters | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | -| **displayName** | Key | String | The name of the app category. | | -| **id** | Write | String | The unique identifier for an entity. Read-only. | | +| **v10_7** | Write | Boolean | Indicates if Mac OS X 10.7 or later is required to install the app. | | +| **v10_8** | Write | Boolean | Indicates if Mac OS X 10.8 or later is required to install the app. | | +| **v10_9** | Write | Boolean | Indicates if Mac OS X 10.9 or later is required to install the app. | | +| **v10_10** | Write | Boolean | Indicates if Mac OS X 10.10 or later is required to install the app. | | +| **v10_11** | Write | Boolean | Indicates if Mac OS X 10.11 or later is required to install the app. | | +| **v10_12** | Write | Boolean | Indicates if Mac OS X 10.12 or later is required to install the app. | | +| **v10_13** | Write | Boolean | Indicates if Mac OS X 10.13 or later is required to install the app. | | +| **v10_14** | Write | Boolean | Indicates if Mac OS X 10.14 or later is required to install the app. | | +| **v10_15** | Write | Boolean | Indicates if Mac OS X 10.15 or later is required to install the app. | | +| **v11_0** | Write | Boolean | Indicates if Mac OS X 11.0 or later is required to install the app. | | +| **v12_0** | Write | Boolean | Indicates if Mac OS X 12.0 or later is required to install the app. | | +| **v13_0** | Write | Boolean | Indicates if Mac OS X 13.0 or later is required to install the app. | | +| **v14_0** | Write | Boolean | Indicates if Mac OS X 14.0 or later is required to install the app. | | -### MSFT_DeviceManagementMobileAppChildApp +### MSFT_DeviceManagementMimeContent #### Parameters | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | -| **bundleId** | Write | String | The bundleId of the app. | | -| **buildNumber** | Write | String | The build number of the app. | | -| **versionNumber** | Write | String | The version number of the app. | | +| **Type** | Write | String | Indicates the type of content mime. | | +| **Value** | Write | String | The Base64 encoded string content. | | -### MSFT_DeviceManagementMobileAppAssignment +### MSFT_DeviceManagementMobileAppCategory #### Parameters | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | -| **dataType** | Write | String | The type of the target assignment. | `#microsoft.graph.groupAssignmentTarget`, `#microsoft.graph.allLicensedUsersAssignmentTarget`, `#microsoft.graph.allDevicesAssignmentTarget`, `#microsoft.graph.exclusionGroupAssignmentTarget`, `#microsoft.graph.mobileAppAssignment` | -| **deviceAndAppManagementAssignmentFilterId** | Write | String | The Id of the filter for the target assignment. | | -| **deviceAndAppManagementAssignmentFilterType** | Write | String | The type of filter of the target assignment i.e. Exclude or Include. Possible values are: none, include, exclude. | `none`, `include`, `exclude` | -| **groupId** | Write | String | The group Id that is the target of the assignment. | | -| **groupDisplayName** | Write | String | The group Display Name that is the target of the assignment. | | -| **intent** | Write | String | Possible values for the install intent chosen by the admin. | `available`, `required`, `uninstall`, `availableWithoutEnrollment` | -| **source** | Write | String | The source of this assignment. | | +| **DisplayName** | Key | String | The name of the app category. | | +| **Id** | Write | String | The unique identifier for an entity. Read-only. | | + +### MSFT_DeviceManagementMobileAppChildApp + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **BundleId** | Write | String | The bundleId of the app. | | +| **BuildNumber** | Write | String | The build number of the app. | | +| **VersionNumber** | Write | String | The version number of the app. | | ## Description @@ -142,30 +162,31 @@ Configuration Example Ensure = "Present"; InformationUrl = ""; IsFeatured = $False; + MinimumSupportedOperatingSystem = MSFT_DeviceManagementMinimumOperatingSystem{ + v11_0 = $true + } Notes = ""; Owner = ""; PrivacyInformationUrl = ""; Publisher = "Contoso"; - PublishingState = "published"; Assignments = @( MSFT_DeviceManagementMobileAppAssignment{ - groupDisplayName = 'All devices' - source = 'direct' + groupDisplayName = 'All devices' deviceAndAppManagementAssignmentFilterType = 'none' dataType = '#microsoft.graph.allDevicesAssignmentTarget' intent = 'required' } MSFT_DeviceManagementMobileAppAssignment{ deviceAndAppManagementAssignmentFilterType = 'none' - source = 'direct' dataType = '#microsoft.graph.groupAssignmentTarget' groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' intent = 'required' } ); - Categories = @(MSFT_DeviceManagementMobileAppCategory { - id = '1bff2652-03ec-4a48-941c-152e93736515' - displayName = 'Kajal 3' + Categories = @( + MSFT_DeviceManagementMobileAppCategory { + Id = '1bff2652-03ec-4a48-941c-152e93736515' + DisplayName = 'Kajal 3' }); } } @@ -206,30 +227,30 @@ Configuration Example Ensure = "Present"; InformationUrl = ""; IsFeatured = $False; + MinimumSupportedOperatingSystem = MSFT_DeviceManagementMinimumOperatingSystem{ + v11_0 = $true + } Notes = ""; Owner = ""; PrivacyInformationUrl = ""; Publisher = "Contoso"; - PublishingState = "published"; Assignments = @( MSFT_DeviceManagementMobileAppAssignment{ - groupDisplayName = 'All devices' - source = 'direct' + groupDisplayName = 'All devices' deviceAndAppManagementAssignmentFilterType = 'none' dataType = '#microsoft.graph.allDevicesAssignmentTarget' intent = 'required' } MSFT_DeviceManagementMobileAppAssignment{ deviceAndAppManagementAssignmentFilterType = 'none' - source = 'direct' dataType = '#microsoft.graph.groupAssignmentTarget' groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' intent = 'required' } ); Categories = @(MSFT_DeviceManagementMobileAppCategory { - id = '1bff2652-03ec-4a48-941c-152e93736515' - displayName = 'Kajal 3' + Id = '1bff2652-03ec-4a48-941c-152e93736515' + DisplayName = 'Kajal 3' }); } } @@ -264,17 +285,8 @@ Configuration Example IntuneMobileAppsMacOSLobApp "IntuneMobileAppsMacOSLobApp-TeamsForBusinessInstaller" { Id = "8d027f94-0682-431e-97c1-827d1879fa79"; - Description = "TeamsForBusinessInstaller"; - Developer = "Contoso"; DisplayName = "TeamsForBusinessInstaller"; Ensure = "Absent"; - InformationUrl = ""; - IsFeatured = $False; - Notes = ""; - Owner = ""; - PrivacyInformationUrl = ""; - Publisher = "Contoso"; - PublishingState = "published"; } } } From 17897e50e9007cd558fc90833135ed91b7736cdc Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 10 Oct 2024 16:54:38 +0000 Subject: [PATCH 160/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 248 +++++++++++------- 1 file changed, 159 insertions(+), 89 deletions(-) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 27d0a9feb6..c3ba07eb30 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -35400,63 +35400,143 @@ ] }, { - "ClassName": "MSFT_IntuneMobileAppsMacOSLobApp", + "ClassName": "MSFT_DeviceManagementMobileAppAssignment", "Parameters": [ { "CIMType": "String", - "Name": "DisplayName", - "Option": "Key" + "Name": "dataType", + "Option": "Write" }, { "CIMType": "String", - "Name": "Id", + "Name": "deviceAndAppManagementAssignmentFilterId", "Option": "Write" }, { "CIMType": "String", - "Name": "Description", + "Name": "deviceAndAppManagementAssignmentFilterType", "Option": "Write" }, { "CIMType": "String", - "Name": "Developer", + "Name": "groupId", "Option": "Write" }, { "CIMType": "String", - "Name": "InformationUrl", + "Name": "groupDisplayName", "Option": "Write" }, + { + "CIMType": "String", + "Name": "intent", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_DeviceManagementMinimumOperatingSystem", + "Parameters": [ { "CIMType": "Boolean", - "Name": "IsFeatured", + "Name": "v10_7", "Option": "Write" }, { - "CIMType": "String", - "Name": "Notes", + "CIMType": "Boolean", + "Name": "v10_8", "Option": "Write" }, { - "CIMType": "String", - "Name": "Owner", + "CIMType": "Boolean", + "Name": "v10_9", "Option": "Write" }, { - "CIMType": "String", - "Name": "PrivacyInformationUrl", + "CIMType": "Boolean", + "Name": "v10_10", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "v10_11", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "v10_12", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "v10_13", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "v10_14", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "v10_15", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "v11_0", "Option": "Write" }, + { + "CIMType": "Boolean", + "Name": "v12_0", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "v13_0", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "v14_0", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_DeviceManagementMimeContent", + "Parameters": [ { "CIMType": "String", - "Name": "Publisher", + "Name": "Type", "Option": "Write" }, { "CIMType": "String", - "Name": "PublishingState", + "Name": "Value", "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_DeviceManagementMobileAppCategory", + "Parameters": [ + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Key" }, + { + "CIMType": "String", + "Name": "Id", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_DeviceManagementMobileAppChildApp", + "Parameters": [ { "CIMType": "String", "Name": "BundleId", @@ -35471,165 +35551,155 @@ "CIMType": "String", "Name": "VersionNumber", "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_IntuneMobileAppsMacOSLobApp", + "Parameters": [ + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Key" }, { - "CIMType": "String[]", - "Name": "RoleScopeTagIds", + "CIMType": "String", + "Name": "Id", "Option": "Write" }, { - "CIMType": "Boolean", - "Name": "IgnoreVersionDetection", + "CIMType": "String", + "Name": "Description", "Option": "Write" }, { - "CIMType": "MSFT_DeviceManagementMimeContent", - "Name": "LargeIcon", + "CIMType": "String", + "Name": "Developer", "Option": "Write" }, { - "CIMType": "MSFT_DeviceManagementMobileAppCategory[]", - "Name": "Categories", + "CIMType": "String", + "Name": "InformationUrl", "Option": "Write" }, { - "CIMType": "MSFT_DeviceManagementMobileAppAssignment[]", - "Name": "Assignments", + "CIMType": "Boolean", + "Name": "IsFeatured", "Option": "Write" }, { - "CIMType": "MSFT_DeviceManagementMobileAppChildApp[]", - "Name": "ChildApps", + "CIMType": "String", + "Name": "Notes", "Option": "Write" }, { "CIMType": "String", - "Name": "Ensure", + "Name": "Owner", "Option": "Write" }, { - "CIMType": "MSFT_Credential", - "Name": "Credential", + "CIMType": "String", + "Name": "PrivacyInformationUrl", "Option": "Write" }, { "CIMType": "String", - "Name": "ApplicationId", + "Name": "Publisher", "Option": "Write" }, { "CIMType": "String", - "Name": "TenantId", + "Name": "BundleId", "Option": "Write" }, { - "CIMType": "MSFT_Credential", - "Name": "ApplicationSecret", + "CIMType": "String", + "Name": "BuildNumber", "Option": "Write" }, { "CIMType": "String", - "Name": "CertificateThumbprint", + "Name": "VersionNumber", "Option": "Write" }, { - "CIMType": "Boolean", - "Name": "ManagedIdentity", + "CIMType": "String[]", + "Name": "RoleScopeTagIds", "Option": "Write" }, { - "CIMType": "String[]", - "Name": "AccessTokens", + "CIMType": "Boolean", + "Name": "IgnoreVersionDetection", "Option": "Write" - } - ] - }, - { - "ClassName": "MSFT_DeviceManagementMimeContent", - "Parameters": [ + }, { - "CIMType": "String", - "Name": "type", + "CIMType": "Boolean", + "Name": "InstallAsManaged", "Option": "Write" }, { - "CIMType": "String[]", - "Name": "value", + "CIMType": "MSFT_DeviceManagementMimeContent", + "Name": "LargeIcon", "Option": "Write" - } - ] - }, - { - "ClassName": "MSFT_DeviceManagementMobileAppCategory", - "Parameters": [ + }, { - "CIMType": "String", - "Name": "displayName", - "Option": "Key" + "CIMType": "MSFT_DeviceManagementMinimumOperatingSystem", + "Name": "MinimumSupportedOperatingSystem", + "Option": "Write" }, { - "CIMType": "String", - "Name": "id", + "CIMType": "MSFT_DeviceManagementMobileAppCategory[]", + "Name": "Categories", "Option": "Write" - } - ] - }, - { - "ClassName": "MSFT_DeviceManagementMobileAppChildApp", - "Parameters": [ + }, { - "CIMType": "String", - "Name": "bundleId", + "CIMType": "MSFT_DeviceManagementMobileAppAssignment[]", + "Name": "Assignments", "Option": "Write" }, { - "CIMType": "String", - "Name": "buildNumber", + "CIMType": "MSFT_DeviceManagementMobileAppChildApp[]", + "Name": "ChildApps", "Option": "Write" }, { "CIMType": "String", - "Name": "versionNumber", + "Name": "Ensure", "Option": "Write" - } - ] - }, - { - "ClassName": "MSFT_DeviceManagementMobileAppAssignment", - "Parameters": [ + }, { - "CIMType": "String", - "Name": "dataType", + "CIMType": "MSFT_Credential", + "Name": "Credential", "Option": "Write" }, { "CIMType": "String", - "Name": "deviceAndAppManagementAssignmentFilterId", + "Name": "ApplicationId", "Option": "Write" }, { "CIMType": "String", - "Name": "deviceAndAppManagementAssignmentFilterType", + "Name": "TenantId", "Option": "Write" }, { - "CIMType": "String", - "Name": "groupId", + "CIMType": "MSFT_Credential", + "Name": "ApplicationSecret", "Option": "Write" }, { "CIMType": "String", - "Name": "groupDisplayName", + "Name": "CertificateThumbprint", "Option": "Write" }, { - "CIMType": "String", - "Name": "intent", + "CIMType": "Boolean", + "Name": "ManagedIdentity", "Option": "Write" }, { - "CIMType": "String", - "Name": "source", + "CIMType": "String[]", + "Name": "AccessTokens", "Option": "Write" } ] From f148d94b3d39c2fa7bd6c9a9a40b37ca4b41f020 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 10 Oct 2024 16:55:14 +0000 Subject: [PATCH 161/252] Updated {Create} Intune Integration Tests --- .../M365DSCIntegration.INTUNE.Create.Tests.ps1 | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 index f4c2a0dab7..26e65f5d12 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 @@ -2534,30 +2534,31 @@ Ensure = "Present"; InformationUrl = ""; IsFeatured = $False; + MinimumSupportedOperatingSystem = MSFT_DeviceManagementMinimumOperatingSystem{ + v11_0 = $true + } Notes = ""; Owner = ""; PrivacyInformationUrl = ""; Publisher = "Contoso"; - PublishingState = "published"; Assignments = @( MSFT_DeviceManagementMobileAppAssignment{ - groupDisplayName = 'All devices' - source = 'direct' + groupDisplayName = 'All devices' deviceAndAppManagementAssignmentFilterType = 'none' dataType = '#microsoft.graph.allDevicesAssignmentTarget' intent = 'required' } MSFT_DeviceManagementMobileAppAssignment{ deviceAndAppManagementAssignmentFilterType = 'none' - source = 'direct' dataType = '#microsoft.graph.groupAssignmentTarget' groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' intent = 'required' } ); - Categories = @(MSFT_DeviceManagementMobileAppCategory { - id = '1bff2652-03ec-4a48-941c-152e93736515' - displayName = 'Kajal 3' + Categories = @( + MSFT_DeviceManagementMobileAppCategory { + Id = '1bff2652-03ec-4a48-941c-152e93736515' + DisplayName = 'Kajal 3' }); } IntunePolicySets 'Example' From de78e944560c47eb0ac725083187a7c1293b89b3 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 10 Oct 2024 13:01:34 -0400 Subject: [PATCH 162/252] Update Microsoft365.psm1 --- Tests/Unit/Stubs/Microsoft365.psm1 | 86 ++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index d222e03e89..4a12b257c4 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -96162,3 +96162,89 @@ function New-MgBetaDirectoryCustomSecurityAttributeDefinition $HttpPipelineAppend ) } + +function Get-MgBetaDirectoryCustomSecurityAttributeDefinition +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.String] + $CustomSecurityAttributeDefinitionId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} From 803e6b998d826326757c81058ec41ae8e6e0c511 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 10 Oct 2024 17:22:51 +0000 Subject: [PATCH 163/252] Updated Resources and Cmdlet documentation pages --- .../AADCustomSecurityAttributeDefinition.md | 185 ++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 docs/docs/resources/azure-ad/AADCustomSecurityAttributeDefinition.md diff --git a/docs/docs/resources/azure-ad/AADCustomSecurityAttributeDefinition.md b/docs/docs/resources/azure-ad/AADCustomSecurityAttributeDefinition.md new file mode 100644 index 0000000000..d1da8c4e1f --- /dev/null +++ b/docs/docs/resources/azure-ad/AADCustomSecurityAttributeDefinition.md @@ -0,0 +1,185 @@ +# AADCustomSecurityAttributeDefinition + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Name** | Key | String | Name of the custom security attribute. Must be unique within an attribute set. Can be up to 32 characters long and include Unicode characters. Can't contain spaces or special characters. Can't be changed later. Case sensitive. | | +| **AttributeSet** | Write | String | Name of the attribute set. Case sensitive. | | +| **Id** | Write | String | Unique identifier of the Attribute Definition. | | +| **Description** | Write | String | Description of the custom security attribute. Can be up to 128 characters long and include Unicode characters. Can't contain spaces or special characters. Can be changed later. | | +| **IsCollection** | Write | Boolean | Indicates whether multiple values can be assigned to the custom security attribute. Can't be changed later. If type is set to Boolean, isCollection can't be set to true. | | +| **IsSearchable** | Write | Boolean | Indicates whether custom security attribute values are indexed for searching on objects that are assigned attribute values. Can't be changed later. | | +| **Status** | Write | String | Specifies whether the custom security attribute is active or deactivated. Acceptable values are Available and Deprecated. Can be changed later. | | +| **Type** | Write | String | Data type for the custom security attribute values. Supported types are: Boolean, Integer, and String. Can't be changed later. | | +| **UsePreDefinedValuesOnly** | Write | Boolean | Indicates whether only predefined values can be assigned to the custom security attribute. If set to false, free-form values are allowed. Can later be changed from true to false, but can't be changed from false to true. If type is set to Boolean, usePreDefinedValuesOnly can't be set to true. | | +| **Ensure** | Write | String | Present ensures the instance exists, absent ensures it is removed. | `Absent`, `Present` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Configures custom security attribute definitions in Entra Id. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - CustomSecAttributeDefinition.Read.All + +- **Update** + + - CustomSecAttributeDefinition.ReadWrite.All + +## Examples + +### Example 1 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADCustomSecurityAttributeDefinition "AADCustomSecurityAttributeDefinition-ShoeSize" + { + ApplicationId = $ApplicationId; + AttributeSet = "TestAttributeSet"; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Present"; + IsCollection = $False; + IsSearchable = $True; + Name = "ShoeSize"; + Status = "Available"; + TenantId = $TenantId; + Type = "String"; + UsePreDefinedValuesOnly = $False; + Description = "What size of shoe is the person wearing?" + } + } +} +``` + +### Example 2 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADCustomSecurityAttributeDefinition "AADCustomSecurityAttributeDefinition-ShoeSize" + { + ApplicationId = $ApplicationId; + AttributeSet = "TestAttributeSet"; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Present"; + IsCollection = $False; + IsSearchable = $True; + Name = "ShoeSize"; + Status = "Available"; + TenantId = $TenantId; + Type = "String"; + UsePreDefinedValuesOnly = $False; + Description = "What size of shoe is the person wearing? Drifted" # Drift + } + } +} +``` + +### Example 3 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADCustomSecurityAttributeDefinition "AADCustomSecurityAttributeDefinition-ShoeSize" + { + ApplicationId = $ApplicationId; + AttributeSet = "TestAttributeSet"; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Absent"; + IsCollection = $False; + IsSearchable = $True; + Name = "ShoeSize"; + Status = "Available"; + TenantId = $TenantId; + Type = "String"; + UsePreDefinedValuesOnly = $False; + Description = "What size of shoe is the person wearing?" + } + } +} +``` + From 1d0c5d467e9be1951ab052b20ae94a081967de41 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 10 Oct 2024 17:23:07 +0000 Subject: [PATCH 164/252] Updated {Create} AAD Integration Tests --- .../M365DSCIntegration.AAD.Create.Tests.ps1 | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 index c51f4401d2..828bde930b 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 @@ -191,6 +191,36 @@ CertificateThumbprint = $CertificateThumbprint Ensure = "Present"; } + AADCustomSecurityAttributeDefinition 'AADCustomSecurityAttributeDefinition-ShoeSize' + { + ApplicationId = $ApplicationId; + AttributeSet = "TestAttributeSet"; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Present"; + IsCollection = $False; + IsSearchable = $True; + Name = "ShoeSize"; + Status = "Available"; + TenantId = $TenantId; + Type = "String"; + UsePreDefinedValuesOnly = $False; + Description = "What size of shoe is the person wearing?" + } + AADDomain 'AADDomain-Contoso' + { + ApplicationId = $ApplicationId; + AuthenticationType = "Managed"; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Present"; + Id = "contoso.com"; + IsAdminManaged = $True; + IsDefault = $True; + IsRoot = $True; + IsVerified = $True; + PasswordNotificationWindowInDays = 14; + PasswordValidityPeriodInDays = 2147483647; + TenantId = $TenantId; + } AADEntitlementManagementAccessPackage 'myAccessPackage' { AccessPackagesIncompatibleWith = @(); From 714f0b787d0356aaf3f90fdd0be6501a82f865d7 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 10 Oct 2024 17:23:27 +0000 Subject: [PATCH 165/252] Updated {Update} AAD Integration Tests --- .../M365DSCIntegration.AAD.Update.Tests.ps1 | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 index 97df9b5436..38a257dddf 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 @@ -641,6 +641,21 @@ CertificateThumbprint = $CertificateThumbprint Ensure = "Present"; } + AADCustomSecurityAttributeDefinition 'AADCustomSecurityAttributeDefinition-ShoeSize' + { + ApplicationId = $ApplicationId; + AttributeSet = "TestAttributeSet"; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Present"; + IsCollection = $False; + IsSearchable = $True; + Name = "ShoeSize"; + Status = "Available"; + TenantId = $TenantId; + Type = "String"; + UsePreDefinedValuesOnly = $False; + Description = "What size of shoe is the person wearing? Drifted" # Drift + } AADDeviceRegistrationPolicy 'MyDeviceRegistrationPolicy' { ApplicationId = $ApplicationId; @@ -658,6 +673,21 @@ TenantId = $TenantId; UserDeviceQuota = 50; } + AADDomain 'AADDomain-Contoso' + { + ApplicationId = $ApplicationId; + AuthenticationType = "Managed"; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Present"; + Id = "contoso.com"; + IsAdminManaged = $True; + IsDefault = $True; + IsRoot = $True; + IsVerified = $False; #Drift + PasswordNotificationWindowInDays = 14; + PasswordValidityPeriodInDays = 2147483647; + TenantId = $TenantId; + } AADEntitlementManagementAccessPackage 'myAccessPackage' { AccessPackagesIncompatibleWith = @(); From 9e9224eafad309749a85381e3d0dc5d25e75ad95 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 10 Oct 2024 17:23:42 +0000 Subject: [PATCH 166/252] Updated {Update} AAD Integration Tests --- .../M365DSCIntegration.AAD.Remove.Tests.ps1 | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 index 611d0c5be0..c7f705b234 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 @@ -166,6 +166,29 @@ Ensure = "Absent"; PartnerTenantId = "12345-12345-12345-12345-12345"; } + AADCustomSecurityAttributeDefinition 'AADCustomSecurityAttributeDefinition-ShoeSize' + { + ApplicationId = $ApplicationId; + AttributeSet = "TestAttributeSet"; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Absent"; + IsCollection = $False; + IsSearchable = $True; + Name = "ShoeSize"; + Status = "Available"; + TenantId = $TenantId; + Type = "String"; + UsePreDefinedValuesOnly = $False; + Description = "What size of shoe is the person wearing?" + } + AADDomain 'AADDomain-Contoso' + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Absent"; + Id = "contoso.com"; + TenantId = $TenantId; + } AADEntitlementManagementAccessPackage 'myAccessPackage' { DisplayName = 'Integration Package' From 5d82747cfb98d04bd04211d6cd883222b02f9d3a Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 10 Oct 2024 17:25:40 +0000 Subject: [PATCH 167/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index c3ba07eb30..7db89b925c 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -3154,6 +3154,91 @@ } ] }, + { + "ClassName": "MSFT_AADCustomSecurityAttributeDefinition", + "Parameters": [ + { + "CIMType": "String", + "Name": "Name", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "AttributeSet", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Id", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Description", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "IsCollection", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "IsSearchable", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Status", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Type", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "UsePreDefinedValuesOnly", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_AADDeviceRegistrationPolicy", "Parameters": [ From 0aad5f45abac6bd7ce95814e698189c1abbb6999 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 10 Oct 2024 19:16:24 -0400 Subject: [PATCH 168/252] PPAdminDLPPolicy - Initial Release --- CHANGELOG.md | 2 + .../MSFT_PPAdminDLPPolicy.psm1 | 429 ++++++++++++++++++ .../MSFT_PPAdminDLPPolicy.schema.mof | 16 + .../MSFT_PPAdminDLPPolicy/readme.md | 6 + .../MSFT_PPAdminDLPPolicy/settings.json | 20 + .../Resources/PPAdminDLPPolicy/1-Create.ps1 | 33 ++ .../Resources/PPAdminDLPPolicy/2-Update.ps1 | 35 ++ .../Resources/PPAdminDLPPolicy/3-Remove.ps1 | 33 ++ ...Microsoft365DSC.PPAdminDLPPolicy.Tests.ps1 | 196 ++++++++ Tests/Unit/Stubs/Microsoft365.psm1 | 84 ++++ 10 files changed, 854 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_PPAdminDLPPolicy/MSFT_PPAdminDLPPolicy.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_PPAdminDLPPolicy/MSFT_PPAdminDLPPolicy.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_PPAdminDLPPolicy/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_PPAdminDLPPolicy/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/PPAdminDLPPolicy/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/PPAdminDLPPolicy/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/PPAdminDLPPolicy/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.PPAdminDLPPolicy.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index df501deccd..ef3468e027 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,8 @@ * Migrate to new Settings Catalog cmdlets. * IntuneMobileAppsMacOSLobApp * Initial release +* PPAdminDLPPolicy + * Initial release. * M365DSCDRGUtil * Fixes an issue for the handling of skipped one-property elements in the Settings Catalog. FIXES [#5086](https://github.com/microsoft/Microsoft365DSC/issues/5086) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_PPAdminDLPPolicy/MSFT_PPAdminDLPPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_PPAdminDLPPolicy/MSFT_PPAdminDLPPolicy.psm1 new file mode 100644 index 0000000000..bb6bde14be --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_PPAdminDLPPolicy/MSFT_PPAdminDLPPolicy.psm1 @@ -0,0 +1,429 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $PolicyName, + + [Parameter()] + [System.String[]] + $Environments, + + [Parameter()] + [System.String] + $FilterType, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + New-M365DSCConnection -Workload 'PowerPlatforms' ` + -InboundParameters $PSBoundParameters | Out-Null + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + try + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + if (-not [System.String]::IsNullOrEmpty($PolicyName)) + { + $instances = $Script:exportedInstances | Where-Object -FilterScript {$_.PolicyName -eq $PolicyName} + } + + if ($null -eq $instance) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.DisplayName -eq $DisplayName} + } + } + else + { + if (-not [System.String]::IsNullOrEmpty($PolicyName)) + { + $instance = Get-AdminDlpPolicy -PolicyName $PolicyName -ErrorAction SilentlyContinue + } + + if ($null -eq $instance) + { + $instance = Get-AdminDlpPolicy | Where-Object -FilterScript {$_.DisplayName -eq $DisplayName} + } + } + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + DisplayName = $instance.DisplayName + PolicyName = $instance.PolicyName + Environments = $instance.Environments.name + FilterType = $instance.FilterType + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $PolicyName, + + [Parameter()] + [System.String[]] + $Environments, + + [Parameter()] + [System.String] + $FilterType, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # CREATE + $needToUpdateNewInstance = $false + $policyName = $currentInstance.PolicyName + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + Write-Verbose -Message "Creating new Data Policy {$DisplayName}" + $policy = New-AdminDLPPolicy -DisplayName $DisplayName + $policyName = $policy.PolicyName + } + if ($setParameters.ContainsKey('PolicyName')) + { + $setParameters.PolicyName = $policyName + } + else + { + $setParameters.Add("PolicyName", $policyName) + } + + # UPDATE + if (($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') -or $needToUpdateNewInstance) + { + Write-Verbose -Message "Updating Data Policy {$DisplayName}" + $setParameters.Remove('DisplayName') | Out-Null + + if ($null -ne $setParameters.Environments -and $setParameters.Environments.Count -gt 0) + { + $setParameters.Environments = ($setParameters.Environments -join ',') + } + Write-Verbose -Message "Updating Data Policy {$DisplayName} with values:`r`n$(Convert-M365DscHashtableToString -Hashtable $setParameters)" + Set-AdminDLPPolicy @setParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Removing Data Policy {$DisplayName}" + Remove-AdminDLPPolicy -PolicyName $policyName + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $PolicyName, + + [Parameter()] + [System.String[]] + $Environments, + + [Parameter()] + [System.String] + $FilterType, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'PowerPlatforms' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-AdminDlpPolicy -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + $displayedKey = $config.DisplayName + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + DisplayName = $config.DisplayName + PolicyName = $config.PolicyName + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_PPAdminDLPPolicy/MSFT_PPAdminDLPPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_PPAdminDLPPolicy/MSFT_PPAdminDLPPolicy.schema.mof new file mode 100644 index 0000000000..4ed948ec86 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_PPAdminDLPPolicy/MSFT_PPAdminDLPPolicy.schema.mof @@ -0,0 +1,16 @@ +[ClassVersion("1.0.0.0"), FriendlyName("PPAdminDLPPolicy")] +class MSFT_PPAdminDLPPolicy : OMI_BaseResource +{ + [Key, Description("Creates the policy with the input display name")] String DisplayName; + [Write, Description("Unique identifier of the policy.")] String PolicyName; + [Write, Description("Comma separated string list used as input environments to either include or exclude, depending on the FilterType.")] String Environments[]; + [Write, Description("Identifies which filter type the policy will have, none, include, or exclude.")] String FilterType; + + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Absent","Present"}, Values{"Absent","Present"}] string Ensure; + [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_PPAdminDLPPolicy/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_PPAdminDLPPolicy/readme.md new file mode 100644 index 0000000000..2dfde53b68 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_PPAdminDLPPolicy/readme.md @@ -0,0 +1,6 @@ + +# PPAdminDLPPolicy + +## Description + +Manages a policy's environment and default API group settings. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_PPAdminDLPPolicy/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_PPAdminDLPPolicy/settings.json new file mode 100644 index 0000000000..e015f493fc --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_PPAdminDLPPolicy/settings.json @@ -0,0 +1,20 @@ +{ + "resourceName": "PPAdminDLPPolicy", + "description": "Manages a policy's environment and default API group settings.", + "roles": { + "read": [], + "update": [] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/PPAdminDLPPolicy/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/PPAdminDLPPolicy/1-Create.ps1 new file mode 100644 index 0000000000..82f9e9a159 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/PPAdminDLPPolicy/1-Create.ps1 @@ -0,0 +1,33 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + PPAdminDLPPolicy "PPAdminDLPPolicy-Test" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + DisplayName = "SuperTest"; + Ensure = "Present"; + TenantId = $TenantId; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/PPAdminDLPPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/PPAdminDLPPolicy/2-Update.ps1 new file mode 100644 index 0000000000..72da87212b --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/PPAdminDLPPolicy/2-Update.ps1 @@ -0,0 +1,35 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + PPAdminDLPPolicy "PPAdminDLPPolicy-Test" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + DisplayName = "SuperTest"; + Ensure = "Present"; + Environments = "Default-e91d4e0e-d5a5-4e3a-be14-2192592a59af"; + FilterType = "include"; # Drift + TenantId = $TenantId; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/PPAdminDLPPolicy/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/PPAdminDLPPolicy/3-Remove.ps1 new file mode 100644 index 0000000000..0703757596 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/PPAdminDLPPolicy/3-Remove.ps1 @@ -0,0 +1,33 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + PPAdminDLPPolicy "PPAdminDLPPolicy-Test" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + DisplayName = "SuperTest"; + Ensure = "Absent"; + TenantId = $TenantId; + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.PPAdminDLPPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.PPAdminDLPPolicy.Tests.ps1 new file mode 100644 index 0000000000..84d3de716e --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.PPAdminDLPPolicy.Tests.ps1 @@ -0,0 +1,196 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -GenericStubModule $GenericStubPath + +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + Mock -CommandName New-AdminDlpPolicy -MockWith {} + Mock -CommandName Set-AdminDlpPolicy -MockWith {} + Mock -CommandName Remove-AdminDlpPolicy -MockWith {} + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + Context -Name "The instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + DisplayName = "SuperTest"; + Ensure = "Present"; + Environments = "Default-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx"; + FilterType = "include"; + Credential = $Credential; + } + + Mock -CommandName Get-AdminDlpPolicy -MockWith { + return $null + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should create a new instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-AdminDLPPolicy -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + DisplayName = "SuperTest"; + Ensure = "Absent"; + Environments = "Default-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx"; + FilterType = "include"; + Credential = $Credential; + } + + Mock -CommandName Get-AdminDlpPolicy -MockWith { + return @{ + PolicyName = "MyPolicy" + DisplayName = "SuperTest" + Environments = @(@{ + name = 'Default-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx' + }) + FilterType = 'include' + } + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should remove the instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-AdminDlpPolicy -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + DisplayName = "SuperTest"; + Ensure = "Present"; + Environments = "Default-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx"; + FilterType = "include"; + Credential = $Credential; + } + + Mock -CommandName Get-AdminDlpPolicy -MockWith { + return @{ + PolicyName = "MyPolicy" + DisplayName = "SuperTest" + Environments = @(@{ + name = 'Default-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx' + }) + FilterType = 'include' + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + DisplayName = "SuperTest"; + Ensure = "Present"; + Environments = "Default-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx"; + FilterType = "exclude"; #drift + Credential = $Credential; + } + + Mock -CommandName Get-AdminDlpPolicy -MockWith { + return @{ + PolicyName = "MyPolicy" + DisplayName = "SuperTest" + Environments = @(@{ + name = 'Default-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx' + }) + FilterType = 'include' + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Set-AdminDlpPolicy -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + Mock -CommandName Get-AdminDlpPolicy -MockWith { + return @{ + PolicyName = "MyPolicy" + DisplayName = "SuperTest" + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 4a12b257c4..681ace6779 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -96248,3 +96248,87 @@ function Get-MgBetaDirectoryCustomSecurityAttributeDefinition $HttpPipelineAppend ) } + +function Get-AdminDlpPolicy +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $PolicyName, + + [Parameter()] + [System.Object] + $ApiVersion, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.String] + $CreatedBy + ) +} +function New-AdminDlpPolicy +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $ApiVersion, + + [Parameter()] + [System.Boolean] + $BlockNonBusinessDataGroup, + + [Parameter()] + [System.String] + $EnvironmentName, + + [Parameter()] + [System.String] + $SchemaVersion + ) +} +function Set-AdminDlpPolicy +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $SchemaVersion, + + [Parameter()] + [System.String] + $FilterType, + + [Parameter()] + [System.String] + $EnvironmentName, + + [Parameter()] + [System.String] + $SetNonBusinessDataGroupState, + + [Parameter()] + [System.String] + $DefaultGroup, + + [Parameter()] + [System.String] + $ApiVersion, + + [Parameter()] + [System.String] + $PolicyName, + + [Parameter()] + [System.String] + $Environments + ) +} From 098ffb19dde3000936892963e22c8d5bc9fe9bd3 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 10 Oct 2024 19:55:02 -0400 Subject: [PATCH 169/252] Update Microsoft365.psm1 --- Tests/Unit/Stubs/Microsoft365.psm1 | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 681ace6779..d38fac8e14 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -96332,3 +96332,21 @@ function Set-AdminDlpPolicy $Environments ) } + +function Remove-AdminDlpPolicy +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $ApiVersion, + + [Parameter()] + [System.String] + $PolicyName, + + [Parameter()] + [System.String] + $EnvironmentName + ) +} From e36c14c005d1034ab6e2bae2430e070680ec4291 Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Fri, 11 Oct 2024 12:28:25 +0530 Subject: [PATCH 170/252] updating examples --- .../AADIdentityGovernanceLifecycleWorkflow/1-Create.ps1 | 4 +++- .../AADIdentityGovernanceLifecycleWorkflow/2-Update.ps1 | 4 +++- .../AADIdentityGovernanceLifecycleWorkflow/3-Remove.ps1 | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADIdentityGovernanceLifecycleWorkflow/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADIdentityGovernanceLifecycleWorkflow/1-Create.ps1 index 201fdda338..0b86b74b9a 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/AADIdentityGovernanceLifecycleWorkflow/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/AADIdentityGovernanceLifecycleWorkflow/1-Create.ps1 @@ -24,7 +24,6 @@ Configuration Example AADIdentityGovernanceLifecycleWorkflow "AADIdentityGovernanceLifecycleWorkflow-Onboard pre-hire employee updated version" { Category = "joiner"; - Credential = $Credscredential; Description = "Description the onboard of prehire employee"; DisplayName = "Onboard pre-hire employee updated version"; Ensure = "Present"; @@ -59,6 +58,9 @@ Configuration Example ) } ); + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADIdentityGovernanceLifecycleWorkflow/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADIdentityGovernanceLifecycleWorkflow/2-Update.ps1 index 1ed9701969..b7db5fd0a6 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/AADIdentityGovernanceLifecycleWorkflow/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/AADIdentityGovernanceLifecycleWorkflow/2-Update.ps1 @@ -24,7 +24,6 @@ Configuration Example AADIdentityGovernanceLifecycleWorkflow "AADIdentityGovernanceLifecycleWorkflow-Onboard pre-hire employee updated version" { Category = "joiner"; - Credential = $Credscredential; #updated description Description = "Updated description the onboard of prehire employee"; DisplayName = "Onboard pre-hire employee updated version"; @@ -62,6 +61,9 @@ Configuration Example ) } ); + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADIdentityGovernanceLifecycleWorkflow/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADIdentityGovernanceLifecycleWorkflow/3-Remove.ps1 index fa2840fe12..0af81405a2 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/AADIdentityGovernanceLifecycleWorkflow/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/AADIdentityGovernanceLifecycleWorkflow/3-Remove.ps1 @@ -24,7 +24,6 @@ Configuration Example AADIdentityGovernanceLifecycleWorkflow "AADIdentityGovernanceLifecycleWorkflow-Onboard pre-hire employee updated version" { Category = "joiner"; - Credential = $Credscredential; Description = "Updated description the onboard of prehire employee"; DisplayName = "Onboard pre-hire employee updated version"; Ensure = "Absent"; @@ -59,6 +58,9 @@ Configuration Example ) } ); + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint } } } From a144aa14f21994a4aacde537e8028700af1a38c4 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 11 Oct 2024 10:33:22 +0000 Subject: [PATCH 171/252] Updated Resources and Cmdlet documentation pages --- .../power-platform/PPAdminDLPPolicy.md | 161 ++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 docs/docs/resources/power-platform/PPAdminDLPPolicy.md diff --git a/docs/docs/resources/power-platform/PPAdminDLPPolicy.md b/docs/docs/resources/power-platform/PPAdminDLPPolicy.md new file mode 100644 index 0000000000..dd2e85c07f --- /dev/null +++ b/docs/docs/resources/power-platform/PPAdminDLPPolicy.md @@ -0,0 +1,161 @@ +# PPAdminDLPPolicy + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **DisplayName** | Key | String | Creates the policy with the input display name | | +| **PolicyName** | Write | String | Unique identifier of the policy. | | +| **Environments** | Write | StringArray[] | Comma separated string list used as input environments to either include or exclude, depending on the FilterType. | | +| **FilterType** | Write | String | Identifies which filter type the policy will have, none, include, or exclude. | | +| **Ensure** | Write | String | Present ensures the instance exists, absent ensures it is removed. | `Absent`, `Present` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Manages a policy's environment and default API group settings. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - None + +- **Update** + + - None + +## Examples + +### Example 1 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + PPAdminDLPPolicy "PPAdminDLPPolicy-Test" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + DisplayName = "SuperTest"; + Ensure = "Present"; + TenantId = $TenantId; + } + } +} +``` + +### Example 2 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + PPAdminDLPPolicy "PPAdminDLPPolicy-Test" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + DisplayName = "SuperTest"; + Ensure = "Present"; + Environments = "Default-e91d4e0e-d5a5-4e3a-be14-2192592a59af"; + FilterType = "include"; # Drift + TenantId = $TenantId; + } + } +} +``` + +### Example 3 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + PPAdminDLPPolicy "PPAdminDLPPolicy-Test" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + DisplayName = "SuperTest"; + Ensure = "Absent"; + TenantId = $TenantId; + } + } +} +``` + From a057fd622067634348c02cdc0b7ca521e29a4dc6 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 11 Oct 2024 10:35:56 +0000 Subject: [PATCH 172/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 7db89b925c..ddd2b9d94d 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -39644,6 +39644,66 @@ } ] }, + { + "ClassName": "MSFT_PPAdminDLPPolicy", + "Parameters": [ + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "PolicyName", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "Environments", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "FilterType", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_PPPowerAppsEnvironment", "Parameters": [ From dbe3675b333aaec237615fd0192e74b09f3585d6 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 11 Oct 2024 10:44:01 +0000 Subject: [PATCH 173/252] Updated Resources and Cmdlet documentation pages --- .../AADIdentityGovernanceLifecycleWorkflow.md | 317 ++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 docs/docs/resources/azure-ad/AADIdentityGovernanceLifecycleWorkflow.md diff --git a/docs/docs/resources/azure-ad/AADIdentityGovernanceLifecycleWorkflow.md b/docs/docs/resources/azure-ad/AADIdentityGovernanceLifecycleWorkflow.md new file mode 100644 index 0000000000..14afcf7a7f --- /dev/null +++ b/docs/docs/resources/azure-ad/AADIdentityGovernanceLifecycleWorkflow.md @@ -0,0 +1,317 @@ +# AADIdentityGovernanceLifecycleWorkflow + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **DisplayName** | Key | String | Specifies the Display Name of the Workflow | | +| **Description** | Write | String | Description of the Workflow | | +| **Category** | Write | String | Category of the Workflow | | +| **IsEnabled** | Write | Boolean | Indicates if the Workflow is enabled | | +| **IsSchedulingEnabled** | Write | Boolean | Indicates if scheduling is enabled for the Workflow | | +| **Tasks** | Write | MSFT_AADIdentityGovernanceTask[] | Tasks associated with this workflow | | +| **ExecutionConditions** | Write | MSFT_IdentityGovernanceWorkflowExecutionConditions | ExecutionConditions for this workflow | | +| **Ensure** | Write | String | Present ensures the instance exists, absent ensures it is removed. | `Absent`, `Present` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + +### MSFT_IdentityGovernanceScope + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **OdataType** | Write | String | The @odata.type for the Scope. | | +| **Rule** | Write | String | The rule associated with the Scope. | | + +### MSFT_IdentityGovernanceTrigger + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **OdataType** | Write | String | The @odata.type for the Trigger. | | +| **TimeBasedAttribute** | Write | String | The time-based attribute for the Trigger. | | +| **OffsetInDays** | Write | SInt32 | The offset in days for the Trigger. | | + +### MSFT_IdentityGovernanceWorkflowExecutionConditions + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **OdataType** | Write | String | The @odata.type for the Workflow Execution Conditions. | | +| **ScopeValue** | Write | MSFT_IdentityGovernanceScope | The scope for the Workflow Execution Conditions. | | +| **TriggerValue** | Write | MSFT_IdentityGovernanceTrigger | The trigger for the Workflow Execution Conditions. | | + +### MSFT_AADIdentityGovernanceTaskArguments + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Name** | Key | String | The name of the key | | +| **Value** | Write | String | The value associated with the key | | + +### MSFT_AADIdentityGovernanceTask + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **DisplayName** | Write | String | Specifies the display name of the Workflow Task | | +| **Description** | Write | String | Description of the Workflow Task | | +| **Category** | Write | String | Category of the Workflow Task | | +| **IsEnabled** | Write | Boolean | Indicates if the Workflow Task is enabled or not | | +| **ExecutionSequence** | Write | SInt32 | The sequence in which the task is executed | | +| **ContinueOnError** | Write | Boolean | Specifies whether the task should continue on error | | +| **TaskDefinitionId** | Write | String | ID of the task definition associated with this Workflow Task | | +| **Arguments** | Write | MSFT_AADIdentityGovernanceTaskArguments[] | Arguments for the Workflow Task | | + + +## Description + +Use this resource to manage Lifecycle workflows. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - LifecycleWorkflows.Read.All + +- **Update** + + - LifecycleWorkflows.ReadWrite.All + +#### Application permissions + +- **Read** + + - LifecycleWorkflows.Read.All + +- **Update** + + - LifecycleWorkflows.ReadWrite.All + +## Examples + +### Example 1 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADIdentityGovernanceLifecycleWorkflow "AADIdentityGovernanceLifecycleWorkflow-Onboard pre-hire employee updated version" + { + Category = "joiner"; + Description = "Description the onboard of prehire employee"; + DisplayName = "Onboard pre-hire employee updated version"; + Ensure = "Present"; + ExecutionConditions = MSFT_IdentityGovernanceWorkflowExecutionConditions { + ScopeValue = MSFT_IdentityGovernanceScope { + Rule = '(not (country eq ''Brazil''))' + ODataType = '#microsoft.graph.identityGovernance.ruleBasedSubjectSet' + } + TriggerValue = MSFT_IdentityGovernanceTrigger { + OffsetInDays = 4 + TimeBasedAttribute = 'employeeHireDate' + ODataType = '#microsoft.graph.identityGovernance.timeBasedAttributeTrigger' + } + ODataType = '#microsoft.graph.identityGovernance.triggerAndScopeBasedConditions' + }; + IsEnabled = $True; + IsSchedulingEnabled = $False; + Tasks = @( + MSFT_AADIdentityGovernanceTask { + DisplayName = 'Add user to groups' + Description = 'Add user to selected groups' + Category = 'joiner,leaver,mover' + IsEnabled = $True + ExecutionSequence = 1 + ContinueOnError = $True + TaskDefinitionId = '22085229-5809-45e8-97fd-270d28d66910' + Arguments = @( + MSFT_AADIdentityGovernanceTaskArguments { + Name = 'groupID' + Value = '7ad01e00-8c3a-42a6-baaf-39f2390b2565' + } + ) + } + ); + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} +``` + +### Example 2 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADIdentityGovernanceLifecycleWorkflow "AADIdentityGovernanceLifecycleWorkflow-Onboard pre-hire employee updated version" + { + Category = "joiner"; + #updated description + Description = "Updated description the onboard of prehire employee"; + DisplayName = "Onboard pre-hire employee updated version"; + Ensure = "Present"; + ExecutionConditions = MSFT_IdentityGovernanceWorkflowExecutionConditions { + ScopeValue = MSFT_IdentityGovernanceScope { + #updated rule + Rule = '(not (country eq ''America''))' + ODataType = '#microsoft.graph.identityGovernance.ruleBasedSubjectSet' + } + TriggerValue = MSFT_IdentityGovernanceTrigger { + OffsetInDays = 4 + TimeBasedAttribute = 'employeeHireDate' + ODataType = '#microsoft.graph.identityGovernance.timeBasedAttributeTrigger' + } + ODataType = '#microsoft.graph.identityGovernance.triggerAndScopeBasedConditions' + }; + IsEnabled = $True; + IsSchedulingEnabled = $False; + Tasks = @( + MSFT_AADIdentityGovernanceTask { + DisplayName = 'Add user to groups' + #updated description + Description = 'Add user to selected groups updated' + Category = 'joiner,leaver,mover' + IsEnabled = $True + ExecutionSequence = 1 + ContinueOnError = $True + TaskDefinitionId = '22085229-5809-45e8-97fd-270d28d66910' + Arguments = @( + MSFT_AADIdentityGovernanceTaskArguments { + Name = 'groupID' + Value = '7ad01e00-8c3a-42a6-baaf-39f2390b2565' + } + ) + } + ); + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} +``` + +### Example 3 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADIdentityGovernanceLifecycleWorkflow "AADIdentityGovernanceLifecycleWorkflow-Onboard pre-hire employee updated version" + { + Category = "joiner"; + Description = "Updated description the onboard of prehire employee"; + DisplayName = "Onboard pre-hire employee updated version"; + Ensure = "Absent"; + ExecutionConditions = MSFT_IdentityGovernanceWorkflowExecutionConditions { + ScopeValue = MSFT_IdentityGovernanceScope { + Rule = '(not (country eq ''America''))' + ODataType = '#microsoft.graph.identityGovernance.ruleBasedSubjectSet' + } + TriggerValue = MSFT_IdentityGovernanceTrigger { + OffsetInDays = 4 + TimeBasedAttribute = 'employeeHireDate' + ODataType = '#microsoft.graph.identityGovernance.timeBasedAttributeTrigger' + } + ODataType = '#microsoft.graph.identityGovernance.triggerAndScopeBasedConditions' + }; + IsEnabled = $True; + IsSchedulingEnabled = $False; + Tasks = @( + MSFT_AADIdentityGovernanceTask { + DisplayName = 'Add user to groups' + Description = 'Add user to selected groups updated' + Category = 'joiner,leaver,mover' + IsEnabled = $True + ExecutionSequence = 1 + ContinueOnError = $True + TaskDefinitionId = '22085229-5809-45e8-97fd-270d28d66910' + Arguments = @( + MSFT_AADIdentityGovernanceTaskArguments { + Name = 'groupID' + Value = '7ad01e00-8c3a-42a6-baaf-39f2390b2565' + } + ) + } + ); + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} +``` + From e2325776e7489f5193659913a9ab972cff0619b0 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 11 Oct 2024 10:46:44 +0000 Subject: [PATCH 174/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 190 ++++++++++++++++++ 1 file changed, 190 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index ddd2b9d94d..27653bf947 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -4949,6 +4949,196 @@ } ] }, + { + "ClassName": "MSFT_IdentityGovernanceScope", + "Parameters": [ + { + "CIMType": "String", + "Name": "OdataType", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Rule", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_IdentityGovernanceTrigger", + "Parameters": [ + { + "CIMType": "String", + "Name": "OdataType", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TimeBasedAttribute", + "Option": "Write" + }, + { + "CIMType": "SInt32", + "Name": "OffsetInDays", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_IdentityGovernanceWorkflowExecutionConditions", + "Parameters": [ + { + "CIMType": "String", + "Name": "OdataType", + "Option": "Write" + }, + { + "CIMType": "MSFT_IdentityGovernanceScope", + "Name": "ScopeValue", + "Option": "Write" + }, + { + "CIMType": "MSFT_IdentityGovernanceTrigger", + "Name": "TriggerValue", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_AADIdentityGovernanceTaskArguments", + "Parameters": [ + { + "CIMType": "String", + "Name": "Name", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "Value", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_AADIdentityGovernanceTask", + "Parameters": [ + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Description", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Category", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "IsEnabled", + "Option": "Write" + }, + { + "CIMType": "SInt32", + "Name": "ExecutionSequence", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ContinueOnError", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TaskDefinitionId", + "Option": "Write" + }, + { + "CIMType": "MSFT_AADIdentityGovernanceTaskArguments[]", + "Name": "Arguments", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_AADIdentityGovernanceLifecycleWorkflow", + "Parameters": [ + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "Description", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Category", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "IsEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "IsSchedulingEnabled", + "Option": "Write" + }, + { + "CIMType": "MSFT_AADIdentityGovernanceTask[]", + "Name": "Tasks", + "Option": "Write" + }, + { + "CIMType": "MSFT_IdentityGovernanceWorkflowExecutionConditions", + "Name": "ExecutionConditions", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_AADLifecycleWorkflowSettings", "Parameters": [ From 71f094819e6ca86ad8a2b9489fb85f6c6ce35540 Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Fri, 11 Oct 2024 16:27:24 +0200 Subject: [PATCH 175/252] Add cleanup for property names in Settings Catalog --- .../Modules/M365DSCDRGUtil.psm1 | 17 +++++++++++++++++ .../M365DSCResourceGenerator.psm1 | 19 ++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 index d85eaa083e..e534d1df33 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 @@ -2555,6 +2555,23 @@ function Export-IntuneSettingCatalogPolicySettings { $settingName = Get-SettingDefinitionNameWithParentFromOffsetUri -OffsetUri $settingDefinition.OffsetUri -SettingName $settingName } + + # Simplify names from the OffsetUri. This is done to make the names more readable, especially in case of long and complex OffsetUris. + switch -wildcard ($settingName) + { + { 'access16v2~Policy~L_MicrosoftOfficeaccess~L_ApplicationSettings~L_Security*' } { $settingName = $settingName.Replace('access16v2~Policy~L_MicrosoftOfficeaccess~L_ApplicationSettings', 'MicrosoftAccess_') } + { 'excel16v2~Policy~L_MicrosoftOfficeExcel~L_ExcelOptions~*' } { $settingName = $settingName.Replace('excel16v2~Policy~L_MicrosoftOfficeExcel~L_ExcelOptions', 'MicrosoftExcel_') } + { 'word16v2~Policy~L_MicrosoftOfficeWord~L_WordOptions~*' } { $settingName = $settingName.Replace('word16v2~Policy~L_MicrosoftOfficeWord~L_WordOptions', 'MicrosoftWord_') } + { 'ppt16v2~Policy~L_MicrosoftOfficePowerPoint~L_PowerPointOptions~*' } { $settingName = $settingName.Replace('ppt16v2~Policy~L_MicrosoftOfficePowerPoint~L_PowerPointOptions', 'MicrosoftPowerPoint_') } + { 'proj16v2~Policy~L_Proj~L_ProjectOptions~*' } { $settingName = $settingName.Replace('proj16v2~Policy~L_Proj~L_ProjectOptions', 'MicrosoftProject_') } + { 'visio16v2~Policy~L_MicrosoftVisio~L_VisioOptions~*' } { $settingName = $settingName.Replace('visio16v2~Policy~L_MicrosoftVisio~L_VisioOptions', 'MicrosoftVisio_') } + { 'pub16v*~Policy~L_MicrosoftOfficePublisher~' } { $settingName = [Regex]::replace($settingName, 'pub16v(.*)~Policy~L_MicrosoftOfficePublisher', 'MicrosoftPublisher_') } + { '*~L_Security~*' } { $settingName = $settingName.Replace('~L_Security', 'Security') } + { '*~L_TrustCenter_'} { $settingName = $settingName.Replace('~L_TrustCenter', '_TrustCenter') } + { '*~L_ProtectedView_' } { $settingName = $settingName.Replace('~L_ProtectedView', 'ProtectedView') } + { '*~L_FileBlockSettings_' } { $settingName = $settingName.Replace('~L_FileBlockSettings', 'FileBlockSettings') } + { '*~L_TrustedLocations' } { $settingName = $settingName.Replace('~L_TrustedLocations', 'TrustedLocations') } + } } $odataType = if ($IsRoot) { $SettingInstance.AdditionalProperties.'@odata.type' } else { $SettingInstance.'@odata.type' } diff --git a/ResourceGenerator/M365DSCResourceGenerator.psm1 b/ResourceGenerator/M365DSCResourceGenerator.psm1 index fbe1658771..8073abe8d2 100644 --- a/ResourceGenerator/M365DSCResourceGenerator.psm1 +++ b/ResourceGenerator/M365DSCResourceGenerator.psm1 @@ -337,7 +337,7 @@ $($userDefinitionSettings.MOF -join "`r`n") $parameter -match '\$.*$' $parameterName = $Matches[0].Replace('$', '') $parameterType = 'IntuneSettingsCatalog' + $parameterName - $cimInstance = $definitionSettings.MOFInstance | Where-Object -FilterScript { $_ -like "*$parameterType`n*" } + $cimInstance = $definitionSettings.MOFInstance | Where-Object -FilterScript { $_ -like "*$parameterType`n*" -or $_ -like "*$parameterType`r`n*" } $rowFilter = '\[.*;' $cimRows = [regex]::Matches($cimInstance, $rowFilter) | Foreach-Object { $_.Value @@ -3925,6 +3925,23 @@ function New-SettingsCatalogSettingDefinitionSettingsFromTemplate { { $settingName = Get-SettingDefinitionNameWithParentFromOffsetUri -OffsetUri $SettingDefinition.OffsetUri -SettingName $settingName } + + # Simplify names from the OffsetUri. This is done to make the names more readable, especially in case of long and complex OffsetUris. + switch -wildcard ($settingName) + { + { 'access16v2~Policy~L_MicrosoftOfficeaccess~L_ApplicationSettings~L_Security*' } { $settingName = $settingName.Replace('access16v2~Policy~L_MicrosoftOfficeaccess~L_ApplicationSettings', 'MicrosoftAccess_') } + { 'excel16v2~Policy~L_MicrosoftOfficeExcel~L_ExcelOptions~*' } { $settingName = $settingName.Replace('excel16v2~Policy~L_MicrosoftOfficeExcel~L_ExcelOptions', 'MicrosoftExcel_') } + { 'word16v2~Policy~L_MicrosoftOfficeWord~L_WordOptions~*' } { $settingName = $settingName.Replace('word16v2~Policy~L_MicrosoftOfficeWord~L_WordOptions', 'MicrosoftWord_') } + { 'ppt16v2~Policy~L_MicrosoftOfficePowerPoint~L_PowerPointOptions~*' } { $settingName = $settingName.Replace('ppt16v2~Policy~L_MicrosoftOfficePowerPoint~L_PowerPointOptions', 'MicrosoftPowerPoint_') } + { 'proj16v2~Policy~L_Proj~L_ProjectOptions~*' } { $settingName = $settingName.Replace('proj16v2~Policy~L_Proj~L_ProjectOptions', 'MicrosoftProject_') } + { 'visio16v2~Policy~L_MicrosoftVisio~L_VisioOptions~*' } { $settingName = $settingName.Replace('visio16v2~Policy~L_MicrosoftVisio~L_VisioOptions', 'MicrosoftVisio_') } + { 'pub16v*~Policy~L_MicrosoftOfficePublisher~' } { $settingName = [Regex]::replace($settingName, 'pub16v(.*)~Policy~L_MicrosoftOfficePublisher', 'MicrosoftPublisher_') } + { '*~L_Security~*' } { $settingName = $settingName.Replace('~L_Security', 'Security') } + { '*~L_TrustCenter_'} { $settingName = $settingName.Replace('~L_TrustCenter', '_TrustCenter') } + { '*~L_ProtectedView_' } { $settingName = $settingName.Replace('~L_ProtectedView', 'ProtectedView') } + { '*~L_FileBlockSettings_' } { $settingName = $settingName.Replace('~L_FileBlockSettings', 'FileBlockSettings') } + { '*~L_TrustedLocations' } { $settingName = $settingName.Replace('~L_TrustedLocations', 'TrustedLocations') } + } } $childSettings = @() From 62f1cabafdd6c5bfa51e1fc3346608d0cdca9825 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 11 Oct 2024 10:48:45 -0400 Subject: [PATCH 176/252] PPPowerAppPolicyUrlPatterns - Initial Release --- CHANGELOG.md | 2 + .../MSFT_PPPowerAppPolicyUrlPatterns.psm1 | 421 ++++++++++++++++++ ...SFT_PPPowerAppPolicyUrlPatterns.schema.mof | 23 + .../readme.md | 6 + .../settings.json | 20 + .../PPPowerAppPolicyUrlPatterns/1-Create.ps1 | 51 +++ .../PPPowerAppPolicyUrlPatterns/2-Update.ps1 | 51 +++ .../PPPowerAppPolicyUrlPatterns/3-Remove.ps1 | 34 ++ .../Microsoft365DSC/Modules/M365DSCUtil.psm1 | 13 +- ...5DSC.PPPowerAppPolicyUrlPatterns.Tests.ps1 | 241 ++++++++++ Tests/Unit/Stubs/Microsoft365.psm1 | 65 +++ 11 files changed, 918 insertions(+), 9 deletions(-) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_PPPowerAppPolicyUrlPatterns/MSFT_PPPowerAppPolicyUrlPatterns.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_PPPowerAppPolicyUrlPatterns/MSFT_PPPowerAppPolicyUrlPatterns.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_PPPowerAppPolicyUrlPatterns/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_PPPowerAppPolicyUrlPatterns/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/PPPowerAppPolicyUrlPatterns/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/PPPowerAppPolicyUrlPatterns/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/PPPowerAppPolicyUrlPatterns/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.PPPowerAppPolicyUrlPatterns.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 181e2038b5..b096d97f8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,8 @@ * Initial release * PPAdminDLPPolicy * Initial release. +* PPPowerAppPolicyUrlPatterns + * Initial release. * M365DSCDRGUtil * Fixes an issue for the handling of skipped one-property elements in the Settings Catalog. FIXES [#5086](https://github.com/microsoft/Microsoft365DSC/issues/5086) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_PPPowerAppPolicyUrlPatterns/MSFT_PPPowerAppPolicyUrlPatterns.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_PPPowerAppPolicyUrlPatterns/MSFT_PPPowerAppPolicyUrlPatterns.psm1 new file mode 100644 index 0000000000..b99fc8179b --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_PPPowerAppPolicyUrlPatterns/MSFT_PPPowerAppPolicyUrlPatterns.psm1 @@ -0,0 +1,421 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $PPTenantId, + + [Parameter(Mandatory = $true)] + [System.String] + $PolicyName, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $RuleSet, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'PowerPlatforms' ` + -InboundParameters $PSBoundParameters | Out-Null + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + try + { + $policy = Get-AdminDlpPolicy | Where-Object -FilterScript {$_.DisplayName -eq $PolicyName} + + if ($null -eq $policy) + { + return $nullResult + } + + $rules = Get-PowerAppPolicyUrlPatterns -TenantID $PPTenantId ` + -PolicyName $($policy.PolicyName) + $RulesValue = @() + foreach ($rule in $rules.rules) + { + $RulesValue += @{ + order = $rule.order + customConnectorRuleClassification = $rule.customConnectorRuleClassification + pattern = $rule.pattern + } + } + + $results = @{ + PPTenantId = $PPTenantId + PolicyName = $PolicyName + RuleSet = $RulesValue + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $PPTenantId, + + [Parameter(Mandatory = $true)] + [System.String] + $PolicyName, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $RuleSet, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'PowerPlatforms' ` + -InboundParameters $PSBoundParameters | Out-Null + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $policy = Get-AdminDlpPolicy | Where-Object -FilterScript {$_.DisplayName -eq $PolicyName} + $policyNameValue = $policy.PolicyName + + # CREATE + if ($Ensure -eq 'Present') + { + $body = @{ + rules = @() + } + + foreach ($rule in $RuleSet) + { + $body.rules += @{ + order = $rule.order + customConnectorRuleClassification = $rule.customConnectorRuleClassification + pattern = $rule.pattern + } + } + $payload = $(ConvertTo-Json $body -Depth 9 -Compress) + Write-Verbose -Message "Setting new Url Patterns for Policy {$($PolicyNameValue)} with parameters:`r`n$payload" + + New-PowerAppPolicyUrlPatterns -TenantId $PPTenantId ` + -PolicyName $policyNameValue ` + -NewUrlPatterns $body ` + -Verbose + } + # REMOVE + elseif ($Ensure -eq 'Absent') + { + Write-Verbose -Message "Removing Url Patterns for Policy {$($PolicyNameValue)}" + Remove-PowerAppPolicyUrlPatterns -TenantId $PPTenantId -PolicyName $policyNameValue + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $PPTenantId, + + [Parameter(Mandatory = $true)] + [System.String] + $PolicyName, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $RuleSet, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'PowerPlatforms' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + $Script:ExportMode = $true + $tenantInfo = Get-TenantDetailsFromGraph + [array] $policies = Get-AdminDlpPolicy -ErrorAction Stop + + $dscContent = '' + if ($policies.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + $i = 1 + foreach ($policy in $policies) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + Write-Host " |---[$i/$($policies.Count)] $($policy.DisplayName)" -NoNewline + $params = @{ + PPTenantId = $tenantInfo.TenantId + PolicyName = $policy.DisplayName + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + if ($null -ne $Results.RuleSet) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.RuleSet ` + -CIMInstanceName 'PPPowerAPpPolicyUrlPatternsRule' + if (-Not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.RuleSet = $complexTypeStringResult + } + else + { + $Results.Remove('RuleSet') | Out-Null + } + } + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + if ($Results.RuleSet) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'RuleSet' -IsCIMArray:$true + } + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $k++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + + $i++ + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_PPPowerAppPolicyUrlPatterns/MSFT_PPPowerAppPolicyUrlPatterns.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_PPPowerAppPolicyUrlPatterns/MSFT_PPPowerAppPolicyUrlPatterns.schema.mof new file mode 100644 index 0000000000..9d323799a0 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_PPPowerAppPolicyUrlPatterns/MSFT_PPPowerAppPolicyUrlPatterns.schema.mof @@ -0,0 +1,23 @@ +[ClassVersion("1.0.0.0")] +class MSFT_PPPowerAPpPolicyUrlPatternsRule +{ + [Write, Description("Rule priority order.")] String order; + [Write, Description("Rule classification.")] String customConnectorRuleClassification; + [Write, Description("Rule pattern.")] String pattern; +}; + +[ClassVersion("1.0.0.0"), FriendlyName("PPPowerAppPolicyUrlPatterns")] +class MSFT_PPPowerAppPolicyUrlPatterns : OMI_BaseResource +{ + [Key, Description("The policy name identifier.")] String PolicyName; + [Key, Description("The tenant identifier.")] String PPTenantId; + [Write, Description("Set of custom connector pattern rules associated with the policy."), EmbeddedInstance("MSFT_PPPowerAPpPolicyUrlPatternsRule")] String RuleSet[]; + + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Absent","Present"}, Values{"Absent","Present"}] string Ensure; + [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_PPPowerAppPolicyUrlPatterns/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_PPPowerAppPolicyUrlPatterns/readme.md new file mode 100644 index 0000000000..2656b9f1e2 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_PPPowerAppPolicyUrlPatterns/readme.md @@ -0,0 +1,6 @@ + +# PPPowerAppPolicyUrlPatterns + +## Description + +Configures custom connector patterns for Data Loss Prevention policies in Power Platforms. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_PPPowerAppPolicyUrlPatterns/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_PPPowerAppPolicyUrlPatterns/settings.json new file mode 100644 index 0000000000..b9f4f13d61 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_PPPowerAppPolicyUrlPatterns/settings.json @@ -0,0 +1,20 @@ +{ + "resourceName": "PPPowerAppPolicyUrlPatterns", + "description": "Configures custom connector patterns for Data Loss Prevention policies in Power Platforms.", + "roles": { + "read": [], + "update": [] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/PPPowerAppPolicyUrlPatterns/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/PPPowerAppPolicyUrlPatterns/1-Create.ps1 new file mode 100644 index 0000000000..f658e08a3d --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/PPPowerAppPolicyUrlPatterns/1-Create.ps1 @@ -0,0 +1,51 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + PPPowerAppPolicyUrlPatterns "PPPowerAppPolicyUrlPatterns" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Present"; + PolicyName = "DSCPolicy"; + PPTenantId = "e91d4e0e-d5a5-4e3a-be14-2192592a59af"; + RuleSet = @( + MSFT_PPPowerAPpPolicyUrlPatternsRule{ + pattern = 'https://contoso.com' + customConnectorRuleClassification = 'General' + order = 1 + } + MSFT_PPPowerAPpPolicyUrlPatternsRule{ + pattern = 'https://fabrikam.com' + customConnectorRuleClassification = 'General' + order = 2 + } + MSFT_PPPowerAPpPolicyUrlPatternsRule{ + pattern = '*' + customConnectorRuleClassification = 'Ignore' + order = 3 + } + ); + TenantId = $TenantId; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/PPPowerAppPolicyUrlPatterns/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/PPPowerAppPolicyUrlPatterns/2-Update.ps1 new file mode 100644 index 0000000000..e7a1509d29 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/PPPowerAppPolicyUrlPatterns/2-Update.ps1 @@ -0,0 +1,51 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + PPPowerAppPolicyUrlPatterns "PPPowerAppPolicyUrlPatterns" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Present"; + PolicyName = "DSCPolicy"; + PPTenantId = "e91d4e0e-d5a5-4e3a-be14-2192592a59af"; + RuleSet = @( + MSFT_PPPowerAPpPolicyUrlPatternsRule{ + pattern = 'https://contoso.com' + customConnectorRuleClassification = 'General' + order = 1 + } + MSFT_PPPowerAPpPolicyUrlPatternsRule{ + pattern = 'https://tailspintoys.com' # drift + customConnectorRuleClassification = 'General' + order = 2 + } + MSFT_PPPowerAPpPolicyUrlPatternsRule{ + pattern = '*' + customConnectorRuleClassification = 'Ignore' + order = 3 + } + ); + TenantId = $TenantId; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/PPPowerAppPolicyUrlPatterns/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/PPPowerAppPolicyUrlPatterns/3-Remove.ps1 new file mode 100644 index 0000000000..3c885442c3 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/PPPowerAppPolicyUrlPatterns/3-Remove.ps1 @@ -0,0 +1,34 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + PPPowerAppPolicyUrlPatterns "PPPowerAppPolicyUrlPatterns" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Absent"; + PolicyName = "DSCPolicy"; + PPTenantId = "e91d4e0e-d5a5-4e3a-be14-2192592a59af"; + TenantId = $TenantId; + } + } +} diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 148c450c1a..93e4d39e0f 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -3830,20 +3830,15 @@ function Get-M365DSCExportContentForResource $primaryKey = $Results.UserPrincipalName } - if ([String]::IsNullOrEmpty($primaryKey) -and ` - -not $Keys.Contains('IsSingleInstance')) - { - foreach ($Key in $Keys) - { - $primaryKey += $Results.$Key - } - } - $instanceName = $ResourceName if (-not [System.String]::IsNullOrEmpty($primaryKey)) { $instanceName += "-$primaryKey" } + else + { + $instanceName += "-" + (New-Guid).ToString() + } if ($Results.ContainsKey('Workload')) { diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.PPPowerAppPolicyUrlPatterns.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.PPPowerAppPolicyUrlPatterns.Tests.ps1 new file mode 100644 index 0000000000..0c69d915a5 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.PPPowerAppPolicyUrlPatterns.Tests.ps1 @@ -0,0 +1,241 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -GenericStubModule $GenericStubPath + +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + Mock -commandName Remove-PowerAppPolicyUrlPatterns -MockWith {} + Mock -commandName Get-PowerAppPolicyUrlPatterns -MockWith {} + Mock -commandName New-PowerAppPolicyUrlPatterns -MockWith {} + Mock -commandName Get-TenantDetailsFromGraph -MockWith { + return @{ + TenantId = 'xxxxxxx' + } + } + Mock -commandName Get-AdminDlpPolicy -MockWith { + return @{ + PolicyName = 'DSCPolicy' + DisplayName = 'DSCPolicy' + } + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + PolicyName = "DSCPolicy"; + PPTenantId = "xxxxxxx"; + RuleSet = @( + (New-CimInstance -ClassName MSFT_PPPowerAPpPolicyUrlPatternsRule -Property @{ + pattern = 'https://contoso.com' + customConnectorRuleClassification = 'General' + order = 1 + } -ClientOnly) + (New-CimInstance -ClassName MSFT_PPPowerAPpPolicyUrlPatternsRule -Property @{ + pattern = 'https://fabrikam.com' + customConnectorRuleClassification = 'General' + order = 2 + } -ClientOnly) + ) + Ensure = 'Absent' + Credential = $Credential; + } + + Mock -CommandName Get-PowerAppPolicyUrlPatterns -MockWith { + return @{ + rules = @( + @{ + pattern = 'https://contoso.com' + customConnectorRuleClassification = 'General' + order = 1 + }, + @{ + pattern = 'https://fabrikam.com' + customConnectorRuleClassification = 'General' + order = 2 + } + ) + } + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should remove the instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-PowerAppPolicyUrlPatterns -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + PolicyName = "DSCPolicy"; + PPTenantId = "xxxxxxx"; + RuleSet = @( + (New-CimInstance -ClassName MSFT_PPPowerAPpPolicyUrlPatternsRule -Property @{ + pattern = 'https://contoso.com' + customConnectorRuleClassification = 'General' + order = 1 + } -ClientOnly) + (New-CimInstance -ClassName MSFT_PPPowerAPpPolicyUrlPatternsRule -Property @{ + pattern = 'https://fabrikam.com' + customConnectorRuleClassification = 'General' + order = 2 + } -ClientOnly) + ) + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-PowerAppPolicyUrlPatterns -MockWith { + return @{ + rules = @( + @{ + pattern = 'https://contoso.com' + customConnectorRuleClassification = 'General' + order = 1 + }, + @{ + pattern = 'https://fabrikam.com' + customConnectorRuleClassification = 'General' + order = 2 + } + ) + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + PolicyName = "DSCPolicy"; + PPTenantId = "xxxxxxx"; + RuleSet = @( + (New-CimInstance -ClassName MSFT_PPPowerAPpPolicyUrlPatternsRule -Property @{ + pattern = 'https://contoso.com' + customConnectorRuleClassification = 'General' + order = 1 + } -ClientOnly) + (New-CimInstance -ClassName MSFT_PPPowerAPpPolicyUrlPatternsRule -Property @{ + pattern = 'https://tailspintoys.com' #drift + customConnectorRuleClassification = 'General' + order = 2 + } -ClientOnly) + ) + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-PowerAppPolicyUrlPatterns -MockWith { + return @{ + rules = @( + @{ + pattern = 'https://contoso.com' + customConnectorRuleClassification = 'General' + order = 1 + }, + @{ + pattern = 'https://fabrikam.com' + customConnectorRuleClassification = 'General' + order = 2 + } + ) + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-PowerAppPolicyUrlPatterns -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + Mock -CommandName Get-PowerAppPolicyUrlPatterns -MockWith { + return @{ + rules = @( + @{ + pattern = 'https://contoso.com' + customConnectorRuleClassification = 'General' + order = 1 + }, + @{ + pattern = 'https://fabrikam.com' + customConnectorRuleClassification = 'General' + order = 2 + } + ) + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 1513a0bc6f..b75ebef3fc 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -96910,3 +96910,68 @@ function Remove-AdminDlpPolicy $EnvironmentName ) } + +function New-PowerAppPolicyUrlPatterns +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $PolicyName, + + [Parameter()] + [System.Object] + $NewUrlPatterns, + + [Parameter()] + [System.String] + $ApiVersion + ) +} +function Remove-PowerAppPolicyUrlPatterns +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $PolicyName, + + [Parameter()] + [System.String] + $ApiVersion + ) +} +function Get-PowerAppPolicyUrlPatterns +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $PolicyName, + + [Parameter()] + [System.String] + $ApiVersion + ) +} +function Get-TenantDetailsFromGraph +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $GraphApiVersion + ) +} From 167c5176276eac2ec0f3ec907f28beb0bddb0ce8 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 11 Oct 2024 11:01:07 -0400 Subject: [PATCH 177/252] Update MSFT_PPPowerAppPolicyUrlPatterns.psm1 --- .../MSFT_PPPowerAppPolicyUrlPatterns.psm1 | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_PPPowerAppPolicyUrlPatterns/MSFT_PPPowerAppPolicyUrlPatterns.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_PPPowerAppPolicyUrlPatterns/MSFT_PPPowerAppPolicyUrlPatterns.psm1 index b99fc8179b..fc0895a29b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_PPPowerAppPolicyUrlPatterns/MSFT_PPPowerAppPolicyUrlPatterns.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_PPPowerAppPolicyUrlPatterns/MSFT_PPPowerAppPolicyUrlPatterns.psm1 @@ -273,10 +273,33 @@ function Test-TargetResource Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" - $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` - -Source $($MyInvocation.MyCommand.Source) ` - -DesiredValues $PSBoundParameters ` - -ValuesToCheck $ValuesToCheck.Keys + #Compare Cim instances + foreach ($key in $PSBoundParameters.Keys) + { + $source = $PSBoundParameters.$key + $target = $CurrentValues.$key + if ($source.getType().Name -like '*CimInstance*') + { + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + if (-Not $testResult) + { + $testResult = $false + break + } + + $ValuesToCheck.Remove($key) | Out-Null + } + } + if ($testResult) + { + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + } Write-Verbose -Message "Test-TargetResource returned $testResult" From 2b953ad0a75105656b244e8172b030426ee3a159 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 11 Oct 2024 16:34:12 +0000 Subject: [PATCH 178/252] Updated Resources and Cmdlet documentation pages --- .../PPPowerAppPolicyUrlPatterns.md | 205 ++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 docs/docs/resources/power-platform/PPPowerAppPolicyUrlPatterns.md diff --git a/docs/docs/resources/power-platform/PPPowerAppPolicyUrlPatterns.md b/docs/docs/resources/power-platform/PPPowerAppPolicyUrlPatterns.md new file mode 100644 index 0000000000..d658c23ba1 --- /dev/null +++ b/docs/docs/resources/power-platform/PPPowerAppPolicyUrlPatterns.md @@ -0,0 +1,205 @@ +# PPPowerAppPolicyUrlPatterns + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **PolicyName** | Key | String | The policy name identifier. | | +| **PPTenantId** | Key | String | The tenant identifier. | | +| **RuleSet** | Write | MSFT_PPPowerAPpPolicyUrlPatternsRule[] | Set of custom connector pattern rules associated with the policy. | | +| **Ensure** | Write | String | Present ensures the instance exists, absent ensures it is removed. | `Absent`, `Present` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + +### MSFT_PPPowerAPpPolicyUrlPatternsRule + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **order** | Write | String | Rule priority order. | | +| **customConnectorRuleClassification** | Write | String | Rule classification. | | +| **pattern** | Write | String | Rule pattern. | | + + +## Description + +Configures custom connector patterns for Data Loss Prevention policies in Power Platforms. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - None + +- **Update** + + - None + +## Examples + +### Example 1 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + PPPowerAppPolicyUrlPatterns "PPPowerAppPolicyUrlPatterns" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Present"; + PolicyName = "DSCPolicy"; + PPTenantId = "e91d4e0e-d5a5-4e3a-be14-2192592a59af"; + RuleSet = @( + MSFT_PPPowerAPpPolicyUrlPatternsRule{ + pattern = 'https://contoso.com' + customConnectorRuleClassification = 'General' + order = 1 + } + MSFT_PPPowerAPpPolicyUrlPatternsRule{ + pattern = 'https://fabrikam.com' + customConnectorRuleClassification = 'General' + order = 2 + } + MSFT_PPPowerAPpPolicyUrlPatternsRule{ + pattern = '*' + customConnectorRuleClassification = 'Ignore' + order = 3 + } + ); + TenantId = $TenantId; + } + } +} +``` + +### Example 2 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + PPPowerAppPolicyUrlPatterns "PPPowerAppPolicyUrlPatterns" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Present"; + PolicyName = "DSCPolicy"; + PPTenantId = "e91d4e0e-d5a5-4e3a-be14-2192592a59af"; + RuleSet = @( + MSFT_PPPowerAPpPolicyUrlPatternsRule{ + pattern = 'https://contoso.com' + customConnectorRuleClassification = 'General' + order = 1 + } + MSFT_PPPowerAPpPolicyUrlPatternsRule{ + pattern = 'https://tailspintoys.com' # drift + customConnectorRuleClassification = 'General' + order = 2 + } + MSFT_PPPowerAPpPolicyUrlPatternsRule{ + pattern = '*' + customConnectorRuleClassification = 'Ignore' + order = 3 + } + ); + TenantId = $TenantId; + } + } +} +``` + +### Example 3 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + PPPowerAppPolicyUrlPatterns "PPPowerAppPolicyUrlPatterns" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Absent"; + PolicyName = "DSCPolicy"; + PPTenantId = "e91d4e0e-d5a5-4e3a-be14-2192592a59af"; + TenantId = $TenantId; + } + } +} +``` + From c3c8d21fb506e369f6afa73767aa5919664b97fe Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 11 Oct 2024 16:37:27 +0000 Subject: [PATCH 179/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 27653bf947..0091590937 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -39894,6 +39894,81 @@ } ] }, + { + "ClassName": "MSFT_PPPowerAPpPolicyUrlPatternsRule", + "Parameters": [ + { + "CIMType": "String", + "Name": "order", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "customConnectorRuleClassification", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "pattern", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_PPPowerAppPolicyUrlPatterns", + "Parameters": [ + { + "CIMType": "String", + "Name": "PolicyName", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "PPTenantId", + "Option": "Key" + }, + { + "CIMType": "MSFT_PPPowerAPpPolicyUrlPatternsRule[]", + "Name": "RuleSet", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_PPPowerAppsEnvironment", "Parameters": [ From 95d2c93f01cb74271063fdbf41fc9a77cb4a842c Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Fri, 11 Oct 2024 11:56:14 -0700 Subject: [PATCH 180/252] no message --- .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 index f0e7cd245e..4267b4c264 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 @@ -44,7 +44,7 @@ function Get-TargetResource [Parameter()] [System.String] - $Notes, + $Notes, klkdslakd [Parameter()] [System.String] From 1f3d95fa74de897140d24601bf5918f651093304 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Fri, 11 Oct 2024 11:58:51 -0700 Subject: [PATCH 181/252] fixed UTs. --- .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 2 +- .../Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 | 2 +- .../Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 index 4267b4c264..f0e7cd245e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 @@ -44,7 +44,7 @@ function Get-TargetResource [Parameter()] [System.String] - $Notes, klkdslakd + $Notes, [Parameter()] [System.String] diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 index 1901c61b5e..41a30afc06 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 @@ -41,7 +41,7 @@ Configuration Example Assignments = @( MSFT_DeviceManagementMobileAppAssignment { groupDisplayName = 'All devices' - source = 'direct' + source = 'dataType' deviceAndAppManagementAssignmentFilterType = 'none' dataType = '#microsoft.graph.allDevicesAssignmentTarget' intent = 'required' diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 index 88dcec1ff8..67bca9bd7f 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 @@ -42,7 +42,7 @@ Configuration Example Assignments = @( MSFT_DeviceManagementMobileAppAssignment { groupDisplayName = 'All devices' - source = 'direct' + source = 'dataType' deviceAndAppManagementAssignmentFilterType = 'none' dataType = '#microsoft.graph.allDevicesAssignmentTarget' intent = 'required' From 3edce46b14cd39da8e145c012f42013fb747a89e Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 11 Oct 2024 15:17:00 -0400 Subject: [PATCH 182/252] PPDLPPolicyConnectorConfigurations - Initial Release --- CHANGELOG.md | 2 + ...FT_PPDLPPolicyConnectorConfigurations.psm1 | 472 ++++++++++++++++++ ...LPPolicyConnectorConfigurations.schema.mof | 30 ++ .../readme.md | 6 + .../settings.json | 20 + .../1-Create.ps1 | 46 ++ .../2-Update.ps1 | 46 ++ .../3-Remove.ps1 | 34 ++ ...DLPPolicyConnectorConfigurations.Tests.ps1 | 231 +++++++++ Tests/Unit/Stubs/Microsoft365.psm1 | 55 ++ 10 files changed, 942 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_PPDLPPolicyConnectorConfigurations/MSFT_PPDLPPolicyConnectorConfigurations.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_PPDLPPolicyConnectorConfigurations/MSFT_PPDLPPolicyConnectorConfigurations.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_PPDLPPolicyConnectorConfigurations/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_PPDLPPolicyConnectorConfigurations/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/PPDLPPolicyConnectorConfigurations/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/PPDLPPolicyConnectorConfigurations/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/PPDLPPolicyConnectorConfigurations/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.PPDLPPolicyConnectorConfigurations.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index b096d97f8c..3b6d19afb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,8 @@ * Initial release * PPAdminDLPPolicy * Initial release. +* PPDLPPolicyConnectorConfigurations + * Initial release. * PPPowerAppPolicyUrlPatterns * Initial release. * M365DSCDRGUtil diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_PPDLPPolicyConnectorConfigurations/MSFT_PPDLPPolicyConnectorConfigurations.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_PPDLPPolicyConnectorConfigurations/MSFT_PPDLPPolicyConnectorConfigurations.psm1 new file mode 100644 index 0000000000..ea6471b259 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_PPDLPPolicyConnectorConfigurations/MSFT_PPDLPPolicyConnectorConfigurations.psm1 @@ -0,0 +1,472 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $PPTenantId, + + [Parameter(Mandatory = $true)] + [System.String] + $PolicyName, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $ConnectorActionConfigurations, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'PowerPlatforms' ` + -InboundParameters $PSBoundParameters | Out-Null + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + try + { + $policy = Get-AdminDlpPolicy | Where-Object -FilterScript {$_.DisplayName -eq $PolicyName} + + if ($null -eq $policy) + { + return $nullResult + } + + $ActionList = Get-PowerAppDlpPolicyConnectorConfigurations -TenantID $PPTenantId ` + -PolicyName $($policy.PolicyName) + $ActionsValue = @() + foreach ($action in $ActionList.connectorActionConfigurations) + { + $entry = @{ + connectorId = $action.connectorId + defaultConnectorActionRuleBehavior = $action.defaultConnectorActionRuleBehavior + } + + $actionRulesValues = @() + foreach ($rule in $action.actionRules) + { + $actionRulesValues += @{ + actionId = $rule.actionId + behavior = $rule.behavior + } + } + $entry.Add('actionRules', $actionRulesValues) + $ActionsValue += $entry + } + + $results = @{ + PPTenantId = $PPTenantId + PolicyName = $PolicyName + ConnectorActionConfigurations = $ActionsValue + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $PPTenantId, + + [Parameter(Mandatory = $true)] + [System.String] + $PolicyName, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $ConnectorActionConfigurations, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'PowerPlatforms' ` + -InboundParameters $PSBoundParameters | Out-Null + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $policy = Get-AdminDlpPolicy | Where-Object -FilterScript {$_.DisplayName -eq $PolicyName} + $policyNameValue = $policy.PolicyName + + # CREATE + if ($Ensure -eq 'Present') + { + $body = @{ + connectorActionConfigurations = @() + } + + foreach ($action in $connectorActionConfigurations) + { + $entry = @{ + connectorId = $action.connectorId + defaultConnectorActionRuleBehavior = $action.defaultConnectorActionRuleBehavior + } + + $ruleValues = @() + foreach ($rule in $actionRules) + { + $ruleValues += @{ + actionId = $rule.actionId + behavior = $rule.behavior + } + } + $entry.Add('actionRules', $ruleValues) + $body.connectorActionConfigurations += $entry + } + $payload = $(ConvertTo-Json $body -Depth 9 -Compress) + Write-Verbose -Message "Setting Connector Configuration for Policy {$($PolicyNameValue)} with parameters:`r`n$payload" + + New-PowerAppDlpPolicyConnectorConfigurations -TenantId $PPTenantId ` + -PolicyName $policyNameValue ` + -NewDlpPolicyConnectorConfigurations $body ` + -Verbose + } + # REMOVE + elseif ($Ensure -eq 'Absent') + { + Write-Verbose -Message "Removing Connector Configuration for Policy {$($PolicyNameValue)}" + Remove-PowerAppDlpPolicyConnectorConfigurations -TenantId $PPTenantId -PolicyName $policyNameValue + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $PPTenantId, + + [Parameter(Mandatory = $true)] + [System.String] + $PolicyName, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $ConnectorActionConfigurations, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + #Compare Cim instances + foreach ($key in $PSBoundParameters.Keys) + { + $source = $PSBoundParameters.$key + $target = $CurrentValues.$key + if ($source.getType().Name -like '*CimInstance*') + { + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + if (-Not $testResult) + { + $testResult = $false + break + } + + $ValuesToCheck.Remove($key) | Out-Null + } + } + if ($testResult) + { + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + } + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'PowerPlatforms' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + $Script:ExportMode = $true + $tenantInfo = Get-TenantDetailsFromGraph + [array] $policies = Get-AdminDlpPolicy -ErrorAction Stop + + $dscContent = '' + if ($policies.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + $i = 1 + foreach ($policy in $policies) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + Write-Host " |---[$i/$($policies.Count)] $($policy.DisplayName)" -NoNewline + $params = @{ + PPTenantId = $tenantInfo.TenantId + PolicyName = $policy.DisplayName + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + if ($null -ne $Results.ConnectorActionConfigurations) + { + $complexMapping = @( + @{ + Name = 'actionRules' + CimInstanceName = 'PPDLPPolicyConnectorConfigurationsActionRules' + IsRequired = $False + } + ) + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.ConnectorActionConfigurations ` + -CIMInstanceName 'PPDLPPolicyConnectorConfigurationsAction' ` + -ComplexTypeMapping $complexMapping + if (-Not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.ConnectorActionConfigurations = $complexTypeStringResult + } + else + { + $Results.Remove('ConnectorActionConfigurations') | Out-Null + } + } + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + if ($Results.ConnectorActionConfigurations) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'ConnectorActionConfigurations' -IsCIMArray:$true + } + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $k++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + + $i++ + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_PPDLPPolicyConnectorConfigurations/MSFT_PPDLPPolicyConnectorConfigurations.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_PPDLPPolicyConnectorConfigurations/MSFT_PPDLPPolicyConnectorConfigurations.schema.mof new file mode 100644 index 0000000000..2324766826 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_PPDLPPolicyConnectorConfigurations/MSFT_PPDLPPolicyConnectorConfigurations.schema.mof @@ -0,0 +1,30 @@ +[ClassVersion("1.0.0.0")] +class MSFT_PPDLPPolicyConnectorConfigurationsActionRules +{ + [Write, Description("Id of the action.")] String actionId; + [Write, Description("Associated behavior.")] String behavior; +}; + +[ClassVersion("1.0.0.0")] +class MSFT_PPDLPPolicyConnectorConfigurationsAction +{ + [Write, Description("Unique id of the connector.")] String connectorId; + [Write, Description("Default action behavior for to connector.")] String defaultConnectorActionRuleBehavior; + [Write, Description("List of associated actions."), EmbeddedInstance("MSFT_PPDLPPolicyConnectorConfigurationsActionRules")] String actionRules[]; +}; + +[ClassVersion("1.0.0.0"), FriendlyName("PPDLPPolicyConnectorConfigurations")] +class MSFT_PPDLPPolicyConnectorConfigurations : OMI_BaseResource +{ + [Key, Description("The policy name identifier.")] String PolicyName; + [Key, Description("The tenant identifier.")] String PPTenantId; + [Write, Description("Set of cnnector actions associated with the policy."), EmbeddedInstance("MSFT_PPDLPPolicyConnectorConfigurationsAction")] String ConnectorActionConfigurations[]; + + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Absent","Present"}, Values{"Absent","Present"}] string Ensure; + [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_PPDLPPolicyConnectorConfigurations/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_PPDLPPolicyConnectorConfigurations/readme.md new file mode 100644 index 0000000000..530565738e --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_PPDLPPolicyConnectorConfigurations/readme.md @@ -0,0 +1,6 @@ + +# PPDLPPolicyConnectorConfigurations + +## Description + +Configures connectors Data Loss Prevention policies in Power Platforms. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_PPDLPPolicyConnectorConfigurations/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_PPDLPPolicyConnectorConfigurations/settings.json new file mode 100644 index 0000000000..cde694440e --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_PPDLPPolicyConnectorConfigurations/settings.json @@ -0,0 +1,20 @@ +{ + "resourceName": "PPDLPPolicyConnectorConfigurations", + "description": "Configures connectors Data Loss Prevention policies in Power Platforms.", + "roles": { + "read": [], + "update": [] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/PPDLPPolicyConnectorConfigurations/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/PPDLPPolicyConnectorConfigurations/1-Create.ps1 new file mode 100644 index 0000000000..494899726e --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/PPDLPPolicyConnectorConfigurations/1-Create.ps1 @@ -0,0 +1,46 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + PPDLPPolicyConnectorConfigurations "PPDLPPolicyConnectorConfigurations-9fdd99b8-6c9f-4e9c-aafe-1a4c1e4fe451" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + ConnectorActionConfigurations = @( + MSFT_PPDLPPolicyConnectorConfigurationsAction{ + actionRules = @( + MSFT_PPDLPPolicyConnectorConfigurationsActionRules{ + actionId = 'CreateInvitation' + behavior = 'Allow' + } + ) + connectorId = '/providers/Microsoft.PowerApps/apis/shared_aadinvitationmanager' + defaultConnectorActionRuleBehavior = 'Allow' + } + ); + Ensure = "Present"; + PolicyName = "DSCPolicy"; + PPTenantId = "e91d4e0e-d5a5-4e3a-be14-2192592a59af"; + TenantId = $TenantId; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/PPDLPPolicyConnectorConfigurations/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/PPDLPPolicyConnectorConfigurations/2-Update.ps1 new file mode 100644 index 0000000000..402a6bf2e6 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/PPDLPPolicyConnectorConfigurations/2-Update.ps1 @@ -0,0 +1,46 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + PPDLPPolicyConnectorConfigurations "PPDLPPolicyConnectorConfigurations-9fdd99b8-6c9f-4e9c-aafe-1a4c1e4fe451" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + ConnectorActionConfigurations = @( + MSFT_PPDLPPolicyConnectorConfigurationsAction{ + actionRules = @( + MSFT_PPDLPPolicyConnectorConfigurationsActionRules{ + actionId = 'CreateInvitation' + behavior = 'Block' #drift + } + ) + connectorId = '/providers/Microsoft.PowerApps/apis/shared_aadinvitationmanager' + defaultConnectorActionRuleBehavior = 'Allow' + } + ); + Ensure = "Present"; + PolicyName = "DSCPolicy"; + PPTenantId = "e91d4e0e-d5a5-4e3a-be14-2192592a59af"; + TenantId = $TenantId; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/PPDLPPolicyConnectorConfigurations/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/PPDLPPolicyConnectorConfigurations/3-Remove.ps1 new file mode 100644 index 0000000000..72d8324ff1 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/PPDLPPolicyConnectorConfigurations/3-Remove.ps1 @@ -0,0 +1,34 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + PPDLPPolicyConnectorConfigurations "PPDLPPolicyConnectorConfigurations-9fdd99b8-6c9f-4e9c-aafe-1a4c1e4fe451" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Absent"; + PolicyName = "DSCPolicy"; + PPTenantId = "e91d4e0e-d5a5-4e3a-be14-2192592a59af"; + TenantId = $TenantId; + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.PPDLPPolicyConnectorConfigurations.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.PPDLPPolicyConnectorConfigurations.Tests.ps1 new file mode 100644 index 0000000000..bfb5d25c7e --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.PPDLPPolicyConnectorConfigurations.Tests.ps1 @@ -0,0 +1,231 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -GenericStubModule $GenericStubPath + +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + Mock -commandName Remove-PowerAppDlpPolicyConnectorConfigurations -MockWith {} + Mock -commandName New-PowerAppDlpPolicyConnectorConfigurations -MockWith {} + Mock -commandName Get-TenantDetailsFromGraph -MockWith { + return @{ + TenantId = 'xxxxxxx' + } + } + Mock -commandName Get-AdminDlpPolicy -MockWith { + return @{ + PolicyName = 'DSCPolicy' + DisplayName = 'DSCPolicy' + } + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + ConnectorActionConfigurations = + (New-CimInstance -ClassName 'MSFT_PPDLPPolicyConnectorConfigurationsAction' -Property @{ + actionRules = (New-CimInstance -ClassName 'MSFT_PPDLPPolicyConnectorConfigurationsActionRules' -Property @{ + actionId = 'CreateInvitation' + behavior = 'Block' + } -ClientOnly) + connectorId = '/providers/Microsoft.PowerApps/apis/shared_aadinvitationmanager' + defaultConnectorActionRuleBehavior = 'Allow' + } -ClientOnly) + PolicyName = "DSCPolicy"; + PPTenantId = "e91d4e0e-d5a5-4e3a-be14-2192592a59af"; + Ensure = 'Absent' + Credential = $Credential; + } + + Mock -CommandName Get-PowerAppDlpPolicyConnectorConfigurations -MockWith { + return @{ + connectorActionConfigurations = @( + @{ + connectorId = '/providers/Microsoft.PowerApps/apis/shared_aadinvitationmanager' + defaultConnectorActionRuleBehavior = 'Allow' + actionRules = @( + @{ + actionId = 'CreateInvitation' + behavior = 'Allow' + } + ) + } + ) + } + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should remove the instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-PowerAppDlpPolicyConnectorConfigurations -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ConnectorActionConfigurations = + (New-CimInstance -ClassName 'MSFT_PPDLPPolicyConnectorConfigurationsAction' -Property @{ + actionRules = (New-CimInstance -ClassName 'MSFT_PPDLPPolicyConnectorConfigurationsActionRules' -Property @{ + actionId = 'CreateInvitation' + behavior = 'Block' + } -ClientOnly) + connectorId = '/providers/Microsoft.PowerApps/apis/shared_aadinvitationmanager' + defaultConnectorActionRuleBehavior = 'Allow' + } -ClientOnly) + PolicyName = "DSCPolicy"; + PPTenantId = "e91d4e0e-d5a5-4e3a-be14-2192592a59af"; + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-PowerAppDlpPolicyConnectorConfigurations -MockWith { + return @{ + connectorActionConfigurations = @( + @{ + connectorId = '/providers/Microsoft.PowerApps/apis/shared_aadinvitationmanager' + defaultConnectorActionRuleBehavior = 'Allow' + actionRules = @( + @{ + actionId = 'CreateInvitation' + behavior = 'Block' + } + ) + } + ) + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ConnectorActionConfigurations = + (New-CimInstance -ClassName 'MSFT_PPDLPPolicyConnectorConfigurationsAction' -Property @{ + actionRules = (New-CimInstance -ClassName 'MSFT_PPDLPPolicyConnectorConfigurationsActionRules' -Property @{ + actionId = 'CreateInvitation' + behavior = 'Block' + } -ClientOnly) + connectorId = '/providers/Microsoft.PowerApps/apis/shared_aadinvitationmanager' + defaultConnectorActionRuleBehavior = 'Allow' + } -ClientOnly) + PolicyName = "DSCPolicy"; + PPTenantId = "e91d4e0e-d5a5-4e3a-be14-2192592a59af"; + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-PowerAppDlpPolicyConnectorConfigurations -MockWith { + return @{ + connectorActionConfigurations = @( + @{ + connectorId = '/providers/Microsoft.PowerApps/apis/shared_aadinvitationmanager' + defaultConnectorActionRuleBehavior = 'Allow' + actionRules = @( + @{ + actionId = 'CreateInvitation' + behavior = 'Allow' #Drift + } + ) + } + ) + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-PowerAppDlpPolicyConnectorConfigurations -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + Mock -CommandName Get-PowerAppDlpPolicyConnectorConfigurations -MockWith { + return @{ + connectorActionConfigurations = @( + @{ + connectorId = '/providers/Microsoft.PowerApps/apis/shared_aadinvitationmanager' + defaultConnectorActionRuleBehavior = 'Allow' + actionRules = @( + @{ + actionId = 'CreateInvitation' + behavior = 'Block' #Drift + } + ) + } + ) + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index b75ebef3fc..b5c7007061 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -96975,3 +96975,58 @@ function Get-TenantDetailsFromGraph $GraphApiVersion ) } +function Remove-PowerAppDlpPolicyConnectorConfigurations +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $PolicyName, + + [Parameter()] + [System.String] + $ApiVersion + ) +} +function New-PowerAppDlpPolicyConnectorConfigurations +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $PolicyName, + + [Parameter()] + [System.String] + $ApiVersion, + + [Parameter()] + [System.Object] + $NewDlpPolicyConnectorConfigurations + ) +} +function Get-PowerAppDlpPolicyConnectorConfigurations +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $PolicyName, + + [Parameter()] + [System.String] + $ApiVersion + ) +} From e1b8391dee9804ed9cff3a2c4bc7b78c9b9a3d20 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 11 Oct 2024 19:33:00 +0000 Subject: [PATCH 183/252] Updated Resources and Cmdlet documentation pages --- .../PPDLPPolicyConnectorConfigurations.md | 204 ++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 docs/docs/resources/power-platform/PPDLPPolicyConnectorConfigurations.md diff --git a/docs/docs/resources/power-platform/PPDLPPolicyConnectorConfigurations.md b/docs/docs/resources/power-platform/PPDLPPolicyConnectorConfigurations.md new file mode 100644 index 0000000000..a1731db384 --- /dev/null +++ b/docs/docs/resources/power-platform/PPDLPPolicyConnectorConfigurations.md @@ -0,0 +1,204 @@ +# PPDLPPolicyConnectorConfigurations + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **PolicyName** | Key | String | The policy name identifier. | | +| **PPTenantId** | Key | String | The tenant identifier. | | +| **ConnectorActionConfigurations** | Write | MSFT_PPDLPPolicyConnectorConfigurationsAction[] | Set of cnnector actions associated with the policy. | | +| **Ensure** | Write | String | Present ensures the instance exists, absent ensures it is removed. | `Absent`, `Present` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + +### MSFT_PPDLPPolicyConnectorConfigurationsActionRules + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **actionId** | Write | String | Id of the action. | | +| **behavior** | Write | String | Associated behavior. | | + +### MSFT_PPDLPPolicyConnectorConfigurationsAction + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **connectorId** | Write | String | Unique id of the connector. | | +| **defaultConnectorActionRuleBehavior** | Write | String | Default action behavior for to connector. | | +| **actionRules** | Write | MSFT_PPDLPPolicyConnectorConfigurationsActionRules[] | List of associated actions. | | + + +## Description + +Configures connectors Data Loss Prevention policies in Power Platforms. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - None + +- **Update** + + - None + +## Examples + +### Example 1 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + PPDLPPolicyConnectorConfigurations "PPDLPPolicyConnectorConfigurations-9fdd99b8-6c9f-4e9c-aafe-1a4c1e4fe451" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + ConnectorActionConfigurations = @( + MSFT_PPDLPPolicyConnectorConfigurationsAction{ + actionRules = @( + MSFT_PPDLPPolicyConnectorConfigurationsActionRules{ + actionId = 'CreateInvitation' + behavior = 'Allow' + } + ) + connectorId = '/providers/Microsoft.PowerApps/apis/shared_aadinvitationmanager' + defaultConnectorActionRuleBehavior = 'Allow' + } + ); + Ensure = "Present"; + PolicyName = "DSCPolicy"; + PPTenantId = "e91d4e0e-d5a5-4e3a-be14-2192592a59af"; + TenantId = $TenantId; + } + } +} +``` + +### Example 2 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + PPDLPPolicyConnectorConfigurations "PPDLPPolicyConnectorConfigurations-9fdd99b8-6c9f-4e9c-aafe-1a4c1e4fe451" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + ConnectorActionConfigurations = @( + MSFT_PPDLPPolicyConnectorConfigurationsAction{ + actionRules = @( + MSFT_PPDLPPolicyConnectorConfigurationsActionRules{ + actionId = 'CreateInvitation' + behavior = 'Block' #drift + } + ) + connectorId = '/providers/Microsoft.PowerApps/apis/shared_aadinvitationmanager' + defaultConnectorActionRuleBehavior = 'Allow' + } + ); + Ensure = "Present"; + PolicyName = "DSCPolicy"; + PPTenantId = "e91d4e0e-d5a5-4e3a-be14-2192592a59af"; + TenantId = $TenantId; + } + } +} +``` + +### Example 3 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + PPDLPPolicyConnectorConfigurations "PPDLPPolicyConnectorConfigurations-9fdd99b8-6c9f-4e9c-aafe-1a4c1e4fe451" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Absent"; + PolicyName = "DSCPolicy"; + PPTenantId = "e91d4e0e-d5a5-4e3a-be14-2192592a59af"; + TenantId = $TenantId; + } + } +} +``` + From ce27cb83a4f168482b396663a2c2474a61085324 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 11 Oct 2024 19:35:38 +0000 Subject: [PATCH 184/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 0091590937..4844f64a3c 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -39894,6 +39894,96 @@ } ] }, + { + "ClassName": "MSFT_PPDLPPolicyConnectorConfigurationsActionRules", + "Parameters": [ + { + "CIMType": "String", + "Name": "actionId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "behavior", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_PPDLPPolicyConnectorConfigurationsAction", + "Parameters": [ + { + "CIMType": "String", + "Name": "connectorId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "defaultConnectorActionRuleBehavior", + "Option": "Write" + }, + { + "CIMType": "MSFT_PPDLPPolicyConnectorConfigurationsActionRules[]", + "Name": "actionRules", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_PPDLPPolicyConnectorConfigurations", + "Parameters": [ + { + "CIMType": "String", + "Name": "PolicyName", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "PPTenantId", + "Option": "Key" + }, + { + "CIMType": "MSFT_PPDLPPolicyConnectorConfigurationsAction[]", + "Name": "ConnectorActionConfigurations", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_PPPowerAPpPolicyUrlPatternsRule", "Parameters": [ From b84ca9e5e7b5a6f57ddf5927817764bcba78a9ef Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Fri, 11 Oct 2024 12:43:49 -0700 Subject: [PATCH 185/252] examples fixed for macos lob app. --- .../Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 index 67bca9bd7f..f7746f29b1 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 @@ -42,7 +42,6 @@ Configuration Example Assignments = @( MSFT_DeviceManagementMobileAppAssignment { groupDisplayName = 'All devices' - source = 'dataType' deviceAndAppManagementAssignmentFilterType = 'none' dataType = '#microsoft.graph.allDevicesAssignmentTarget' intent = 'required' From 360c82b29cf5ba386956cccca29019a26ee22ed6 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Fri, 11 Oct 2024 12:55:03 -0700 Subject: [PATCH 186/252] fixed create example. --- .../Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 index 41a30afc06..f19c52da7d 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 @@ -41,7 +41,6 @@ Configuration Example Assignments = @( MSFT_DeviceManagementMobileAppAssignment { groupDisplayName = 'All devices' - source = 'dataType' deviceAndAppManagementAssignmentFilterType = 'none' dataType = '#microsoft.graph.allDevicesAssignmentTarget' intent = 'required' From 357c18ed0b4b02975056f3638544be721406acbf Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Wed, 9 Oct 2024 20:08:05 -0700 Subject: [PATCH 187/252] update parameters and filter --- ...IntuneMobileAppsWindowsOfficeSuiteApp.psm1 | 1231 +++++++++++++++++ ...MobileAppsWindowsOfficeSuiteApp.schema.mof | 14 + .../readme.md | 6 + .../settings.json | 32 + .../1-Create.ps1 | 26 + .../2-Update.ps1 | 26 + .../3-Remove.ps1 | 26 + ...eMobileAppsWindowsOfficeSuiteApp.Tests.ps1 | 178 +++ 8 files changed, 1539 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 new file mode 100644 index 0000000000..f616acf07a --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 @@ -0,0 +1,1231 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + #region Intune resource parameters + + [Parameter()] + [System.String] + $Id, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $Publisher, + + [Parameter()] + [System.Boolean] + $IsFeatured, + + [Parameter()] + [System.String] + $PrivacyInformationUrl, + + [Parameter()] + [System.String] + $InformationUrl, + + [Parameter()] + [System.String] + $Owner, + + [Parameter()] + [System.String] + $Developer, + + [Parameter()] + [System.String] + $Notes, + + [Parameter()] + [System.String] + [ValidateSet('notPublished', 'processing','published')] + $PublishingState, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.Boolean] + $AutoAcceptEula, + + [Parameter()] + [System.String[]] + $ProductIds, + + [Parameter()] + [PSCustomObject] + $ExcludedApps, + + [Parameter()] + [System.Boolean] + $UseSharedComputerActivation, + + [Parameter()] + [System.String] + [ValidateSet('current', 'monthlyEnterprise', 'semiAnnual')] + $UpdateChannel = 'monthlyEnterprise', + + [Parameter()] + [System.String] + [ValidateSet('officeOpenDocumentFormat', 'binaryFormat')] + $OfficeSuiteAppDefaultFileFormat, + + [Parameter()] + [System.String] + [ValidateSet('x86', 'x64')] + $OfficePlatformArchitecture = 'x64', + + [Parameter()] + [System.String[]] + $LocalesToInstall, + + [Parameter()] + [System.String] + [ValidateSet('none', 'full')] + $InstallProgressDisplayLevel = 'none', + + [Parameter()] + [System.Boolean] + $ShouldUninstallOlderVersionsOfOffice = $true, + + [Parameter()] + [System.String] + $TargetVersion = "", +> + [Parameter()] + [System.String] + $UpdateVersion = "", + + [Parameter()] + [System.Byte[]] + $OfficeConfigurationXml, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Categories, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $LargeIcon, + + #endregion + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters | Out-Null + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + try + { + $instance = Get-MgBetaDeviceAppManagementMobileApp ` + -Filter "(isof('microsoft.graph.officeSuiteApp') and displayName eq '$DisplayName')" ` + -ExpandProperty "categories,assignments" ` + -ErrorAction SilentlyContinue | Where-Object ` + -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.officeSuiteApp' } + + if ($null -eq $instance) + { + Write-Verbose -Message "No Mobile app with DisplayName {$DisplayName} was found. Search with DisplayName." + $instance = Get-MgBetaDeviceAppManagementMobileApp ` + -MobileAppId $Id ` + -ExpandProperty "categories,assignments" ` + -ErrorAction Stop | Where-Object ` + -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.officeSuiteApp' } + } + + if ($null -eq $instance) + { + Write-Verbose -Message "No Mobile app with {$Id} was found." + return $nullResult + } + + $results = @{ + Id = $instance.Id + Description = $instance.Description + Developer = $instance.Developer + DisplayName = $instance.DisplayName + InformationUrl = $instance.InformationUrl + IsFeatured = $instance.IsFeatured + Notes = $instance.Notes + Owner = $instance.Owner + PrivacyInformationUrl = $instance.PrivacyInformationUrl + Publisher = $instance.Publisher + PublishingState = $instance.PublishingState.ToString() + RoleScopeTagIds = $instance.RoleScopeTagIds + BundleId = $instance.BundleId + BuildNumber = $instance.BuildNumber + VersionNumber = $instance.VersionNumber + IgnoreVersionDetection = $instance.AdditionalProperties.ignoreVersionDetection + + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ApplicationSecret = $ApplicationSecret + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + #region complex types + + #Categories + if($null -ne $instance.Categories) + { + $results.Add('Categories', $instance.Categories) + } + else { + $results.Add('Categories', "") + } + + #childApps + if($null -ne $instance.AdditionalProperties.childApps) + { + $results.Add('ChildApps', $instance.AdditionalProperties.childApps) + } + else { + $results.Add('ChildApps', "") + } + + #Assignments + $resultAssignments = @() + $appAssignments = Get-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $instance.Id + if ($null -ne $appAssignments -and $appAssignments.count -gt 0) + { + $resultAssignments += ConvertFrom-IntuneMobileAppAssignment ` + -IncludeDeviceFilter:$true ` + -Assignments ($appAssignments) + + $results.Add('Assignments', $resultAssignments) + } + + #LargeIcon + # The large is returned only when Get cmdlet is called with Id parameter. The large icon is a base64 encoded string, so we need to convert it to a byte array. + $instanceWithLargeIcon = Get-MgBetaDeviceAppManagementMobileApp -MobileAppId $instance.Id + if($null -ne $instanceWithLargeIcon.LargeIcon) + { + $results.Add('LargeIcon', $instanceWithLargeIcon.LargeIcon) + } + else { + $results.Add('LargeIcon', "") + } + + #end region complex types + + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + #region Intune resource parameters + + [Parameter()] + [System.String] + $Id, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $Publisher, + + [Parameter()] + [System.Boolean] + $IsFeatured, + + [Parameter()] + [System.String] + $PrivacyInformationUrl, + + [Parameter()] + [System.String] + $InformationUrl, + + [Parameter()] + [System.String] + $Owner, + + [Parameter()] + [System.String] + $Developer, + + [Parameter()] + [System.String] + $Notes, + + [Parameter()] + [System.String] + [ValidateSet('notPublished', 'processing','published')] + $PublishingState, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.Boolean] + $AutoAcceptEula, + + [Parameter()] + [System.String[]] + $ProductIds, + + [Parameter()] + [PSCustomObject] + $ExcludedApps, + + [Parameter()] + [System.Boolean] + $UseSharedComputerActivation, + + [Parameter()] + [System.String] + [ValidateSet('current', 'monthlyEnterprise', 'semiAnnual')] + $UpdateChannel = 'monthlyEnterprise', + + [Parameter()] + [System.String] + [ValidateSet('officeOpenDocumentFormat', 'binaryFormat')] + $OfficeSuiteAppDefaultFileFormat, + + [Parameter()] + [System.String] + [ValidateSet('x86', 'x64')] + $OfficePlatformArchitecture = 'x64', + + [Parameter()] + [System.String[]] + $LocalesToInstall, + + [Parameter()] + [System.String] + [ValidateSet('none', 'full')] + $InstallProgressDisplayLevel = 'none', + + [Parameter()] + [System.Boolean] + $ShouldUninstallOlderVersionsOfOffice = $true, + + [Parameter()] + [System.String] + $TargetVersion = "", +> + [Parameter()] + [System.String] + $UpdateVersion = "", + + [Parameter()] + [System.Byte[]] + $OfficeConfigurationXml, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Categories, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $LargeIcon, + + #endregion + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + $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 + + $CreateParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + Write-Host "Create MacOS app: $DisplayName" + + $CreateParameters = ([Hashtable]$PSBoundParameters).clone() + $CreateParameters = Rename-M365DSCCimInstanceParameter -Properties $CreateParameters + + $AdditionalProperties = Get-M365DSCIntuneMobileMocOSLobAppAdditionalProperties -Properties ($CreateParameters) + foreach ($key in $AdditionalProperties.keys) + { + if ($key -ne '@odata.type') + { + $keyName = $key.substring(0, 1).ToUpper() + $key.substring(1, $key.length - 1) + $CreateParameters.remove($keyName) + } + } + + $CreateParameters.remove('Id') | Out-Null + $CreateParameters.remove('Ensure') | Out-Null + $CreateParameters.remove('Categories') | Out-Null + $CreateParameters.remove('Assignments') | Out-Null + $CreateParameters.remove('childApps') | Out-Null + $CreateParameters.remove('IgnoreVersionDetection') | Out-Null + $CreateParameters.Remove('Verbose') | Out-Null + $CreateParameters.Remove('PublishingState') | Out-Null #Not allowed to update as it's a computed property + $CreateParameters.Remove('LargeIcon') | Out-Null + + foreach ($key in ($CreateParameters.clone()).Keys) + { + if ($CreateParameters[$key].getType().Fullname -like '*CimInstance*') + { + $CreateParameters[$key] = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $CreateParameters[$key] + } + } + + if ($AdditionalProperties) + { + $CreateParameters.add('AdditionalProperties', $AdditionalProperties) + } + + #LargeIcon + if($LargeIcon) + { + [System.Object]$LargeIconValue = ConvertTo-M365DSCIntuneAppLargeIcon -LargeIcon $LargeIcon + $CreateParameters.Add('LargeIcon', $LargeIconValue) + } + + $app = New-MgBetaDeviceAppManagementMobileApp @CreateParameters + + #Assignments + $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + if ($app.id) + { + Update-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $app.id ` + -Target $assignmentsHash ` + -Repository 'deviceAppManagement/mobileAppAssignments' + } + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Write-Host "Update MacOS app: $DisplayName" + + $PSBoundParameters.Remove('Assignments') | Out-Null + $UpdateParameters = ([Hashtable]$PSBoundParameters).clone() + $UpdateParameters = Rename-M365DSCCimInstanceParameter -Properties $UpdateParameters + + $AdditionalProperties = Get-M365DSCIntuneMobileMocOSLobAppAdditionalProperties -Properties ($UpdateParameters) + foreach ($key in $AdditionalProperties.keys) + { + if ($key -ne '@odata.type') + { + $keyName = $key.substring(0, 1).ToUpper() + $key.substring(1, $key.length - 1) + #Remove additional keys, so that later they can be added as 'AdditionalProperties' + $UpdateParameters.Remove($keyName) + } + } + + $UpdateParameters.Remove('Id') | Out-Null + $UpdateParameters.Remove('Verbose') | Out-Null + $UpdateParameters.Remove('Categories') | Out-Null + $UpdateParameters.Remove('PublishingState') | Out-Null #Not allowed to update as it's a computed property + + foreach ($key in ($UpdateParameters.clone()).Keys) + { + if ($UpdateParameters[$key].getType().Fullname -like '*CimInstance*') + { + $value = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $UpdateParameters[$key] + $UpdateParameters[$key] = $value + } + } + + if ($AdditionalProperties) + { + $UpdateParameters.Add('AdditionalProperties', $AdditionalProperties) + } + + #LargeIcon + if($LargeIcon) + { + [System.Object]$LargeIconValue = ConvertTo-M365DSCIntuneAppLargeIcon -LargeIcon $LargeIcon + $UpdateParameters.Add('LargeIcon', $LargeIconValue) + } + + Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id @UpdateParameters + Write-Host "Updated MacOS App: $DisplayName." + + #Assignments + $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + Update-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $currentInstance.id ` + -Target $assignmentsHash ` + -Repository 'deviceAppManagement/mobileAppAssignments' + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Write-Host "Remove MacOS app: $DisplayName" + Remove-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id -Confirm:$false + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + #region Intune resource parameters + + [Parameter()] + [System.String] + $Id, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $Publisher, + + [Parameter()] + [System.Boolean] + $IsFeatured, + + [Parameter()] + [System.String] + $PrivacyInformationUrl, + + [Parameter()] + [System.String] + $InformationUrl, + + [Parameter()] + [System.String] + $Owner, + + [Parameter()] + [System.String] + $Developer, + + [Parameter()] + [System.String] + $Notes, + + [Parameter()] + [System.String] + [ValidateSet('notPublished', 'processing','published')] + $PublishingState, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.Boolean] + $AutoAcceptEula, + + [Parameter()] + [System.String[]] + $ProductIds, + + [Parameter()] + [PSCustomObject] + $ExcludedApps, + + [Parameter()] + [System.Boolean] + $UseSharedComputerActivation, + + [Parameter()] + [System.String] + [ValidateSet('current', 'monthlyEnterprise', 'semiAnnual')] + $UpdateChannel = 'monthlyEnterprise', + + [Parameter()] + [System.String] + [ValidateSet('officeOpenDocumentFormat', 'binaryFormat')] + $OfficeSuiteAppDefaultFileFormat, + + [Parameter()] + [System.String] + [ValidateSet('x86', 'x64')] + $OfficePlatformArchitecture = 'x64', + + [Parameter()] + [System.String[]] + $LocalesToInstall, + + [Parameter()] + [System.String] + [ValidateSet('none', 'full')] + $InstallProgressDisplayLevel = 'none', + + [Parameter()] + [System.Boolean] + $ShouldUninstallOlderVersionsOfOffice = $true, + + [Parameter()] + [System.String] + $TargetVersion = "", +> + [Parameter()] + [System.String] + $UpdateVersion = "", + + [Parameter()] + [System.Byte[]] + $OfficeConfigurationXml, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Categories, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $LargeIcon, + + #endregion + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + Write-Verbose -Message "Testing configuration of Intune Mobile MacOS App: {$DisplayName}" + + $CurrentValues = Get-TargetResource @PSBoundParameters + if (-not (Test-M365DSCAuthenticationParameter -BoundParameters $CurrentValues)) + { + Write-Verbose "An error occured in Get-TargetResource, the app {$displayName} will not be processed" + throw "An error occured in Get-TargetResource, the app {$displayName} will not be processed. Refer to the event viewer logs for more information." + } + $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() + $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck + $ValuesToCheck.Remove('Id') | Out-Null + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + + if ($CurrentValues.Ensure -ne $Ensure) + { + Write-Verbose -Message "Test-TargetResource returned $false" + return $false + } + $testResult = $true + + #Compare Cim instances + foreach ($key in $PSBoundParameters.Keys) + { + $source = $PSBoundParameters.$key + $target = $CurrentValues.$key + if ($source.getType().Name -like '*CimInstance*') + { + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + if (-Not $testResult) + { + $testResult = $false + break + } + + $ValuesToCheck.Remove($key) | Out-Null + } + } + + if ($testResult) + { + $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + } + + Write-Verbose -Message "Test-TargetResource returned $TestResult" + + return $TestResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + $Script:ExportMode = $true + [array] $Script:getInstances = Get-MgBetaDeviceAppManagementMobileApp ` + -Filter "isof('microsoft.graph.officeSuiteApp')" ` + -ExpandProperty "categories,assignments" ` + -ErrorAction Stop | Where-Object ` + -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.officeSuiteApp' } + + $i = 1 + $dscContent = '' + if ($Script:getInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + + foreach ($config in $Script:getInstances) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + $displayedKey = $config.Id + Write-Host " |---[$i/$($Script:getInstances.Count)] $displayedKey" -NoNewline + + $params = @{ + Id = $config.Id + DisplayName = $config.DisplayName + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ApplicationSecret = $ApplicationSecret + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + if (-not (Test-M365DSCAuthenticationParameter -BoundParameters $Results)) + { + Write-Verbose "An error occured in Get-TargetResource, the app {$($params.displayName)} will not be processed." + throw "An error occured in Get-TargetResource, the app {$($params.displayName)} will not be processed. Refer to the event viewer logs for more information." + } + + #region complex types + + #Categories + if($null -ne $Results.Categories) + { + $Results.Categories = Get-M365DSCIntuneAppCategoriesAsString -Categories $Results.Categories + } + else { + $Results.Remove('Categories') | Out-Null + } + + #ChildApps + if($null -ne $Results.childApps) + { + $Results.childApps = Get-M365DSCIntuneAppChildAppsAsString -ChildApps $Results.childApps + } + else { + $Results.Remove('childApps') | Out-Null + } + + #Assignments + if ($null -ne $Results.Assignments) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString -ComplexObject ([Array]$Results.Assignments) -CIMInstanceName DeviceManagementMobileAppAssignment + + if ($complexTypeStringResult) + { + $Results.Assignments = $complexTypeStringResult + } + else + { + $Results.Remove('Assignments') | Out-Null + } + } + + #LargeIcon + if($null -ne $Results.LargeIcon) + { + $Results.LargeIcon = Get-M365DSCIntuneAppLargeIconAsString -LargeIcon $Results.LargeIcon + } + else + { + $Results.Remove('LargeIcon') | Out-Null + } + + #endregion complex types + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + + #region complex types + + #Categories + if ($null -ne $Results.Categories) + { + $isCIMArray = $false + if ($Results.Categories.getType().Fullname -like '*[[\]]') + { + $isCIMArray = $true + } + + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Categories' -IsCIMArray:$isCIMArray + } + + #ChildApps + if ($null -ne $Results.childApps) + { + $isCIMArray = $false + if ($Results.childApps.getType().Fullname -like '*[[\]]') + { + $isCIMArray = $true + } + + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'ChildApps' -IsCIMArray:$isCIMArray + } + + #Assignments + if ($null -ne $Results.Assignments) + { + $isCIMArray = $false + if ($Results.Assignments.getType().Fullname -like '*[[\]]') + { + $isCIMArray = $true + } + + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Assignments' -IsCIMArray:$isCIMArray + } + + #LargeIcon + if ($null -ne $Results.LargeIcon) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'LargeIcon' -IsCIMArray:$false + } + + #endregion complex types + + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +#region Helper functions + +function Get-M365DSCIntuneAppCategoriesAsString +{ + [CmdletBinding()] + [OutputType([System.String])] + param( + [Parameter(Mandatory = $true)] + [System.Object[]] + $Categories + ) + + $StringContent = '@(' + $space = ' ' + $indent = ' ' + + $i = 1 + foreach ($category in $Categories) + { + if ($Categories.Count -gt 1) + { + $StringContent += "`r`n" + $StringContent += "$space" + } + + #Only export the displayName, not Id + $StringContent += "MSFT_DeviceManagementMobileAppCategory { `r`n" + $StringContent += "$($space)$($indent)displayName = '" + $category.displayName + "'`r`n" + $StringContent += "$space}" + + $i++ + } + + $StringContent += ')' + + return $StringContent +} + +function Get-M365DSCIntuneAppChildAppsAsString +{ + [CmdletBinding()] + [OutputType([System.String])] + param( + [Parameter(Mandatory = $true)] + [System.Object[]] + $ChildApps + ) + + $StringContent = '@(' + $space = ' ' + $indent = ' ' + + $i = 1 + foreach ($childApp in $ChildApps) + { + if ($ChildApps.Count -gt 1) + { + $StringContent += "`r`n" + $StringContent += "$space" + } + + $StringContent += "MSFT_DeviceManagementMobileAppChildApp { `r`n" + $StringContent += "$($space)$($indent)bundleId = '" + $childApp.bundleId + "'`r`n" + $StringContent += "$($space)$($indent)buildNumber = '" + $childApp.buildNumber + "'`r`n" + $StringContent += "$($space)$($indent)versionNumber = '" + $childApp.versionNumber + "'`r`n" + $StringContent += "$space}" + + $i++ + } + + $StringContent += ')' + + return $StringContent +} + +function Get-M365DSCIntuneMobileMocOSLobAppAdditionalProperties +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = 'true')] + [System.Collections.Hashtable] + $Properties + ) + + $additionalProperties = @( + 'IgnoreVersionDetection' + 'ChildApps' + ) + + $results = @{'@odata.type' = '#microsoft.graph.officeSuiteApp' } + $cloneProperties = $Properties.clone() + foreach ($property in $cloneProperties.Keys) + { + if ($property -in $additionalProperties) + { + $propertyName = $property[0].ToString().ToLower() + $property.Substring(1, $property.Length - 1) + if ($properties.$property -and $properties.$property.getType().FullName -like '*CIMInstance*') + { + if ($properties.$property.getType().FullName -like '*[[\]]') + { + $array = @() + foreach ($item in $properties.$property) + { + $array += Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $item + + } + $propertyValue = $array + } + else + { + $propertyValue = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $properties.$property + } + + } + else + { + $propertyValue = $properties.$property + } + + $results.Add($propertyName, $propertyValue) + } + } + + if ($results.Count -eq 1) + { + return $null + } + return $results +} + +function Get-M365DSCIntuneAppLargeIconAsString #Get and Export +{ + [CmdletBinding()] + [OutputType([System.String])] + param( + [Parameter(Mandatory = $true)] + [System.Object] + $LargeIcon + ) + + $space = ' ' + $indent = ' ' + + if ($null -ne $LargeIcon.Value) + { + $StringContent += "`r`n" + $StringContent += "$space" + + $base64String = [System.Convert]::ToBase64String($LargeIcon.Value) # This exports the base64 string (blob) of the byte array, same as we see in Graph API response + + $StringContent += "MSFT_DeviceManagementMimeContent { `r`n" + $StringContent += "$($space)$($indent)type = '" + $LargeIcon.Type + "'`r`n" + $StringContent += "$($space)$($indent)value = '" + $base64String + "'`r`n" + $StringContent += "$space}" + } + + return $StringContent + } + +function ConvertTo-M365DSCIntuneAppLargeIcon #set +{ + [OutputType([System.Object])] + param( + [Parameter(Mandatory = $true)] + [System.Object] + $LargeIcon + ) + + $result = @{ + type = $LargeIcon.Type + value = $iconValue + } + + return $result +} + +#endregion Helper functions + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof new file mode 100644 index 0000000000..fe8aabccae --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof @@ -0,0 +1,14 @@ +[ClassVersion("1.0.0.0"), FriendlyName("ResourceName")] +class MSFT_ResourceName : OMI_BaseResource +{ + [Key, Description("")] String PrimaryKey; + [Write, Description("")] String OtherProperties; + + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Absent","Present"}, Values{"Absent","Present"}] string Ensure; + [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/readme.md new file mode 100644 index 0000000000..32e0e7fb27 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/readme.md @@ -0,0 +1,6 @@ + +# ResourceName + +## Description + +##TODO - Provide a short description of what the resource is set to configure. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/settings.json new file mode 100644 index 0000000000..edf14b05e4 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName": "ResourceName", + "description": "Description of what the resource is about.", + "roles": { + "read": [ + "Role" + ], + "update": [ + "Role" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [ + { + "name": "Permission for Monitoring and Export" + } + ], + "update": [ + { + "name": "Permission for deploying" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 @@ -0,0 +1,26 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/2-Update.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/2-Update.ps1 @@ -0,0 +1,26 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/3-Remove.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/3-Remove.ps1 @@ -0,0 +1,26 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 new file mode 100644 index 0000000000..780e0f343d --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 @@ -0,0 +1,178 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -GenericStubModule $GenericStubPath + +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + ##TODO - Mock any Remove/Set/New cmdlets + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + Context -Name "The instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return $null + Mock -CommandName Get-Cmdlet -MockWith { + return $null + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should create a new instance from the Set method' { + ##TODO - Replace the New-Cmdlet by the appropriate one + Set-TargetResource @testParams + Should -Invoke -CommandName New-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Absent' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should remove the instance from the Set method' { + Set-TargetResource @testParams + ##TODO - Replace the Remove-Cmdlet by the appropriate one + Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return the desired values + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return a drift + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + ##TODO - Replace the Update-Cmdlet by the appropriate one + Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope From c2383dcaaefed4fc4d5e7396a97c59d2d7719476 Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Wed, 9 Oct 2024 22:01:18 -0700 Subject: [PATCH 188/252] updated parameter types --- ...IntuneMobileAppsWindowsOfficeSuiteApp.psm1 | 114 ++++++++++-------- 1 file changed, 63 insertions(+), 51 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 index f616acf07a..4cf91d3fc9 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 @@ -61,10 +61,11 @@ function Get-TargetResource [Parameter()] [System.String[]] + [ValidateSet('O365ProPlusRetail', 'O365BusinessRetail', 'VisioProRetail', 'ProjectProRetail')] $ProductIds, [Parameter()] - [PSCustomObject] + [Microsoft.Management.Infrastructure.CimInstance] $ExcludedApps, [Parameter()] @@ -73,18 +74,18 @@ function Get-TargetResource [Parameter()] [System.String] - [ValidateSet('current', 'monthlyEnterprise', 'semiAnnual')] - $UpdateChannel = 'monthlyEnterprise', + [ValidateSet('None', 'Current', 'Deferred', 'FirstReleaseCurrent', 'FirstReleaseDeferred', 'MonthlyEnterprise')] + $UpdateChannel, [Parameter()] [System.String] - [ValidateSet('officeOpenDocumentFormat', 'binaryFormat')] + [ValidateSet('NotConfigured', 'OfficeOpenXMLFormat', 'OfficeOpenDocumentFormat', 'UnknownFutureValue')] $OfficeSuiteAppDefaultFileFormat, [Parameter()] [System.String] - [ValidateSet('x86', 'x64')] - $OfficePlatformArchitecture = 'x64', + [ValidateSet('None', 'X86', 'X64', 'Arm', 'Neutral', 'Arm64')] + $OfficePlatformArchitecture, [Parameter()] [System.String[]] @@ -92,20 +93,20 @@ function Get-TargetResource [Parameter()] [System.String] - [ValidateSet('none', 'full')] - $InstallProgressDisplayLevel = 'none', + [ValidateSet('None', 'Full')] + $InstallProgressDisplayLevel, [Parameter()] [System.Boolean] - $ShouldUninstallOlderVersionsOfOffice = $true, + $ShouldUninstallOlderVersionsOfOffice, [Parameter()] [System.String] - $TargetVersion = "", -> + $TargetVersion, + [Parameter()] [System.String] - $UpdateVersion = "", + $UpdateVersion, [Parameter()] [System.Byte[]] @@ -202,21 +203,30 @@ function Get-TargetResource $results = @{ Id = $instance.Id - Description = $instance.Description - Developer = $instance.Developer DisplayName = $instance.DisplayName - InformationUrl = $instance.InformationUrl + Description = $instance.Description + Publisher = $instance.Publisher IsFeatured = $instance.IsFeatured - Notes = $instance.Notes - Owner = $instance.Owner PrivacyInformationUrl = $instance.PrivacyInformationUrl - Publisher = $instance.Publisher + InformationUrl = $instance.InformationUrl + Owner = $instance.Owner + Developer = $instance.Developer + Notes = $instance.Notes PublishingState = $instance.PublishingState.ToString() RoleScopeTagIds = $instance.RoleScopeTagIds - BundleId = $instance.BundleId - BuildNumber = $instance.BuildNumber - VersionNumber = $instance.VersionNumber - IgnoreVersionDetection = $instance.AdditionalProperties.ignoreVersionDetection + ProductIds = $instance.ProductIds + ExcludedApps = $instance.ExcludedApps + UseSharedComputerActivation = $instance.UseSharedComputerActivation + UpdateChannel = $instance.UpdateChannel + OfficeSuiteAppDefaultFileFormat = $instance.OfficeSuiteAppDefaultFileFormat + OfficePlatformArchitecture = $instance.OfficePlatformArchitecture + LocalesToInstall = $instance.LocalesToInstall + InstallProgressDisplayLevel = $instance.InstallProgressDisplayLevel + ShouldUninstallOlderVersionsOfOffice = $instance.ShouldUninstallOlderVersionsOfOffice + TargetVersion = $instance.TargetVersion + UpdateVersion = $instance.UpdateVersion + OfficeConfigurationXml = $instance.OfficeConfigurationXml + AutoAcceptEula = $instance.AdditionalProperties.AutoAcceptEula Ensure = 'Present' Credential = $Credential @@ -350,10 +360,11 @@ function Set-TargetResource [Parameter()] [System.String[]] + [ValidateSet('O365ProPlusRetail', 'O365BusinessRetail', 'VisioProRetail', 'ProjectProRetail')] $ProductIds, [Parameter()] - [PSCustomObject] + [Microsoft.Management.Infrastructure.CimInstance] $ExcludedApps, [Parameter()] @@ -362,18 +373,18 @@ function Set-TargetResource [Parameter()] [System.String] - [ValidateSet('current', 'monthlyEnterprise', 'semiAnnual')] - $UpdateChannel = 'monthlyEnterprise', + [ValidateSet('None', 'Current', 'Deferred', 'FirstReleaseCurrent', 'FirstReleaseDeferred', 'MonthlyEnterprise')] + $UpdateChannel, [Parameter()] [System.String] - [ValidateSet('officeOpenDocumentFormat', 'binaryFormat')] + [ValidateSet('NotConfigured', 'OfficeOpenXMLFormat', 'OfficeOpenDocumentFormat', 'UnknownFutureValue')] $OfficeSuiteAppDefaultFileFormat, [Parameter()] [System.String] - [ValidateSet('x86', 'x64')] - $OfficePlatformArchitecture = 'x64', + [ValidateSet('None', 'X86', 'X64', 'Arm', 'Neutral', 'Arm64')] + $OfficePlatformArchitecture, [Parameter()] [System.String[]] @@ -381,20 +392,20 @@ function Set-TargetResource [Parameter()] [System.String] - [ValidateSet('none', 'full')] - $InstallProgressDisplayLevel = 'none', + [ValidateSet('None', 'Full')] + $InstallProgressDisplayLevel, [Parameter()] [System.Boolean] - $ShouldUninstallOlderVersionsOfOffice = $true, + $ShouldUninstallOlderVersionsOfOffice, [Parameter()] [System.String] - $TargetVersion = "", -> + $TargetVersion, + [Parameter()] [System.String] - $UpdateVersion = "", + $UpdateVersion, [Parameter()] [System.Byte[]] @@ -475,7 +486,7 @@ function Set-TargetResource # CREATE if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { - Write-Host "Create MacOS app: $DisplayName" + Write-Host "Create office suite app: $DisplayName" $CreateParameters = ([Hashtable]$PSBoundParameters).clone() $CreateParameters = Rename-M365DSCCimInstanceParameter -Properties $CreateParameters @@ -534,7 +545,7 @@ function Set-TargetResource # UPDATE elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { - Write-Host "Update MacOS app: $DisplayName" + Write-Host "Update office suite app: $DisplayName" $PSBoundParameters.Remove('Assignments') | Out-Null $UpdateParameters = ([Hashtable]$PSBoundParameters).clone() @@ -578,7 +589,7 @@ function Set-TargetResource } Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id @UpdateParameters - Write-Host "Updated MacOS App: $DisplayName." + Write-Host "Updated office suite App: $DisplayName." #Assignments $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments @@ -589,7 +600,7 @@ function Set-TargetResource # REMOVE elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { - Write-Host "Remove MacOS app: $DisplayName" + Write-Host "Remove office suite app: $DisplayName" Remove-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id -Confirm:$false } } @@ -657,10 +668,11 @@ function Test-TargetResource [Parameter()] [System.String[]] + [ValidateSet('O365ProPlusRetail', 'O365BusinessRetail', 'VisioProRetail', 'ProjectProRetail')] $ProductIds, [Parameter()] - [PSCustomObject] + [Microsoft.Management.Infrastructure.CimInstance] $ExcludedApps, [Parameter()] @@ -669,18 +681,18 @@ function Test-TargetResource [Parameter()] [System.String] - [ValidateSet('current', 'monthlyEnterprise', 'semiAnnual')] - $UpdateChannel = 'monthlyEnterprise', + [ValidateSet('None', 'Current', 'Deferred', 'FirstReleaseCurrent', 'FirstReleaseDeferred', 'MonthlyEnterprise')] + $UpdateChannel, [Parameter()] [System.String] - [ValidateSet('officeOpenDocumentFormat', 'binaryFormat')] + [ValidateSet('NotConfigured', 'OfficeOpenXMLFormat', 'OfficeOpenDocumentFormat', 'UnknownFutureValue')] $OfficeSuiteAppDefaultFileFormat, [Parameter()] [System.String] - [ValidateSet('x86', 'x64')] - $OfficePlatformArchitecture = 'x64', + [ValidateSet('None', 'X86', 'X64', 'Arm', 'Neutral', 'Arm64')] + $OfficePlatformArchitecture, [Parameter()] [System.String[]] @@ -688,20 +700,20 @@ function Test-TargetResource [Parameter()] [System.String] - [ValidateSet('none', 'full')] - $InstallProgressDisplayLevel = 'none', + [ValidateSet('None', 'Full')] + $InstallProgressDisplayLevel, [Parameter()] [System.Boolean] - $ShouldUninstallOlderVersionsOfOffice = $true, + $ShouldUninstallOlderVersionsOfOffice, [Parameter()] [System.String] - $TargetVersion = "", -> + $TargetVersion, + [Parameter()] [System.String] - $UpdateVersion = "", + $UpdateVersion, [Parameter()] [System.Byte[]] @@ -767,7 +779,7 @@ function Test-TargetResource Add-M365DSCTelemetryEvent -Data $data #endregion - Write-Verbose -Message "Testing configuration of Intune Mobile MacOS App: {$DisplayName}" + Write-Verbose -Message "Testing configuration of Intune Mobile office suite App: {$DisplayName}" $CurrentValues = Get-TargetResource @PSBoundParameters if (-not (Test-M365DSCAuthenticationParameter -BoundParameters $CurrentValues)) From b6694e52013eb812a112b719aae201acf4876cf5 Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Wed, 9 Oct 2024 22:05:45 -0700 Subject: [PATCH 189/252] finish get-target --- .../MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 index 4cf91d3fc9..2d51a81d90 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 @@ -215,7 +215,6 @@ function Get-TargetResource PublishingState = $instance.PublishingState.ToString() RoleScopeTagIds = $instance.RoleScopeTagIds ProductIds = $instance.ProductIds - ExcludedApps = $instance.ExcludedApps UseSharedComputerActivation = $instance.UseSharedComputerActivation UpdateChannel = $instance.UpdateChannel OfficeSuiteAppDefaultFileFormat = $instance.OfficeSuiteAppDefaultFileFormat @@ -249,13 +248,13 @@ function Get-TargetResource $results.Add('Categories', "") } - #childApps - if($null -ne $instance.AdditionalProperties.childApps) + #ExcludedApps + if($null -ne $instance.AdditionalProperties.excludedApps) { - $results.Add('ChildApps', $instance.AdditionalProperties.childApps) + $results.Add('ExcludedApps', $instance.AdditionalProperties.excludedApps) } else { - $results.Add('ChildApps', "") + $results.Add('ExcludedApps', "") } #Assignments From 8d127f4e3a2d59ccba21942921c2c372c0a9c65b Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Wed, 9 Oct 2024 22:37:11 -0700 Subject: [PATCH 190/252] handle excludedapps --- ...IntuneMobileAppsWindowsOfficeSuiteApp.psm1 | 81 +++++++++---------- 1 file changed, 37 insertions(+), 44 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 index 2d51a81d90..ce01f533da 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 @@ -65,7 +65,7 @@ function Get-TargetResource $ProductIds, [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance] + [PSCustomObject] $ExcludedApps, [Parameter()] @@ -249,12 +249,12 @@ function Get-TargetResource } #ExcludedApps - if($null -ne $instance.AdditionalProperties.excludedApps) + if ($null -ne $instance.AdditionalProperties -and $null -ne $instance.AdditionalProperties.excludedApps) { - $results.Add('ExcludedApps', $instance.AdditionalProperties.excludedApps) + $results['ExcludedApps'] = [PSCustomObject]$instance.AdditionalProperties.excludedApps } else { - $results.Add('ExcludedApps', "") + $results.Add('ExcludedApps', $null) } #Assignments @@ -363,7 +363,7 @@ function Set-TargetResource $ProductIds, [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance] + [PSCustomObject] $ExcludedApps, [Parameter()] @@ -504,8 +504,7 @@ function Set-TargetResource $CreateParameters.remove('Ensure') | Out-Null $CreateParameters.remove('Categories') | Out-Null $CreateParameters.remove('Assignments') | Out-Null - $CreateParameters.remove('childApps') | Out-Null - $CreateParameters.remove('IgnoreVersionDetection') | Out-Null + $CreateParameters.remove('excludedApps') | Out-Null $CreateParameters.Remove('Verbose') | Out-Null $CreateParameters.Remove('PublishingState') | Out-Null #Not allowed to update as it's a computed property $CreateParameters.Remove('LargeIcon') | Out-Null @@ -671,7 +670,7 @@ function Test-TargetResource $ProductIds, [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance] + [PSCustomObject] $ExcludedApps, [Parameter()] @@ -948,13 +947,13 @@ function Export-TargetResource $Results.Remove('Categories') | Out-Null } - #ChildApps - if($null -ne $Results.childApps) + #ExcludedApps + if($null -ne $Results.excludedApps) { - $Results.childApps = Get-M365DSCIntuneAppChildAppsAsString -ChildApps $Results.childApps + $Results.excludedApps = Get-M365DSCIntuneAppExcludedAppsAsString -ExcludedApps $Results.excludedApps } else { - $Results.Remove('childApps') | Out-Null + $Results.Remove('excludedApps') | Out-Null } #Assignments @@ -1004,16 +1003,16 @@ function Export-TargetResource $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Categories' -IsCIMArray:$isCIMArray } - #ChildApps - if ($null -ne $Results.childApps) + #ExcludedApps + if ($null -ne $Results.excludedApps) { $isCIMArray = $false - if ($Results.childApps.getType().Fullname -like '*[[\]]') + if ($Results.excludedApps.getType().Fullname -like '*[[\]]') { $isCIMArray = $true } - $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'ChildApps' -IsCIMArray:$isCIMArray + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'ExcludedApps' -IsCIMArray:$isCIMArray } #Assignments @@ -1097,39 +1096,33 @@ function Get-M365DSCIntuneAppCategoriesAsString return $StringContent } -function Get-M365DSCIntuneAppChildAppsAsString +function Get-M365DSCIntuneAppExcludedAppsAsString { [CmdletBinding()] [OutputType([System.String])] param( [Parameter(Mandatory = $true)] - [System.Object[]] - $ChildApps + [System.Object] + $ExcludedApps ) - $StringContent = '@(' - $space = ' ' - $indent = ' ' - - $i = 1 - foreach ($childApp in $ChildApps) - { - if ($ChildApps.Count -gt 1) - { - $StringContent += "`r`n" - $StringContent += "$space" - } - - $StringContent += "MSFT_DeviceManagementMobileAppChildApp { `r`n" - $StringContent += "$($space)$($indent)bundleId = '" + $childApp.bundleId + "'`r`n" - $StringContent += "$($space)$($indent)buildNumber = '" + $childApp.buildNumber + "'`r`n" - $StringContent += "$($space)$($indent)versionNumber = '" + $childApp.versionNumber + "'`r`n" - $StringContent += "$space}" - - $i++ - } - - $StringContent += ')' + $StringContent = "@{" + $StringContent += "`n Access = '$($ExcludedApps.Access)'" + $StringContent += "`n Bing = '$($ExcludedApps.Bing)'" + $StringContent += "`n Excel = '$($ExcludedApps.Excel)'" + $StringContent += "`n Groove = '$($ExcludedApps.Groove)'" + $StringContent += "`n InfoPath = '$($ExcludedApps.InfoPath)'" + $StringContent += "`n Lync = '$($ExcludedApps.Lync)'" + $StringContent += "`n OneDrive = '$($ExcludedApps.OneDrive)'" + $StringContent += "`n OneNote = '$($ExcludedApps.OneNote)'" + $StringContent += "`n Outlook = '$($ExcludedApps.Outlook)'" + $StringContent += "`n PowerPoint = '$($ExcludedApps.PowerPoint)'" + $StringContent += "`n Publisher = '$($ExcludedApps.Publisher)'" + $StringContent += "`n SharePointDesigner = '$($ExcludedApps.SharePointDesigner)'" + $StringContent += "`n Teams = '$($ExcludedApps.Teams)'" + $StringContent += "`n Visio = '$($ExcludedApps.Visio)'" + $StringContent += "`n Word = '$($ExcludedApps.Word)'" + $StringContent += "`n}" return $StringContent } @@ -1146,8 +1139,8 @@ function Get-M365DSCIntuneMobileMocOSLobAppAdditionalProperties ) $additionalProperties = @( - 'IgnoreVersionDetection' - 'ChildApps' + 'AutoAcceptEula' + 'ExcludedApps' ) $results = @{'@odata.type' = '#microsoft.graph.officeSuiteApp' } From aa00aff1bb521f0496c1af92ce757fa9d2d44cfa Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Thu, 10 Oct 2024 14:07:54 -0700 Subject: [PATCH 191/252] add mof settings and readme files --- ...MobileAppsWindowsOfficeSuiteApp.schema.mof | 101 ++++++++++++++++-- .../readme.md | 4 +- .../settings.json | 28 ++--- 3 files changed, 111 insertions(+), 22 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof index fe8aabccae..a587398b50 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof @@ -1,14 +1,103 @@ -[ClassVersion("1.0.0.0"), FriendlyName("ResourceName")] -class MSFT_ResourceName : OMI_BaseResource +[ClassVersion("1.0.0"), FriendlyName("IntuneMobileAppsWindowsOfficeSuiteApp")] +class MSFT_IntuneMobileAppsWindowsOfficeSuiteApp : OMI_BaseResource { - [Key, Description("")] String PrimaryKey; - [Write, Description("")] String OtherProperties; + [Key, Description("The admin provided or imported title of the app. Inherited from mobileApp.")] String DisplayName; + [Write, Description("The unique identifier for an entity. Read-only. Inherited from mobileApp object.")] String Id; - [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Absent","Present"}, Values{"Absent","Present"}] string Ensure; - [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("The description of the app. Inherited from mobileApp.")] String Description; + [Write, Description("The publisher of the app. Inherited from mobileApp.")] String Publisher; + [Write, Description("The value indicating whether the app is marked as featured by the admin. Inherited from mobileApp.")] Boolean IsFeatured; + [Write, Description("The privacy statement Url. Inherited from mobileApp.")] String PrivacyInformationUrl; + [Write, Description("The InformationUrl of the app. Inherited from mobileApp.")] String InformationUrl; + [Write, Description("The owner of the app. Inherited from mobileApp.")] String Owner; + [Write, Description("The dewveloper of the app. Inherited from mobileApp.")] String Developer; + [Write, Description("Notes for the app. Inherited from mobileApp.")] String Notes; + [Write, Description("The publishing state for the app. The app cannot be assigned unless the app is published. Inherited from mobileApp."), ValueMap{"notPublished", "processing","published"}, Values{"notPublished", "processing", "published"}] String PublishingState; + [Write, Description("List of Scope Tag IDs for mobile app.")] String RoleScopeTagIds[]; + [Write, Description("Specifies if the EULA is accepted automatically on the end user's device.")] Boolean AutoAcceptEula; + [Write, Description("The Product IDs that represent the Office 365 Suite SKU, such as 'O365ProPlusRetail' or 'VisioProRetail'.")] String ProductIds[]; + [Write, Description("Indicates whether shared computer activation is used for Office installations.")] Boolean UseSharedComputerActivation; + [Write, Description("Specifies the update channel for the Office 365 app suite, such as 'Current' or 'Deferred'.")] String UpdateChannel; + [Write, Description("Specifies the default file format type for Office apps, such as 'OfficeOpenXMLFormat' or 'OfficeOpenDocumentFormat'.")] String OfficeSuiteAppDefaultFileFormat; + [Write, Description("The architecture of the Office installation (e.g., 'X86', 'X64', or 'Arm64').")] String OfficePlatformArchitecture; + [Write, Description("Specifies the locales to be installed when the Office 365 apps are deployed. Uses the standard RFC 5646 format (e.g., 'en-US', 'fr-FR').")] String LocalesToInstall[]; + [Write, Description("Specifies the display level of the installation progress for Office apps. Use 'Full' to display the installation UI, or 'None' for a silent installation.")] String InstallProgressDisplayLevel; + [Write, Description("Indicates whether older versions of Office should be uninstalled when deploying the Office 365 app suite.")] Boolean ShouldUninstallOlderVersionsOfOffice; + [Write, Description("The specific target version of the Office 365 app suite to be deployed.")] String TargetVersion; + [Write, Description("The update version in which the target version is available for the Office 365 app suite.")] String UpdateVersion; + [Write, Description("A base64-encoded XML configuration file that specifies Office ProPlus installation settings. Takes precedence over all other properties. When present, this XML file will be used to create the app.")] String OfficeConfigurationXml; + [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppCategory")] String Categories[]; + [Write, Description("The list of assignments for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppAssignment")] String Assignments[]; + [Write, Description("The property that represents the apps excluded from the selected Office 365 Product ID."), EmbeddedInstance("MSFT_DeviceManagementMobileAppExcludedApp")] String ExcludedApps; + + [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] String Ensure; + [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] String Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Secret of the Azure Active Directory tenant used for authentication."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; [Write, Description("Access token used for authentication.")] String AccessTokens[]; }; + +class MSFT_DeviceManagementMimeContent +{ + [Write, Description("Indicates the type of content mime.")] String type; + [Write, Description("The byte array that contains the actual content.")] String value[]; +}; + +class MSFT_DeviceManagementMobileAppCategory +{ + [Key, Description("The name of the app category.")] String displayName; + [Write, Description("The unique identifier for an entity. Read-only.")] String id; +}; + +class MSFT_DeviceManagementMobileAppChildApp +{ + [Write, Description("The bundleId of the app.")] String bundleId; + [Write, Description("The build number of the app.")] String buildNumber; + [Write, Description("The version number of the app.")] String versionNumber; +}; + +class MSFT_DeviceManagementMobileAppExcludedApp +{ + [Write, Description("Specifies whether to exclude Microsoft Office Access from the installation.")] Boolean Access; + [Write, Description("Specifies whether to exclude Microsoft Search (Bing) as the default from the installation.")] Boolean Bing; + [Write, Description("Specifies whether to exclude Microsoft Office Excel from the installation.")] Boolean Excel; + [Write, Description("Specifies whether to exclude Microsoft Office OneDrive for Business (Groove) from the installation.")] Boolean Groove; + [Write, Description("Specifies whether to exclude Microsoft Office InfoPath from the installation.")] Boolean InfoPath; + [Write, Description("Specifies whether to exclude Microsoft Office Skype for Business (Lync) from the installation.")] Boolean Lync; + [Write, Description("Specifies whether to exclude Microsoft Office OneDrive from the installation.")] Boolean OneDrive; + [Write, Description("Specifies whether to exclude Microsoft Office OneNote from the installation.")] Boolean OneNote; + [Write, Description("Specifies whether to exclude Microsoft Office Outlook from the installation.")] Boolean Outlook; + [Write, Description("Specifies whether to exclude Microsoft Office PowerPoint from the installation.")] Boolean PowerPoint; + [Write, Description("Specifies whether to exclude Microsoft Office Publisher from the installation.")] Boolean Publisher; + [Write, Description("Specifies whether to exclude Microsoft Office SharePoint Designer from the installation.")] Boolean SharePointDesigner; + [Write, Description("Specifies whether to exclude Microsoft Office Teams from the installation.")] Boolean Teams; + [Write, Description("Specifies whether to exclude Microsoft Office Visio from the installation.")] Boolean Visio; + [Write, Description("Specifies whether to exclude Microsoft Office Word from the installation.")] Boolean Word; +}; + +class MSFT_DeviceManagementMobileAppAssignment +{ + [Write, Description("The type of the target assignment."), + ValueMap{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget", "#microsoft.graph.mobileAppAssignment"}, + Values{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget", "#microsoft.graph.mobileAppAssignment"}] + String dataType; + + [Write, Description("The Id of the filter for the target assignment.")] String deviceAndAppManagementAssignmentFilterId; + [Write, Description("The type of filter of the target assignment i.e. Exclude or Include. Possible values are: none, include, exclude."), + ValueMap{"none", "include", "exclude"}, + Values{"none", "include", "exclude"}] + String deviceAndAppManagementAssignmentFilterType; + + [Write, Description("The group Id that is the target of the assignment.")] String groupId; + [Write, Description("The group Display Name that is the target of the assignment.")] String groupDisplayName; + + [Write, Description("Possible values for the install intent chosen by the admin."), + ValueMap{"available", "required", "uninstall", "availableWithoutEnrollment"}, + Values{"available", "required", "uninstall", "availableWithoutEnrollment"}] + String intent; + + [Write, Description("The source of this assignment.")] String source; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/readme.md index 32e0e7fb27..f35ec06360 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/readme.md @@ -1,6 +1,6 @@ -# ResourceName +# IntuneMobileAppsWindowsOfficeSuiteApp ## Description -##TODO - Provide a short description of what the resource is set to configure. +This resource configures an Intune mobile app of OfficeSuiteApp type for Windows devices. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/settings.json index edf14b05e4..a9bd04b5fa 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/settings.json @@ -1,29 +1,29 @@ { - "resourceName": "ResourceName", - "description": "Description of what the resource is about.", - "roles": { - "read": [ - "Role" - ], - "update": [ - "Role" - ] - }, + "resourceName": "IntuneMobileAppsWindowsOfficeSuiteApp", + "description": "This resource configures an Intune mobile app.", "permissions": { "graph": { "delegated": { - "read": [], - "update": [] + "read": [ + { + "name": "DeviceManagementApps.Read.All" + } + ], + "update": [ + { + "name": "DeviceManagementApps.ReadWrite.All" + } + ] }, "application": { "read": [ { - "name": "Permission for Monitoring and Export" + "name": "DeviceManagementApps.Read.All" } ], "update": [ { - "name": "Permission for deploying" + "name": "DeviceManagementApps.ReadWrite.All" } ] } From 063adb301c5ad7fd37affe295d9fd61957edbde4 Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Thu, 10 Oct 2024 16:12:40 -0700 Subject: [PATCH 192/252] add large icon in mof --- .../MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof index a587398b50..ef6cdaf8d0 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof @@ -14,6 +14,7 @@ class MSFT_IntuneMobileAppsWindowsOfficeSuiteApp : OMI_BaseResource [Write, Description("Notes for the app. Inherited from mobileApp.")] String Notes; [Write, Description("The publishing state for the app. The app cannot be assigned unless the app is published. Inherited from mobileApp."), ValueMap{"notPublished", "processing","published"}, Values{"notPublished", "processing", "published"}] String PublishingState; [Write, Description("List of Scope Tag IDs for mobile app.")] String RoleScopeTagIds[]; + [Write, Description("The icon for this app."), EmbeddedInstance("MSFT_DeviceManagementMimeContent")] String LargeIcon; [Write, Description("Specifies if the EULA is accepted automatically on the end user's device.")] Boolean AutoAcceptEula; [Write, Description("The Product IDs that represent the Office 365 Suite SKU, such as 'O365ProPlusRetail' or 'VisioProRetail'.")] String ProductIds[]; [Write, Description("Indicates whether shared computer activation is used for Office installations.")] Boolean UseSharedComputerActivation; From 6a3451a8a99b7a3639e2ada55bfdb1417dd10e37 Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Thu, 10 Oct 2024 21:19:14 -0700 Subject: [PATCH 193/252] working export and compilation of generated file --- ...IntuneMobileAppsWindowsOfficeSuiteApp.psm1 | 92 ++++++++----------- 1 file changed, 36 insertions(+), 56 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 index ce01f533da..4cc90ae467 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 @@ -65,7 +65,7 @@ function Get-TargetResource $ProductIds, [Parameter()] - [PSCustomObject] + [System.Collections.Hashtable] $ExcludedApps, [Parameter()] @@ -248,10 +248,12 @@ function Get-TargetResource $results.Add('Categories', "") } - #ExcludedApps + # ExcludedApps if ($null -ne $instance.AdditionalProperties -and $null -ne $instance.AdditionalProperties.excludedApps) { - $results['ExcludedApps'] = [PSCustomObject]$instance.AdditionalProperties.excludedApps + $excludedAppsHashtable = @{} + $excludedAppsHashtable = [System.Collections.Hashtable]$instance.AdditionalProperties.excludedApps + $results['ExcludedApps'] = $excludedAppsHashtable } else { $results.Add('ExcludedApps', $null) @@ -363,7 +365,7 @@ function Set-TargetResource $ProductIds, [Parameter()] - [PSCustomObject] + [System.Collections.Hashtable] $ExcludedApps, [Parameter()] @@ -490,7 +492,7 @@ function Set-TargetResource $CreateParameters = ([Hashtable]$PSBoundParameters).clone() $CreateParameters = Rename-M365DSCCimInstanceParameter -Properties $CreateParameters - $AdditionalProperties = Get-M365DSCIntuneMobileMocOSLobAppAdditionalProperties -Properties ($CreateParameters) + $AdditionalProperties = Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties -Properties ($CreateParameters) foreach ($key in $AdditionalProperties.keys) { if ($key -ne '@odata.type') @@ -549,7 +551,7 @@ function Set-TargetResource $UpdateParameters = ([Hashtable]$PSBoundParameters).clone() $UpdateParameters = Rename-M365DSCCimInstanceParameter -Properties $UpdateParameters - $AdditionalProperties = Get-M365DSCIntuneMobileMocOSLobAppAdditionalProperties -Properties ($UpdateParameters) + $AdditionalProperties = Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties -Properties ($UpdateParameters) foreach ($key in $AdditionalProperties.keys) { if ($key -ne '@odata.type') @@ -670,7 +672,7 @@ function Test-TargetResource $ProductIds, [Parameter()] - [PSCustomObject] + [System.Collections.Hashtable] $ExcludedApps, [Parameter()] @@ -948,12 +950,12 @@ function Export-TargetResource } #ExcludedApps - if($null -ne $Results.excludedApps) + if ($null -ne $Results.ExcludedApps) { - $Results.excludedApps = Get-M365DSCIntuneAppExcludedAppsAsString -ExcludedApps $Results.excludedApps + $Results.ExcludedApps = Get-M365DSCIntuneAppExcludedAppsAsString -ExcludedApps $Results.ExcludedApps } else { - $Results.Remove('excludedApps') | Out-Null + $Results.Remove('ExcludedApps') | Out-Null } #Assignments @@ -1106,81 +1108,59 @@ function Get-M365DSCIntuneAppExcludedAppsAsString $ExcludedApps ) - $StringContent = "@{" - $StringContent += "`n Access = '$($ExcludedApps.Access)'" - $StringContent += "`n Bing = '$($ExcludedApps.Bing)'" - $StringContent += "`n Excel = '$($ExcludedApps.Excel)'" - $StringContent += "`n Groove = '$($ExcludedApps.Groove)'" - $StringContent += "`n InfoPath = '$($ExcludedApps.InfoPath)'" - $StringContent += "`n Lync = '$($ExcludedApps.Lync)'" - $StringContent += "`n OneDrive = '$($ExcludedApps.OneDrive)'" - $StringContent += "`n OneNote = '$($ExcludedApps.OneNote)'" - $StringContent += "`n Outlook = '$($ExcludedApps.Outlook)'" - $StringContent += "`n PowerPoint = '$($ExcludedApps.PowerPoint)'" - $StringContent += "`n Publisher = '$($ExcludedApps.Publisher)'" - $StringContent += "`n SharePointDesigner = '$($ExcludedApps.SharePointDesigner)'" - $StringContent += "`n Teams = '$($ExcludedApps.Teams)'" - $StringContent += "`n Visio = '$($ExcludedApps.Visio)'" - $StringContent += "`n Word = '$($ExcludedApps.Word)'" + # Create the embedded instance for ExcludedApps + $StringContent = "MSFT_DeviceManagementMobileAppExcludedApp {" + foreach ($key in $ExcludedApps.Keys) { + $value = if ($ExcludedApps[$key]) { '$true' } else { '$false' } + $StringContent += "`n $key = $value;" + } $StringContent += "`n}" return $StringContent } -function Get-M365DSCIntuneMobileMocOSLobAppAdditionalProperties +function Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( - [Parameter(Mandatory = 'true')] + [Parameter(Mandatory = $true)] [System.Collections.Hashtable] $Properties ) - $additionalProperties = @( - 'AutoAcceptEula' - 'ExcludedApps' - ) + # Define the list of additional properties to include in the final payload + $additionalProperties = @('AutoAcceptEula', 'ExcludedApps') + + # Initialize a hashtable to store the additional properties + $results = @{'@odata.type' = '#microsoft.graph.officeSuiteApp'} - $results = @{'@odata.type' = '#microsoft.graph.officeSuiteApp' } + # Clone the original properties to manipulate $cloneProperties = $Properties.clone() + + # Loop through the clone and process each property based on its type foreach ($property in $cloneProperties.Keys) { if ($property -in $additionalProperties) { + # Convert property name to expected format $propertyName = $property[0].ToString().ToLower() + $property.Substring(1, $property.Length - 1) - if ($properties.$property -and $properties.$property.getType().FullName -like '*CIMInstance*') - { - if ($properties.$property.getType().FullName -like '*[[\]]') - { - $array = @() - foreach ($item in $properties.$property) - { - $array += Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $item - - } - $propertyValue = $array - } - else - { - $propertyValue = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $properties.$property - } + $propertyValue = $Properties.$property + # Handle ExcludedApps: Convert to PSCustomObject if it's a Hashtable + if ($propertyName -eq 'excludedApps' -and $propertyValue -is [System.Collections.Hashtable]) + { + $results.Add($propertyName, [PSCustomObject]$propertyValue) } else { - $propertyValue = $properties.$property + # For simple types like Boolean (AutoAcceptEula), add directly + $results.Add($propertyName, $propertyValue) } - - $results.Add($propertyName, $propertyValue) } } - if ($results.Count -eq 1) - { - return $null - } return $results } From eb39bee1de0bc8898115c26a679ccc50e772549b Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Fri, 11 Oct 2024 09:51:25 -0700 Subject: [PATCH 194/252] temp changes not working --- ...IntuneMobileAppsWindowsOfficeSuiteApp.psm1 | 163 ++++++++++++++---- 1 file changed, 127 insertions(+), 36 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 index 4cc90ae467..7f6282e7b5 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 @@ -65,7 +65,7 @@ function Get-TargetResource $ProductIds, [Parameter()] - [System.Collections.Hashtable] + [Microsoft.Management.Infrastructure.CimInstance[]] $ExcludedApps, [Parameter()] @@ -248,14 +248,14 @@ function Get-TargetResource $results.Add('Categories', "") } - # ExcludedApps if ($null -ne $instance.AdditionalProperties -and $null -ne $instance.AdditionalProperties.excludedApps) { - $excludedAppsHashtable = @{} - $excludedAppsHashtable = [System.Collections.Hashtable]$instance.AdditionalProperties.excludedApps - $results['ExcludedApps'] = $excludedAppsHashtable - } - else { + $formattedExcludedApps = @{} + foreach ($key in $instance.AdditionalProperties.excludedApps.Keys) { + $formattedExcludedApps[$key] = if ($instance.AdditionalProperties.excludedApps[$key]) { $true } else { $false } + } + $results['ExcludedApps'] = $formattedExcludedApps + } else { $results.Add('ExcludedApps', $null) } @@ -274,12 +274,10 @@ function Get-TargetResource #LargeIcon # The large is returned only when Get cmdlet is called with Id parameter. The large icon is a base64 encoded string, so we need to convert it to a byte array. $instanceWithLargeIcon = Get-MgBetaDeviceAppManagementMobileApp -MobileAppId $instance.Id - if($null -ne $instanceWithLargeIcon.LargeIcon) - { + if (-not $results.ContainsKey('LargeIcon')) { $results.Add('LargeIcon', $instanceWithLargeIcon.LargeIcon) - } - else { - $results.Add('LargeIcon', "") + } else { + $results['LargeIcon'] = $instanceWithLargeIcon.LargeIcon # Update the existing key } #end region complex types @@ -365,7 +363,7 @@ function Set-TargetResource $ProductIds, [Parameter()] - [System.Collections.Hashtable] + [Microsoft.Management.Infrastructure.CimInstance[]] $ExcludedApps, [Parameter()] @@ -485,14 +483,26 @@ function Set-TargetResource $CreateParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters # CREATE + Write-Host "WE REACHED CREAAATE" + Write-Output "WE REACHED CREAAATE" if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { + Write-Output "INSIDE IF STATEMENT" + Write-Host "INSIDE IF STATEMENT" Write-Host "Create office suite app: $DisplayName" $CreateParameters = ([Hashtable]$PSBoundParameters).clone() $CreateParameters = Rename-M365DSCCimInstanceParameter -Properties $CreateParameters - + Write-Host "Before AdditionalProperties creation: $($CreateParameters | Out-String)" + Write-Output "Before AdditionalProperties creation: $($CreateParameters | Out-String)" $AdditionalProperties = Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties -Properties ($CreateParameters) + Write-Host "AdditionalProperties: $($AdditionalProperties | Out-String)" + Write-Output "AdditionalProperties: $($AdditionalProperties | Out-String)" + # Explicitly enforce Hashtable type for AdditionalProperties + if ($null -ne $AdditionalProperties -and $AdditionalProperties -isnot [System.Collections.Hashtable]) + { + $AdditionalProperties = [System.Collections.Hashtable]$AdditionalProperties + } foreach ($key in $AdditionalProperties.keys) { if ($key -ne '@odata.type') @@ -528,15 +538,21 @@ function Set-TargetResource if($LargeIcon) { [System.Object]$LargeIconValue = ConvertTo-M365DSCIntuneAppLargeIcon -LargeIcon $LargeIcon - $CreateParameters.Add('LargeIcon', $LargeIconValue) + if (-not $CreateParameters.ContainsKey('LargeIcon')) { + $CreateParameters.Add('LargeIcon', $LargeIconValue) + } else { + $CreateParameters['LargeIcon'] = $LargeIconValue + } } - + Write-Output "CreateParameters before API call: $($CreateParameters | Out-String)" $app = New-MgBetaDeviceAppManagementMobileApp @CreateParameters #Assignments $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments if ($app.id) { + Write-Host "Type of AdditionalProperties: $($AdditionalProperties.GetType().FullName)" + Write-Host "Contents of AdditionalProperties: $(ConvertTo-Json $AdditionalProperties)" Update-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $app.id ` -Target $assignmentsHash ` -Repository 'deviceAppManagement/mobileAppAssignments' @@ -546,12 +562,16 @@ function Set-TargetResource elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { Write-Host "Update office suite app: $DisplayName" - + Write-Output "INSIDE ELSE IF STATEMENT" + Write-Host "INSIDE ELSE IF STATEMENT" $PSBoundParameters.Remove('Assignments') | Out-Null $UpdateParameters = ([Hashtable]$PSBoundParameters).clone() $UpdateParameters = Rename-M365DSCCimInstanceParameter -Properties $UpdateParameters - + Write-Host "Before AdditionalProperties creation: $($CreateParameters | Out-String)" + Write-Output "Before AdditionalProperties creation: $($CreateParameters | Out-String)" $AdditionalProperties = Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties -Properties ($UpdateParameters) + Write-Host "AdditionalProperties after it's populated is: $($AdditionalProperties | Out-String)" + Write-Output "AdditionalProperties after it's populated is: $($AdditionalProperties | Out-String)" foreach ($key in $AdditionalProperties.keys) { if ($key -ne '@odata.type') @@ -584,8 +604,12 @@ function Set-TargetResource #LargeIcon if($LargeIcon) { - [System.Object]$LargeIconValue = ConvertTo-M365DSCIntuneAppLargeIcon -LargeIcon $LargeIcon - $UpdateParameters.Add('LargeIcon', $LargeIconValue) + [System.Object]$LargeIconValue = ConvertTo-M365DSCIntuneAppLargeIcon -LargeIcon $LargeIcon + if (-not $CreateParameters.ContainsKey('LargeIcon')) { + $UpdateParameters.Add('LargeIcon', $LargeIconValue) + } else { + $UpdateParameters['LargeIcon'] = $LargeIconValue + } } Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id @UpdateParameters @@ -601,6 +625,8 @@ function Set-TargetResource elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { Write-Host "Remove office suite app: $DisplayName" + Write-Output "INSIDE SECOND ELSE IF STATEMENT" + Write-Host "INSIDE SECOND ELSE IF STATEMENT" Remove-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id -Confirm:$false } } @@ -672,7 +698,7 @@ function Test-TargetResource $ProductIds, [Parameter()] - [System.Collections.Hashtable] + [Microsoft.Management.Infrastructure.CimInstance[]] $ExcludedApps, [Parameter()] @@ -949,9 +975,13 @@ function Export-TargetResource $Results.Remove('Categories') | Out-Null } - #ExcludedApps + # ExcludedApps if ($null -ne $Results.ExcludedApps) { + # Convert to a Hashtable if still an array + if ($Results.ExcludedApps -is [System.Object[]]) { + $Results.ExcludedApps = Convert-ObjectArrayToHashtable -InputArray $Results.ExcludedApps + } $Results.ExcludedApps = Get-M365DSCIntuneAppExcludedAppsAsString -ExcludedApps $Results.ExcludedApps } else { @@ -1062,6 +1092,21 @@ function Export-TargetResource #region Helper functions +function Convert-ObjectArrayToHashtable { + param ( + [Parameter(Mandatory = $true)] + [System.Object[]] + $InputArray + ) + $outputHashTable = @{} + foreach ($element in $InputArray) { + if ($element -is [System.Collections.Hashtable]) { + $outputHashTable += $element + } + } + return $outputHashTable +} + function Get-M365DSCIntuneAppCategoriesAsString { [CmdletBinding()] @@ -1119,8 +1164,7 @@ function Get-M365DSCIntuneAppExcludedAppsAsString return $StringContent } -function Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties -{ +function Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param @@ -1130,8 +1174,14 @@ function Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties $Properties ) + Write-Host "WERE INSIDE THE HELPER FUNCTION" + Write-Output "WERE INSIDE THE HELPER FUNCTION" + # Define the list of additional properties to include in the final payload - $additionalProperties = @('AutoAcceptEula', 'ExcludedApps') + $additionalProperties = @( + 'AutoAcceptEula' + 'ExcludedApps' + ) # Initialize a hashtable to store the additional properties $results = @{'@odata.type' = '#microsoft.graph.officeSuiteApp'} @@ -1140,30 +1190,71 @@ function Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties $cloneProperties = $Properties.clone() # Loop through the clone and process each property based on its type - foreach ($property in $cloneProperties.Keys) - { - if ($property -in $additionalProperties) - { + foreach ($property in $cloneProperties.Keys) { + if ($property -in $additionalProperties) { # Convert property name to expected format $propertyName = $property[0].ToString().ToLower() + $property.Substring(1, $property.Length - 1) $propertyValue = $Properties.$property - # Handle ExcludedApps: Convert to PSCustomObject if it's a Hashtable - if ($propertyName -eq 'excludedApps' -and $propertyValue -is [System.Collections.Hashtable]) - { - $results.Add($propertyName, [PSCustomObject]$propertyValue) + # Handle ExcludedApps: Build a single PSCustomObject with key-value pairs + if ($propertyName -eq 'excludedApps') { + $formattedExcludedApps = @{} + + # Convert each key in ExcludedApps to a key-value pair in a hashtable + foreach ($key in $propertyValue.Keys) { + # Ensure the value is correctly formatted as boolean $true or $false + $formattedExcludedApps[$key] = if ($propertyValue[$key]) { $true } else { $false } + } + + # Convert to PSCustomObject to match the expected format + $results.Add($propertyName, [PSCustomObject]$formattedExcludedApps) } - else - { + else { # For simple types like Boolean (AutoAcceptEula), add directly $results.Add($propertyName, $propertyValue) } } } - + Write-Host "Formatted ExcludedApps: $(ConvertTo-Json $results['excludedApps'])" + Write-Output "Formatted ExcludedApps: $(ConvertTo-Json $results['excludedApps'])" + Write-Host "Formatted AdditionalProperties: $(ConvertTo-Json $results)" + Write-Output "Formatted AdditionalProperties Type: $($results.GetType().FullName)" return $results } +# function Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties { +# [CmdletBinding()] +# [OutputType([System.Collections.Hashtable])] +# param +# ( +# [Parameter(Mandatory = $true)] +# [System.Collections.Hashtable] +# $Properties +# ) + +# # Initialize a hashtable to store only the relevant additional properties +# $results = @{} + +# # Add `excludedApps` if present +# if ($Properties.ContainsKey('ExcludedApps')) { +# $results.Add('excludedApps', $Properties['ExcludedApps']) +# } + +# # Add `autoAcceptEula` if present +# if ($Properties.ContainsKey('AutoAcceptEula')) { +# $results.Add('autoAcceptEula', $Properties['AutoAcceptEula']) +# } + +# # Debug output to ensure correct structure +# Write-Output "Formatted AdditionalProperties Type: $($results.GetType().FullName)" +# Write-Host "Formatted AdditionalProperties: $(ConvertTo-Json $results)" +# Write-Host "Formatted ExcludedApps: $(ConvertTo-Json $results['excludedApps'])" +# Write-Output "Formatted ExcludedApps: $(ConvertTo-Json $results['excludedApps'])" +# return $results +# } + + + function Get-M365DSCIntuneAppLargeIconAsString #Get and Export { [CmdletBinding()] From d106f44335c618817496fafdc9b913a4ba2e3fa7 Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Sat, 12 Oct 2024 00:28:11 -0700 Subject: [PATCH 195/252] trying to fix excluded apps --- ...IntuneMobileAppsWindowsOfficeSuiteApp.psm1 | 144 ++++++++++-------- ...MobileAppsWindowsOfficeSuiteApp.schema.mof | 7 - 2 files changed, 78 insertions(+), 73 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 index 7f6282e7b5..9b63396a4b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 @@ -248,14 +248,29 @@ function Get-TargetResource $results.Add('Categories', "") } + # ExcludedApps if ($null -ne $instance.AdditionalProperties -and $null -ne $instance.AdditionalProperties.excludedApps) { - $formattedExcludedApps = @{} - foreach ($key in $instance.AdditionalProperties.excludedApps.Keys) { - $formattedExcludedApps[$key] = if ($instance.AdditionalProperties.excludedApps[$key]) { $true } else { $false } + # Convert to Hashtable if it is an array + if ($instance.AdditionalProperties.excludedApps -is [System.Object[]]) { + $formattedExcludedApps = @{} + foreach ($app in $instance.AdditionalProperties.excludedApps) { + foreach ($key in $app.Keys) { + $formattedExcludedApps[$key] = $app[$key] + } + } } - $results['ExcludedApps'] = $formattedExcludedApps - } else { + else { + $formattedExcludedApps = $instance.AdditionalProperties.excludedApps + } + + # Ensure ExcludedApps is returned as a Hashtable + $results['ExcludedApps'] = @{} + foreach ($key in $formattedExcludedApps.Keys) { + $results['ExcludedApps'].Add($key, $formattedExcludedApps[$key]) + } + } + else { $results.Add('ExcludedApps', $null) } @@ -483,26 +498,15 @@ function Set-TargetResource $CreateParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters # CREATE - Write-Host "WE REACHED CREAAATE" - Write-Output "WE REACHED CREAAATE" if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { - Write-Output "INSIDE IF STATEMENT" - Write-Host "INSIDE IF STATEMENT" Write-Host "Create office suite app: $DisplayName" $CreateParameters = ([Hashtable]$PSBoundParameters).clone() $CreateParameters = Rename-M365DSCCimInstanceParameter -Properties $CreateParameters - Write-Host "Before AdditionalProperties creation: $($CreateParameters | Out-String)" Write-Output "Before AdditionalProperties creation: $($CreateParameters | Out-String)" $AdditionalProperties = Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties -Properties ($CreateParameters) - Write-Host "AdditionalProperties: $($AdditionalProperties | Out-String)" Write-Output "AdditionalProperties: $($AdditionalProperties | Out-String)" - # Explicitly enforce Hashtable type for AdditionalProperties - if ($null -ne $AdditionalProperties -and $AdditionalProperties -isnot [System.Collections.Hashtable]) - { - $AdditionalProperties = [System.Collections.Hashtable]$AdditionalProperties - } foreach ($key in $AdditionalProperties.keys) { if ($key -ne '@odata.type') @@ -551,8 +555,7 @@ function Set-TargetResource $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments if ($app.id) { - Write-Host "Type of AdditionalProperties: $($AdditionalProperties.GetType().FullName)" - Write-Host "Contents of AdditionalProperties: $(ConvertTo-Json $AdditionalProperties)" + Write-Output "UpdateParameters before API call: $($UpdateParameters | Out-String)" Update-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $app.id ` -Target $assignmentsHash ` -Repository 'deviceAppManagement/mobileAppAssignments' @@ -562,16 +565,12 @@ function Set-TargetResource elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { Write-Host "Update office suite app: $DisplayName" - Write-Output "INSIDE ELSE IF STATEMENT" - Write-Host "INSIDE ELSE IF STATEMENT" + $PSBoundParameters.Remove('Assignments') | Out-Null $UpdateParameters = ([Hashtable]$PSBoundParameters).clone() $UpdateParameters = Rename-M365DSCCimInstanceParameter -Properties $UpdateParameters - Write-Host "Before AdditionalProperties creation: $($CreateParameters | Out-String)" - Write-Output "Before AdditionalProperties creation: $($CreateParameters | Out-String)" + $AdditionalProperties = Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties -Properties ($UpdateParameters) - Write-Host "AdditionalProperties after it's populated is: $($AdditionalProperties | Out-String)" - Write-Output "AdditionalProperties after it's populated is: $($AdditionalProperties | Out-String)" foreach ($key in $AdditionalProperties.keys) { if ($key -ne '@odata.type') @@ -625,8 +624,6 @@ function Set-TargetResource elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { Write-Host "Remove office suite app: $DisplayName" - Write-Output "INSIDE SECOND ELSE IF STATEMENT" - Write-Host "INSIDE SECOND ELSE IF STATEMENT" Remove-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id -Confirm:$false } } @@ -1164,7 +1161,8 @@ function Get-M365DSCIntuneAppExcludedAppsAsString return $StringContent } -function Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties { +function Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties +{ [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param @@ -1174,14 +1172,8 @@ function Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties { $Properties ) - Write-Host "WERE INSIDE THE HELPER FUNCTION" - Write-Output "WERE INSIDE THE HELPER FUNCTION" - # Define the list of additional properties to include in the final payload - $additionalProperties = @( - 'AutoAcceptEula' - 'ExcludedApps' - ) + $additionalProperties = @('AutoAcceptEula', 'ExcludedApps') # Initialize a hashtable to store the additional properties $results = @{'@odata.type' = '#microsoft.graph.officeSuiteApp'} @@ -1190,39 +1182,42 @@ function Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties { $cloneProperties = $Properties.clone() # Loop through the clone and process each property based on its type - foreach ($property in $cloneProperties.Keys) { - if ($property -in $additionalProperties) { + foreach ($property in $cloneProperties.Keys) + { + if ($property -in $additionalProperties) + { # Convert property name to expected format $propertyName = $property[0].ToString().ToLower() + $property.Substring(1, $property.Length - 1) $propertyValue = $Properties.$property - # Handle ExcludedApps: Build a single PSCustomObject with key-value pairs - if ($propertyName -eq 'excludedApps') { + # Handle ExcludedApps: Convert to a hashtable with camelCase properties + if ($propertyName -eq 'excludedApps' -and $propertyValue -is [System.Collections.Hashtable]) + { $formattedExcludedApps = @{} - # Convert each key in ExcludedApps to a key-value pair in a hashtable - foreach ($key in $propertyValue.Keys) { - # Ensure the value is correctly formatted as boolean $true or $false - $formattedExcludedApps[$key] = if ($propertyValue[$key]) { $true } else { $false } + # Convert each key in ExcludedApps to camelCase and add to formattedExcludedApps + foreach ($key in $propertyValue.Keys) + { + $camelCaseKey = $key.Substring(0, 1).ToLower() + $key.Substring(1) + $formattedExcludedApps[$camelCaseKey] = $propertyValue[$key] } # Convert to PSCustomObject to match the expected format $results.Add($propertyName, [PSCustomObject]$formattedExcludedApps) } - else { + else + { # For simple types like Boolean (AutoAcceptEula), add directly $results.Add($propertyName, $propertyValue) } } } - Write-Host "Formatted ExcludedApps: $(ConvertTo-Json $results['excludedApps'])" - Write-Output "Formatted ExcludedApps: $(ConvertTo-Json $results['excludedApps'])" - Write-Host "Formatted AdditionalProperties: $(ConvertTo-Json $results)" - Write-Output "Formatted AdditionalProperties Type: $($results.GetType().FullName)" + return $results } -# function Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties { +# function Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties +# { # [CmdletBinding()] # [OutputType([System.Collections.Hashtable])] # param @@ -1232,29 +1227,46 @@ function Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties { # $Properties # ) -# # Initialize a hashtable to store only the relevant additional properties -# $results = @{} - -# # Add `excludedApps` if present -# if ($Properties.ContainsKey('ExcludedApps')) { -# $results.Add('excludedApps', $Properties['ExcludedApps']) +# # Define the list of additional properties to include in the final payload +# $additionalProperties = @('AutoAcceptEula', 'ExcludedApps') + +# # Initialize a hashtable to store the additional properties +# $results = @{'@odata.type' = '#microsoft.graph.officeSuiteApp'} + +# # Loop through the clone and process each property based on its type +# foreach ($property in $Properties.Keys) +# { +# if ($property -in $additionalProperties) +# { +# $propertyName = $property.Substring(0, 1).ToLower() + $property.Substring(1) +# $propertyValue = $Properties.$property + +# # Handle ExcludedApps as a hashtable with camelCase properties +# if ($propertyName -eq 'excludedApps' -and $propertyValue -is [System.Collections.Hashtable]) +# { +# $formattedExcludedApps = @{} + +# # Ensure the keys are camelCase +# foreach ($key in $propertyValue.Keys) +# { +# $camelCaseKey = $key.Substring(0, 1).ToLower() + $key.Substring(1) +# $formattedExcludedApps[$camelCaseKey] = $propertyValue[$key] +# } + +# # Convert it to PSCustomObject +# $results[$propertyName] = [PSCustomObject]$formattedExcludedApps +# } +# else +# { +# # For simple types, just add the value directly +# $results[$propertyName] = $propertyValue +# } +# } # } -# # Add `autoAcceptEula` if present -# if ($Properties.ContainsKey('AutoAcceptEula')) { -# $results.Add('autoAcceptEula', $Properties['AutoAcceptEula']) -# } - -# # Debug output to ensure correct structure -# Write-Output "Formatted AdditionalProperties Type: $($results.GetType().FullName)" -# Write-Host "Formatted AdditionalProperties: $(ConvertTo-Json $results)" -# Write-Host "Formatted ExcludedApps: $(ConvertTo-Json $results['excludedApps'])" -# Write-Output "Formatted ExcludedApps: $(ConvertTo-Json $results['excludedApps'])" # return $results # } - - function Get-M365DSCIntuneAppLargeIconAsString #Get and Export { [CmdletBinding()] diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof index ef6cdaf8d0..8613b2b42c 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof @@ -53,13 +53,6 @@ class MSFT_DeviceManagementMobileAppCategory [Write, Description("The unique identifier for an entity. Read-only.")] String id; }; -class MSFT_DeviceManagementMobileAppChildApp -{ - [Write, Description("The bundleId of the app.")] String bundleId; - [Write, Description("The build number of the app.")] String buildNumber; - [Write, Description("The version number of the app.")] String versionNumber; -}; - class MSFT_DeviceManagementMobileAppExcludedApp { [Write, Description("Specifies whether to exclude Microsoft Office Access from the installation.")] Boolean Access; From 61949a7977cb28c481e4a92382d0f8b88ded7471 Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Sat, 12 Oct 2024 01:55:10 -0700 Subject: [PATCH 196/252] working version of excluded apps and additional properties --- ...IntuneMobileAppsWindowsOfficeSuiteApp.psm1 | 140 +++++++----------- ...MobileAppsWindowsOfficeSuiteApp.schema.mof | 96 +++++------- 2 files changed, 97 insertions(+), 139 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 index 9b63396a4b..285d263f0c 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 @@ -505,8 +505,10 @@ function Set-TargetResource $CreateParameters = ([Hashtable]$PSBoundParameters).clone() $CreateParameters = Rename-M365DSCCimInstanceParameter -Properties $CreateParameters Write-Output "Before AdditionalProperties creation: $($CreateParameters | Out-String)" + Write-Host "Before AdditionalProperties creation: $($CreateParameters | Out-String)" $AdditionalProperties = Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties -Properties ($CreateParameters) Write-Output "AdditionalProperties: $($AdditionalProperties | Out-String)" + Write-Host "Before AdditionalProperties creation: $($CreateParameters | Out-String)" foreach ($key in $AdditionalProperties.keys) { if ($key -ne '@odata.type') @@ -569,8 +571,35 @@ function Set-TargetResource $PSBoundParameters.Remove('Assignments') | Out-Null $UpdateParameters = ([Hashtable]$PSBoundParameters).clone() $UpdateParameters = Rename-M365DSCCimInstanceParameter -Properties $UpdateParameters - $AdditionalProperties = Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties -Properties ($UpdateParameters) + # AdditionalProperties + Write-Host "AdditionalProperties content: $($AdditionalProperties | Out-String)" + + # If you want to specifically print the 'excludedApps' property within AdditionalProperties + if ($AdditionalProperties.ContainsKey('excludedApps')) { + Write-Host "ExcludedApps content: $($AdditionalProperties['excludedApps'] | Out-String)" + } else { + Write-Host "ExcludedApps not found in AdditionalProperties" + } + # Print the type of AdditionalProperties + if ($null -ne $AdditionalProperties) { + Write-Host "Type of AdditionalProperties: $($AdditionalProperties.GetType().FullName)" + } else { + Write-Host "AdditionalProperties is null." + } + # Check and print the type of ExcludedApps within AdditionalProperties + if ($AdditionalProperties.ContainsKey('excludedApps')) { + Write-Host "Type of excludedApps: $($AdditionalProperties['excludedApps'].GetType().FullName)" + } else { + Write-Host "excludedApps not found in AdditionalProperties." + } + $AdditionalProperties = Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties -Properties $CreateParameters + + # ExcludedApps should be properly formatted and passed to the API + if ($AdditionalProperties.ContainsKey('excludedApps')) { + Write-Host "Formatted ExcludedApps: $($AdditionalProperties['excludedApps'] | ConvertTo-Json -Depth 3)" + } + foreach ($key in $AdditionalProperties.keys) { if ($key -ne '@odata.type') @@ -582,9 +611,15 @@ function Set-TargetResource } $UpdateParameters.Remove('Id') | Out-Null - $UpdateParameters.Remove('Verbose') | Out-Null + # $UpdateParameters.Remove('Verbose') | Out-Null $UpdateParameters.Remove('Categories') | Out-Null $UpdateParameters.Remove('PublishingState') | Out-Null #Not allowed to update as it's a computed property + # Remove read-only properties before updating + $UpdateParameters.Remove('Developer') | Out-Null + $UpdateParameters.Remove('Owner') | Out-Null + $UpdateParameters.Remove('Publisher') | Out-Null + + Write-Host "UpdateParameters before API call: $($UpdateParameters | Out-String)" foreach ($key in ($UpdateParameters.clone()).Keys) { @@ -1161,15 +1196,12 @@ function Get-M365DSCIntuneAppExcludedAppsAsString return $StringContent } -function Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties -{ +function Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] - param - ( + param ( [Parameter(Mandatory = $true)] - [System.Collections.Hashtable] - $Properties + [System.Collections.Hashtable] $Properties ) # Define the list of additional properties to include in the final payload @@ -1178,95 +1210,35 @@ function Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties # Initialize a hashtable to store the additional properties $results = @{'@odata.type' = '#microsoft.graph.officeSuiteApp'} - # Clone the original properties to manipulate - $cloneProperties = $Properties.clone() - - # Loop through the clone and process each property based on its type - foreach ($property in $cloneProperties.Keys) - { - if ($property -in $additionalProperties) - { - # Convert property name to expected format - $propertyName = $property[0].ToString().ToLower() + $property.Substring(1, $property.Length - 1) + # Loop through and process each property based on its type + foreach ($property in $Properties.Keys) { + if ($property -in $additionalProperties) { + $propertyName = $property.Substring(0, 1).ToLower() + $property.Substring(1) $propertyValue = $Properties.$property - # Handle ExcludedApps: Convert to a hashtable with camelCase properties - if ($propertyName -eq 'excludedApps' -and $propertyValue -is [System.Collections.Hashtable]) - { + # Handle ExcludedApps as a hashtable with camelCase properties + if ($propertyName -eq 'excludedApps' -and $propertyValue -is [System.Array]) { $formattedExcludedApps = @{} - # Convert each key in ExcludedApps to camelCase and add to formattedExcludedApps - foreach ($key in $propertyValue.Keys) - { - $camelCaseKey = $key.Substring(0, 1).ToLower() + $key.Substring(1) - $formattedExcludedApps[$camelCaseKey] = $propertyValue[$key] + # Iterate over each CIMInstance object and extract the Name/Value pairs, converting to camelCase + foreach ($app in $propertyValue) { + foreach ($instanceProperty in $app.CimInstanceProperties) { + $camelCaseKey = $instanceProperty.Name.Substring(0, 1).ToLower() + $instanceProperty.Name.Substring(1) + $formattedExcludedApps[$camelCaseKey] = $instanceProperty.Value + } } - # Convert to PSCustomObject to match the expected format - $results.Add($propertyName, [PSCustomObject]$formattedExcludedApps) - } - else - { + # Add the formatted ExcludedApps to results + $results[$propertyName] = $formattedExcludedApps + } else { # For simple types like Boolean (AutoAcceptEula), add directly - $results.Add($propertyName, $propertyValue) + $results[$propertyName] = $propertyValue } } } - return $results } -# function Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties -# { -# [CmdletBinding()] -# [OutputType([System.Collections.Hashtable])] -# param -# ( -# [Parameter(Mandatory = $true)] -# [System.Collections.Hashtable] -# $Properties -# ) - -# # Define the list of additional properties to include in the final payload -# $additionalProperties = @('AutoAcceptEula', 'ExcludedApps') - -# # Initialize a hashtable to store the additional properties -# $results = @{'@odata.type' = '#microsoft.graph.officeSuiteApp'} - -# # Loop through the clone and process each property based on its type -# foreach ($property in $Properties.Keys) -# { -# if ($property -in $additionalProperties) -# { -# $propertyName = $property.Substring(0, 1).ToLower() + $property.Substring(1) -# $propertyValue = $Properties.$property - -# # Handle ExcludedApps as a hashtable with camelCase properties -# if ($propertyName -eq 'excludedApps' -and $propertyValue -is [System.Collections.Hashtable]) -# { -# $formattedExcludedApps = @{} - -# # Ensure the keys are camelCase -# foreach ($key in $propertyValue.Keys) -# { -# $camelCaseKey = $key.Substring(0, 1).ToLower() + $key.Substring(1) -# $formattedExcludedApps[$camelCaseKey] = $propertyValue[$key] -# } - -# # Convert it to PSCustomObject -# $results[$propertyName] = [PSCustomObject]$formattedExcludedApps -# } -# else -# { -# # For simple types, just add the value directly -# $results[$propertyName] = $propertyValue -# } -# } -# } - -# return $results -# } - function Get-M365DSCIntuneAppLargeIconAsString #Get and Export { [CmdletBinding()] diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof index 8613b2b42c..c91163da06 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof @@ -1,3 +1,44 @@ +class MSFT_DeviceManagementMobileAppAssignment +{ + [Write, Description("The type of the target assignment."), ValueMap{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget", "#microsoft.graph.mobileAppAssignment"}, Values{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget", "#microsoft.graph.mobileAppAssignment"}] String dataType; + [Write, Description("The Id of the filter for the target assignment.")] String deviceAndAppManagementAssignmentFilterId; + [Write, Description("The type of filter of the target assignment i.e. Exclude or Include. Possible values are: none, include, exclude."), ValueMap{"none", "include", "exclude"}, Values{"none", "include", "exclude"}] String deviceAndAppManagementAssignmentFilterType; + [Write, Description("The group Id that is the target of the assignment.")] String groupId; + [Write, Description("The group Display Name that is the target of the assignment.")] String groupDisplayName; + [Write, Description("Possible values for the install intent chosen by the admin."), ValueMap{"available", "required", "uninstall", "availableWithoutEnrollment"}, Values{"available", "required", "uninstall", "availableWithoutEnrollment"}] String intent; +}; + +class MSFT_DeviceManagementMimeContent +{ + [Write, Description("Indicates the type of content mime.")] String Type; + [Write, Description("The Base64 encoded string content.")] String Value; +}; + +class MSFT_DeviceManagementMobileAppCategory +{ + [Key, Description("The name of the app category.")] String DisplayName; + [Write, Description("The unique identifier for an entity. Read-only.")] String Id; +}; + +class MSFT_DeviceManagementMobileAppExcludedApp +{ + [Write, Description("Specifies whether to exclude Microsoft Office Access from the installation.")] Boolean Access; + [Write, Description("Specifies whether to exclude Microsoft Search (Bing) as the default from the installation.")] Boolean Bing; + [Write, Description("Specifies whether to exclude Microsoft Office Excel from the installation.")] Boolean Excel; + [Write, Description("Specifies whether to exclude Microsoft Office OneDrive for Business (Groove) from the installation.")] Boolean Groove; + [Write, Description("Specifies whether to exclude Microsoft Office InfoPath from the installation.")] Boolean InfoPath; + [Write, Description("Specifies whether to exclude Microsoft Office Skype for Business (Lync) from the installation.")] Boolean Lync; + [Write, Description("Specifies whether to exclude Microsoft Office OneDrive from the installation.")] Boolean OneDrive; + [Write, Description("Specifies whether to exclude Microsoft Office OneNote from the installation.")] Boolean OneNote; + [Write, Description("Specifies whether to exclude Microsoft Office Outlook from the installation.")] Boolean Outlook; + [Write, Description("Specifies whether to exclude Microsoft Office PowerPoint from the installation.")] Boolean PowerPoint; + [Write, Description("Specifies whether to exclude Microsoft Office Publisher from the installation.")] Boolean Publisher; + [Write, Description("Specifies whether to exclude Microsoft Office SharePoint Designer from the installation.")] Boolean SharePointDesigner; + [Write, Description("Specifies whether to exclude Microsoft Office Teams from the installation.")] Boolean Teams; + [Write, Description("Specifies whether to exclude Microsoft Office Visio from the installation.")] Boolean Visio; + [Write, Description("Specifies whether to exclude Microsoft Office Word from the installation.")] Boolean Word; +}; + [ClassVersion("1.0.0"), FriendlyName("IntuneMobileAppsWindowsOfficeSuiteApp")] class MSFT_IntuneMobileAppsWindowsOfficeSuiteApp : OMI_BaseResource { @@ -40,58 +81,3 @@ class MSFT_IntuneMobileAppsWindowsOfficeSuiteApp : OMI_BaseResource [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; [Write, Description("Access token used for authentication.")] String AccessTokens[]; }; - -class MSFT_DeviceManagementMimeContent -{ - [Write, Description("Indicates the type of content mime.")] String type; - [Write, Description("The byte array that contains the actual content.")] String value[]; -}; - -class MSFT_DeviceManagementMobileAppCategory -{ - [Key, Description("The name of the app category.")] String displayName; - [Write, Description("The unique identifier for an entity. Read-only.")] String id; -}; - -class MSFT_DeviceManagementMobileAppExcludedApp -{ - [Write, Description("Specifies whether to exclude Microsoft Office Access from the installation.")] Boolean Access; - [Write, Description("Specifies whether to exclude Microsoft Search (Bing) as the default from the installation.")] Boolean Bing; - [Write, Description("Specifies whether to exclude Microsoft Office Excel from the installation.")] Boolean Excel; - [Write, Description("Specifies whether to exclude Microsoft Office OneDrive for Business (Groove) from the installation.")] Boolean Groove; - [Write, Description("Specifies whether to exclude Microsoft Office InfoPath from the installation.")] Boolean InfoPath; - [Write, Description("Specifies whether to exclude Microsoft Office Skype for Business (Lync) from the installation.")] Boolean Lync; - [Write, Description("Specifies whether to exclude Microsoft Office OneDrive from the installation.")] Boolean OneDrive; - [Write, Description("Specifies whether to exclude Microsoft Office OneNote from the installation.")] Boolean OneNote; - [Write, Description("Specifies whether to exclude Microsoft Office Outlook from the installation.")] Boolean Outlook; - [Write, Description("Specifies whether to exclude Microsoft Office PowerPoint from the installation.")] Boolean PowerPoint; - [Write, Description("Specifies whether to exclude Microsoft Office Publisher from the installation.")] Boolean Publisher; - [Write, Description("Specifies whether to exclude Microsoft Office SharePoint Designer from the installation.")] Boolean SharePointDesigner; - [Write, Description("Specifies whether to exclude Microsoft Office Teams from the installation.")] Boolean Teams; - [Write, Description("Specifies whether to exclude Microsoft Office Visio from the installation.")] Boolean Visio; - [Write, Description("Specifies whether to exclude Microsoft Office Word from the installation.")] Boolean Word; -}; - -class MSFT_DeviceManagementMobileAppAssignment -{ - [Write, Description("The type of the target assignment."), - ValueMap{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget", "#microsoft.graph.mobileAppAssignment"}, - Values{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget", "#microsoft.graph.mobileAppAssignment"}] - String dataType; - - [Write, Description("The Id of the filter for the target assignment.")] String deviceAndAppManagementAssignmentFilterId; - [Write, Description("The type of filter of the target assignment i.e. Exclude or Include. Possible values are: none, include, exclude."), - ValueMap{"none", "include", "exclude"}, - Values{"none", "include", "exclude"}] - String deviceAndAppManagementAssignmentFilterType; - - [Write, Description("The group Id that is the target of the assignment.")] String groupId; - [Write, Description("The group Display Name that is the target of the assignment.")] String groupDisplayName; - - [Write, Description("Possible values for the install intent chosen by the admin."), - ValueMap{"available", "required", "uninstall", "availableWithoutEnrollment"}, - Values{"available", "required", "uninstall", "availableWithoutEnrollment"}] - String intent; - - [Write, Description("The source of this assignment.")] String source; -}; From ae74a30f866e8ab47c6bec3bb69837f7a955509d Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Sun, 13 Oct 2024 11:43:56 -0700 Subject: [PATCH 197/252] current update with excluded apps not working --- ...IntuneMobileAppsWindowsOfficeSuiteApp.psm1 | 747 +++++++----------- 1 file changed, 276 insertions(+), 471 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 index 285d263f0c..16a0858546 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 @@ -179,99 +179,108 @@ function Get-TargetResource $nullResult.Ensure = 'Absent' try { - $instance = Get-MgBetaDeviceAppManagementMobileApp ` - -Filter "(isof('microsoft.graph.officeSuiteApp') and displayName eq '$DisplayName')" ` - -ExpandProperty "categories,assignments" ` - -ErrorAction SilentlyContinue | Where-Object ` - -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.officeSuiteApp' } + $instance = Get-MgBetaDeviceAppManagementMobileApp -MobileAppId $Id ` + -ExpandProperty "categories" ` + -ErrorAction SilentlyContinue if ($null -eq $instance) { - Write-Verbose -Message "No Mobile app with DisplayName {$DisplayName} was found. Search with DisplayName." - $instance = Get-MgBetaDeviceAppManagementMobileApp ` - -MobileAppId $Id ` - -ExpandProperty "categories,assignments" ` - -ErrorAction Stop | Where-Object ` - -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.officeSuiteApp' } + Write-Verbose -Message "Could not find an Intune Windows Office Suite App with Id {$Id}." + + if (-not [System.String]::IsNullOrEmpty($DisplayName)) + { + $instance = Get-MgBetaDeviceAppManagementMobileApp ` + -Filter "(isof('microsoft.graph.officeSuiteApp') and displayName eq '$DisplayName')" ` + -ErrorAction SilentlyContinue + } + + if ($null -ne $instance) + { + $instance = Get-MgBetaDeviceAppManagementMobileApp -MobileAppId $instance.Id ` + -ExpandProperty "categories" ` + -ErrorAction SilentlyContinue + $Id = $instance.Id + } } if ($null -eq $instance) { - Write-Verbose -Message "No Mobile app with {$Id} was found." + Write-Verbose -Message "Could not find an Intune Windows Office Suite App with DisplayName {$DisplayName} was found." return $nullResult } - $results = @{ - Id = $instance.Id - DisplayName = $instance.DisplayName - Description = $instance.Description - Publisher = $instance.Publisher - IsFeatured = $instance.IsFeatured - PrivacyInformationUrl = $instance.PrivacyInformationUrl - InformationUrl = $instance.InformationUrl - Owner = $instance.Owner - Developer = $instance.Developer - Notes = $instance.Notes - PublishingState = $instance.PublishingState.ToString() - RoleScopeTagIds = $instance.RoleScopeTagIds - ProductIds = $instance.ProductIds - UseSharedComputerActivation = $instance.UseSharedComputerActivation - UpdateChannel = $instance.UpdateChannel - OfficeSuiteAppDefaultFileFormat = $instance.OfficeSuiteAppDefaultFileFormat - OfficePlatformArchitecture = $instance.OfficePlatformArchitecture - LocalesToInstall = $instance.LocalesToInstall - InstallProgressDisplayLevel = $instance.InstallProgressDisplayLevel - ShouldUninstallOlderVersionsOfOffice = $instance.ShouldUninstallOlderVersionsOfOffice - TargetVersion = $instance.TargetVersion - UpdateVersion = $instance.UpdateVersion - OfficeConfigurationXml = $instance.OfficeConfigurationXml - AutoAcceptEula = $instance.AdditionalProperties.AutoAcceptEula - - Ensure = 'Present' - Credential = $Credential - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - ApplicationSecret = $ApplicationSecret - ManagedIdentity = $ManagedIdentity.IsPresent - AccessTokens = $AccessTokens - } + Write-Verbose "An Intune Windows Office Suite App with Id {$Id} and DisplayName {$DisplayName} was found." #region complex types - - #Categories - if($null -ne $instance.Categories) + $complexCategories = @() + foreach ($category in $instance.Categories) { - $results.Add('Categories', $instance.Categories) + $myCategory = @{} + $myCategory.Add('Id', $category.id) + $myCategory.Add('DisplayName', $category.displayName) + $complexCategories += $myCategory } - else { - $results.Add('Categories', "") + + $complexExcludedApps = [ordered]@{ + "access" = $instance.AdditionalProperties.excludedApps["access"] + "bing" = $instance.AdditionalProperties.excludedApps["bing"] + "excel" = $instance.AdditionalProperties.excludedApps["excel"] + "groove" = $instance.AdditionalProperties.excludedApps["groove"] + "infoPath" = $instance.AdditionalProperties.excludedApps["infoPath"] + "lync" = $instance.AdditionalProperties.excludedApps["lync"] + "oneDrive" = $instance.AdditionalProperties.excludedApps["oneDrive"] + "oneNote" = $instance.AdditionalProperties.excludedApps["oneNote"] + "outlook" = $instance.AdditionalProperties.excludedApps["outlook"] + "powerPoint" = $instance.AdditionalProperties.excludedApps["powerPoint"] + "publisher" = $instance.AdditionalProperties.excludedApps["publisher"] + "sharePointDesigner" = $instance.AdditionalProperties.excludedApps["sharePointDesigner"] + "teams" = $instance.AdditionalProperties.excludedApps["teams"] + "visio" = $instance.AdditionalProperties.excludedApps["visio"] + "word" = $instance.AdditionalProperties.excludedApps["word"] } - # ExcludedApps - if ($null -ne $instance.AdditionalProperties -and $null -ne $instance.AdditionalProperties.excludedApps) + $complexLargeIcon = @{} + if ($null -ne $instance.LargeIcon.Value) { - # Convert to Hashtable if it is an array - if ($instance.AdditionalProperties.excludedApps -is [System.Object[]]) { - $formattedExcludedApps = @{} - foreach ($app in $instance.AdditionalProperties.excludedApps) { - foreach ($key in $app.Keys) { - $formattedExcludedApps[$key] = $app[$key] - } - } - } - else { - $formattedExcludedApps = $instance.AdditionalProperties.excludedApps - } - - # Ensure ExcludedApps is returned as a Hashtable - $results['ExcludedApps'] = @{} - foreach ($key in $formattedExcludedApps.Keys) { - $results['ExcludedApps'].Add($key, $formattedExcludedApps[$key]) - } + $complexLargeIcon.Add('Value', [System.Convert]::ToBase64String($instance.LargeIcon.Value)) + $complexLargeIcon.Add('Type', $instance.LargeIcon.Type) } - else { - $results.Add('ExcludedApps', $null) + + $results = @{ + Id = $instance.Id + DisplayName = $instance.DisplayName + Description = $instance.Description + Publisher = $instance.Publisher + IsFeatured = $instance.IsFeatured + PrivacyInformationUrl = $instance.PrivacyInformationUrl + InformationUrl = $instance.InformationUrl + Owner = $instance.Owner + Developer = $instance.Developer + Notes = $instance.Notes + RoleScopeTagIds = $instance.RoleScopeTagIds + AutoAcceptEula = $instance.AdditionalProperties.autoAcceptEula + ProductIds = $instance.AdditionalProperties.productIds + UseSharedComputerActivation = $instance.AdditionalProperties.useSharedComputerActivation + UpdateChannel = $instance.AdditionalProperties.updateChannel + OfficeSuiteAppDefaultFileFormat = $instance.AdditionalProperties.officeSuiteAppDefaultFileFormat + OfficePlatformArchitecture = $instance.AdditionalProperties.officePlatformArchitecture + LocalesToInstall = $instance.AdditionalProperties.localesToInstall + InstallProgressDisplayLevel = $instance.AdditionalProperties.installProgressDisplayLevel + ShouldUninstallOlderVersionsOfOffice = $instance.AdditionalProperties.shouldUninstallOlderVersionsOfOffice + TargetVersion = $instance.AdditionalProperties.targetVersion + UpdateVersion = $instance.AdditionalProperties.updateVersion + OfficeConfigurationXml = $instance.AdditionalProperties.officeConfigurationXml + LargeIcon = $complexLargeIcon + ExcludedApps = $complexExcludedApps + Categories = $complexCategories + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ApplicationSecret = $ApplicationSecret + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens } #Assignments @@ -279,24 +288,20 @@ function Get-TargetResource $appAssignments = Get-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $instance.Id if ($null -ne $appAssignments -and $appAssignments.count -gt 0) { - $resultAssignments += ConvertFrom-IntuneMobileAppAssignment ` - -IncludeDeviceFilter:$true ` - -Assignments ($appAssignments) - - $results.Add('Assignments', $resultAssignments) - } + $convertedAssignments = ConvertFrom-IntuneMobileAppAssignment ` + -IncludeDeviceFilter:$true ` + -Assignments ($appAssignments) + + # Filter out 'source' from the assignment objects + foreach ($assignment in $convertedAssignments) { + if ($assignment.ContainsKey('source')) { + $assignment.Remove('source') + } + } - #LargeIcon - # The large is returned only when Get cmdlet is called with Id parameter. The large icon is a base64 encoded string, so we need to convert it to a byte array. - $instanceWithLargeIcon = Get-MgBetaDeviceAppManagementMobileApp -MobileAppId $instance.Id - if (-not $results.ContainsKey('LargeIcon')) { - $results.Add('LargeIcon', $instanceWithLargeIcon.LargeIcon) - } else { - $results['LargeIcon'] = $instanceWithLargeIcon.LargeIcon # Update the existing key + $resultAssignments += $convertedAssignments } - - #end region complex types - + $results.Add('Assignments', $resultAssignments) return [System.Collections.Hashtable] $results } catch @@ -315,7 +320,7 @@ function Get-TargetResource function Set-TargetResource { [CmdletBinding()] - param + param ( #region Intune resource parameters @@ -486,179 +491,154 @@ function Set-TargetResource #endregion $currentInstance = Get-TargetResource @PSBoundParameters - $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 - - $CreateParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters - - # CREATE + $BoundParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { - Write-Host "Create office suite app: $DisplayName" + Write-Verbose -Message "Creating an Intune Windows Office Suite App with DisplayName {$DisplayName}" + $BoundParameters.Remove('Assignments') | Out-Null - $CreateParameters = ([Hashtable]$PSBoundParameters).clone() + $CreateParameters = ([Hashtable]$BoundParameters).Clone() $CreateParameters = Rename-M365DSCCimInstanceParameter -Properties $CreateParameters - Write-Output "Before AdditionalProperties creation: $($CreateParameters | Out-String)" - Write-Host "Before AdditionalProperties creation: $($CreateParameters | Out-String)" - $AdditionalProperties = Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties -Properties ($CreateParameters) - Write-Output "AdditionalProperties: $($AdditionalProperties | Out-String)" - Write-Host "Before AdditionalProperties creation: $($CreateParameters | Out-String)" - foreach ($key in $AdditionalProperties.keys) + $CreateParameters.Remove('Id') | Out-Null + $CreateParameters.Remove('Categories') | Out-Null + + foreach ($key in ($CreateParameters.Clone()).Keys) { - if ($key -ne '@odata.type') + if ($null -ne $CreateParameters.$key -and $CreateParameters.$key.GetType().Name -like '*CimInstance*') { - $keyName = $key.substring(0, 1).ToUpper() + $key.substring(1, $key.length - 1) - $CreateParameters.remove($keyName) + $CreateParameters.$key = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $CreateParameters.$key } } - $CreateParameters.remove('Id') | Out-Null - $CreateParameters.remove('Ensure') | Out-Null - $CreateParameters.remove('Categories') | Out-Null - $CreateParameters.remove('Assignments') | Out-Null - $CreateParameters.remove('excludedApps') | Out-Null - $CreateParameters.Remove('Verbose') | Out-Null - $CreateParameters.Remove('PublishingState') | Out-Null #Not allowed to update as it's a computed property - $CreateParameters.Remove('LargeIcon') | Out-Null + $CreateParameters.Add('@odata.type', '#microsoft.graph.officeSuiteApp') + $app = New-MgBetaDeviceAppManagementMobileApp -BodyParameter $CreateParameters - foreach ($key in ($CreateParameters.clone()).Keys) + foreach ($category in $Categories) { - if ($CreateParameters[$key].getType().Fullname -like '*CimInstance*') + if ($category.Id) { - $CreateParameters[$key] = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $CreateParameters[$key] + $currentCategory = Get-MgBetaDeviceAppManagementMobileAppCategory -CategoryId $category.Id + } + else + { + $currentCategory = Get-MgBetaDeviceAppManagementMobileAppCategory -Filter "displayName eq '$($category.DisplayName)'" } - } - if ($AdditionalProperties) - { - $CreateParameters.add('AdditionalProperties', $AdditionalProperties) - } + if ($null -eq $currentCategory) + { + throw "Mobile App Category with DisplayName $($category.DisplayName) not found." + } - #LargeIcon - if($LargeIcon) - { - [System.Object]$LargeIconValue = ConvertTo-M365DSCIntuneAppLargeIcon -LargeIcon $LargeIcon - if (-not $CreateParameters.ContainsKey('LargeIcon')) { - $CreateParameters.Add('LargeIcon', $LargeIconValue) - } else { - $CreateParameters['LargeIcon'] = $LargeIconValue + Invoke-MgBetaGraphRequest -Uri "/beta/deviceAppManagement/mobileApps/$($app.Id)/categories/`$ref" -Method 'POST' -Body @{ + '@odata.id' = "https://graph.microsoft.com/beta/deviceAppManagement/mobileAppCategories/$($currentCategory.Id)" } } - Write-Output "CreateParameters before API call: $($CreateParameters | Out-String)" - $app = New-MgBetaDeviceAppManagementMobileApp @CreateParameters #Assignments - $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments - if ($app.id) + if ($app.Id) { - Write-Output "UpdateParameters before API call: $($UpdateParameters | Out-String)" - Update-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $app.id ` - -Target $assignmentsHash ` - -Repository 'deviceAppManagement/mobileAppAssignments' + $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + Update-DeviceAppManagementPolicyAssignment -AppManagementPolicyId $app.Id ` + -Assignments $assignmentsHash } } - # UPDATE elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { - Write-Host "Update office suite app: $DisplayName" + Write-Host "Updating the Intune Windows Office Suite App with DisplayName {$DisplayName}" + $BoundParameters.Remove('Assignments') | Out-Null - $PSBoundParameters.Remove('Assignments') | Out-Null - $UpdateParameters = ([Hashtable]$PSBoundParameters).clone() + $UpdateParameters = ([Hashtable]$BoundParameters).Clone() $UpdateParameters = Rename-M365DSCCimInstanceParameter -Properties $UpdateParameters - $AdditionalProperties = Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties -Properties ($UpdateParameters) - # AdditionalProperties - Write-Host "AdditionalProperties content: $($AdditionalProperties | Out-String)" - - # If you want to specifically print the 'excludedApps' property within AdditionalProperties - if ($AdditionalProperties.ContainsKey('excludedApps')) { - Write-Host "ExcludedApps content: $($AdditionalProperties['excludedApps'] | Out-String)" - } else { - Write-Host "ExcludedApps not found in AdditionalProperties" - } - # Print the type of AdditionalProperties - if ($null -ne $AdditionalProperties) { - Write-Host "Type of AdditionalProperties: $($AdditionalProperties.GetType().FullName)" - } else { - Write-Host "AdditionalProperties is null." - } - # Check and print the type of ExcludedApps within AdditionalProperties - if ($AdditionalProperties.ContainsKey('excludedApps')) { - Write-Host "Type of excludedApps: $($AdditionalProperties['excludedApps'].GetType().FullName)" - } else { - Write-Host "excludedApps not found in AdditionalProperties." - } - $AdditionalProperties = Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties -Properties $CreateParameters - - # ExcludedApps should be properly formatted and passed to the API - if ($AdditionalProperties.ContainsKey('excludedApps')) { - Write-Host "Formatted ExcludedApps: $($AdditionalProperties['excludedApps'] | ConvertTo-Json -Depth 3)" - } - - foreach ($key in $AdditionalProperties.keys) - { - if ($key -ne '@odata.type') - { - $keyName = $key.substring(0, 1).ToUpper() + $key.substring(1, $key.length - 1) - #Remove additional keys, so that later they can be added as 'AdditionalProperties' - $UpdateParameters.Remove($keyName) - } - } - $UpdateParameters.Remove('Id') | Out-Null - # $UpdateParameters.Remove('Verbose') | Out-Null $UpdateParameters.Remove('Categories') | Out-Null - $UpdateParameters.Remove('PublishingState') | Out-Null #Not allowed to update as it's a computed property - # Remove read-only properties before updating + $UpdateParameters.Remove('OfficePlatformArchitecture') | Out-Null $UpdateParameters.Remove('Developer') | Out-Null $UpdateParameters.Remove('Owner') | Out-Null $UpdateParameters.Remove('Publisher') | Out-Null + $UpdateParameters.Remove('RoleScopeTagIds') | Out-Null + Write-Host "Initial ExcludedApps Data:" $ExcludedApps + + if ($UpdateParameters.ContainsKey('ExcludedApps')) { + # Convert ExcludedApps into an ordered hashtable using the same pattern as in the helper functions + $excludedAppsDict = [ordered]@{} + + # Define the list of known apps to exclude + $excludedAppsKeys = @( + 'access', 'bing', 'excel', 'groove', 'infoPath', 'lync', + 'oneDrive', 'oneNote', 'outlook', 'powerPoint', 'publisher', + 'sharePointDesigner', 'teams', 'visio', 'word' + ) + + # Loop through the known app keys and dynamically populate the dictionary + foreach ($key in $excludedAppsKeys) { + if ($AdditionalProperties['excludedApps'].ContainsKey($key)) { + $excludedAppsDict[$key] = $AdditionalProperties['excludedApps'][$key] + } else { + # Set default values for each key if not explicitly provided + if ($key -in @('groove', 'infoPath', 'lync', 'sharePointDesigner')) { + $excludedAppsDict[$key] = $true + } else { + $excludedAppsDict[$key] = $false + } + } + } - Write-Host "UpdateParameters before API call: $($UpdateParameters | Out-String)" + # Convert to JSON before sending to the API + $excludedAppsJson = $excludedAppsDict | ConvertTo-Json -Depth 3 - foreach ($key in ($UpdateParameters.clone()).Keys) - { - if ($UpdateParameters[$key].getType().Fullname -like '*CimInstance*') - { - $value = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $UpdateParameters[$key] - $UpdateParameters[$key] = $value - } + # Add this JSON to your parameters for the API + $UpdateParameters['excludedApps'] = $excludedAppsJson + } else { + Write-Host "ExcludedApps parameter not found in UpdateParameters." } - if ($AdditionalProperties) + # Print the entire UpdateParameters being sent to the API + Write-Host "Now ExcludedApps Data:" $UpdateParameters['excludedApps'] + + Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id -BodyParameter $UpdateParameters + + [array]$referenceObject = if ($null -ne $currentInstance.Categories.DisplayName) { $currentInstance.Categories.DisplayName } else { ,@() } + [array]$differenceObject = if ($null -ne $Categories.DisplayName) { $Categories.DisplayName } else { ,@() } + $delta = Compare-Object -ReferenceObject $referenceObject -DifferenceObject $differenceObject -PassThru + foreach ($diff in $delta) { - $UpdateParameters.Add('AdditionalProperties', $AdditionalProperties) - } + if ($diff.SideIndicator -eq '=>') + { + $category = $Categories | Where-Object { $_.DisplayName -eq $diff } + if ($category.Id) + { + $currentCategory = Get-MgBetaDeviceAppManagementMobileAppCategory -MobileAppCategoryId $category.Id + } + else + { + $currentCategory = Get-MgBetaDeviceAppManagementMobileAppCategory -Filter "displayName eq '$($category.DisplayName)'" + } - #LargeIcon - if($LargeIcon) - { - [System.Object]$LargeIconValue = ConvertTo-M365DSCIntuneAppLargeIcon -LargeIcon $LargeIcon - if (-not $CreateParameters.ContainsKey('LargeIcon')) { - $UpdateParameters.Add('LargeIcon', $LargeIconValue) - } else { - $UpdateParameters['LargeIcon'] = $LargeIconValue - } - } + if ($null -eq $currentCategory) + { + throw "Mobile App Category with DisplayName $($category.DisplayName) not found." + } - Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id @UpdateParameters - Write-Host "Updated office suite App: $DisplayName." + Invoke-MgGraphRequest -Uri "/beta/deviceAppManagement/mobileApps/$($currentInstance.Id)/categories/`$ref" -Method 'POST' -Body @{ + '@odata.id' = "https://graph.microsoft.com/beta/deviceAppManagement/mobileAppCategories/$($currentCategory.Id)" + } + } + else + { + $category = $currentInstance.Categories | Where-Object { $_.DisplayName -eq $diff } + Invoke-MgGraphRequest -Uri "/beta/deviceAppManagement/mobileApps/$($currentInstance.Id)/categories/$($category.Id)/`$ref" -Method 'DELETE' + } + } #Assignments $assignmentsHash = ConvertTo-IntuneMobileAppAssignment -IncludeDeviceFilter:$true -Assignments $Assignments - Update-MgBetaDeviceAppManagementMobileAppAssignment -MobileAppId $currentInstance.id ` - -Target $assignmentsHash ` - -Repository 'deviceAppManagement/mobileAppAssignments' + Update-DeviceAppManagementPolicyAssignment -AppManagementPolicyId $currentInstance.Id ` + -Assignments $assignmentsHash } - # REMOVE elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { - Write-Host "Remove office suite app: $DisplayName" + Write-Host "Remove the Intune MacOS Lob App with Id {$($currentInstance.Id)}" Remove-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id -Confirm:$false } } @@ -667,7 +647,7 @@ function Test-TargetResource { [CmdletBinding()] [OutputType([System.Boolean])] - param + param ( #region Intune resource parameters @@ -837,20 +817,10 @@ function Test-TargetResource Add-M365DSCTelemetryEvent -Data $data #endregion - Write-Verbose -Message "Testing configuration of Intune Mobile office suite App: {$DisplayName}" + Write-Verbose -Message "Testing configuration of the Intune Windows Suite App with Id {$Id} and DisplayName {$DisplayName}" $CurrentValues = Get-TargetResource @PSBoundParameters - if (-not (Test-M365DSCAuthenticationParameter -BoundParameters $CurrentValues)) - { - Write-Verbose "An error occured in Get-TargetResource, the app {$displayName} will not be processed" - throw "An error occured in Get-TargetResource, the app {$displayName} will not be processed. Refer to the event viewer logs for more information." - } - $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() - $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck - $ValuesToCheck.Remove('Id') | Out-Null - - Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" - Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() if ($CurrentValues.Ensure -ne $Ensure) { @@ -864,15 +834,14 @@ function Test-TargetResource { $source = $PSBoundParameters.$key $target = $CurrentValues.$key - if ($source.getType().Name -like '*CimInstance*') + if ($null -ne $source -and $source.GetType().Name -like '*CimInstance*') { $testResult = Compare-M365DSCComplexObject ` -Source ($source) ` -Target ($target) - if (-Not $testResult) + if (-not $testResult) { - $testResult = $false break } @@ -880,6 +849,17 @@ function Test-TargetResource } } + # Prevent screen from filling up with the LargeIcon value + # Comparison will already be done because it's a CimInstance + $CurrentValues.Remove('LargeIcon') | Out-Null + $PSBoundParameters.Remove('LargeIcon') | Out-Null + + $ValuesToCheck.Remove('Id') | Out-Null + $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + if ($testResult) { $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` @@ -899,6 +879,10 @@ function Export-TargetResource [OutputType([System.String])] param ( + [Parameter()] + [System.String] + $Filter, + [Parameter()] [System.Management.Automation.PSCredential] $Credential, @@ -948,9 +932,7 @@ function Export-TargetResource $Script:ExportMode = $true [array] $Script:getInstances = Get-MgBetaDeviceAppManagementMobileApp ` -Filter "isof('microsoft.graph.officeSuiteApp')" ` - -ExpandProperty "categories,assignments" ` - -ErrorAction Stop | Where-Object ` - -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.officeSuiteApp' } + -ErrorAction Stop $i = 1 $dscContent = '' @@ -990,61 +972,73 @@ function Export-TargetResource $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` -Results $Results - if (-not (Test-M365DSCAuthenticationParameter -BoundParameters $Results)) - { - Write-Verbose "An error occured in Get-TargetResource, the app {$($params.displayName)} will not be processed." - throw "An error occured in Get-TargetResource, the app {$($params.displayName)} will not be processed. Refer to the event viewer logs for more information." - } - #region complex types - - #Categories - if($null -ne $Results.Categories) + if ($null -ne $Results.Categories) { - $Results.Categories = Get-M365DSCIntuneAppCategoriesAsString -Categories $Results.Categories - } - else { - $Results.Remove('Categories') | Out-Null + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.Categories ` + -CIMInstanceName 'DeviceManagementMobileAppCategory' + + if (-not [System.String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.Categories = $complexTypeStringResult + } + else + { + $Results.Remove('Categories') | Out-Null + } } - # ExcludedApps if ($null -ne $Results.ExcludedApps) { - # Convert to a Hashtable if still an array - if ($Results.ExcludedApps -is [System.Object[]]) { - $Results.ExcludedApps = Convert-ObjectArrayToHashtable -InputArray $Results.ExcludedApps + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.ExcludedApps ` + -CIMInstanceName 'DeviceManagementMobileAppExcludedApp' + + if (-not [System.String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.ExcludedApps = $complexTypeStringResult + } + else + { + $Results.Remove('ExcludedApps') | Out-Null } - $Results.ExcludedApps = Get-M365DSCIntuneAppExcludedAppsAsString -ExcludedApps $Results.ExcludedApps - } - else { - $Results.Remove('ExcludedApps') | Out-Null } - #Assignments - if ($null -ne $Results.Assignments) + if ($null -ne $Results.LargeIcon) { - $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString -ComplexObject ([Array]$Results.Assignments) -CIMInstanceName DeviceManagementMobileAppAssignment + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.LargeIcon ` + -CIMInstanceName 'DeviceManagementMimeContent' - if ($complexTypeStringResult) + if (-not [System.String]::IsNullOrWhiteSpace($complexTypeStringResult)) { - $Results.Assignments = $complexTypeStringResult + $Results.LargeIcon = $complexTypeStringResult } else { - $Results.Remove('Assignments') | Out-Null + $Results.Remove('LargeIcon') | Out-Null } } - #LargeIcon - if($null -ne $Results.LargeIcon) - { - $Results.LargeIcon = Get-M365DSCIntuneAppLargeIconAsString -LargeIcon $Results.LargeIcon - } - else + if ($null -ne $Results.Assignments) { - $Results.Remove('LargeIcon') | Out-Null - } + if ($Results.Assignments) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.Assignments ` + -CIMInstanceName DeviceManagementMobileAppAssignment + if ($complexTypeStringResult) + { + $Results.Assignments = $complexTypeStringResult + } + else + { + $Results.Remove('Assignments') | Out-Null + } + } + } #endregion complex types $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` @@ -1054,49 +1048,25 @@ function Export-TargetResource -Credential $Credential #region complex types - - #Categories if ($null -ne $Results.Categories) { - $isCIMArray = $false - if ($Results.Categories.getType().Fullname -like '*[[\]]') - { - $isCIMArray = $true - } - - $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Categories' -IsCIMArray:$isCIMArray - } - - #ExcludedApps - if ($null -ne $Results.excludedApps) - { - $isCIMArray = $false - if ($Results.excludedApps.getType().Fullname -like '*[[\]]') - { - $isCIMArray = $true - } - - $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'ExcludedApps' -IsCIMArray:$isCIMArray + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Categories' -IsCIMArray:$true } - #Assignments - if ($null -ne $Results.Assignments) + if ($null -ne $Results.ExcludedApps) { - $isCIMArray = $false - if ($Results.Assignments.getType().Fullname -like '*[[\]]') - { - $isCIMArray = $true - } - - $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Assignments' -IsCIMArray:$isCIMArray + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'ExcludedApps' -IsCIMArray:$true } - #LargeIcon if ($null -ne $Results.LargeIcon) { $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'LargeIcon' -IsCIMArray:$false } + if ($null -ne $Results.Assignments) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Assignments' -IsCIMArray:$true + } #endregion complex types $dscContent += $currentDSCBlock @@ -1122,169 +1092,4 @@ function Export-TargetResource } } -#region Helper functions - -function Convert-ObjectArrayToHashtable { - param ( - [Parameter(Mandatory = $true)] - [System.Object[]] - $InputArray - ) - $outputHashTable = @{} - foreach ($element in $InputArray) { - if ($element -is [System.Collections.Hashtable]) { - $outputHashTable += $element - } - } - return $outputHashTable -} - -function Get-M365DSCIntuneAppCategoriesAsString -{ - [CmdletBinding()] - [OutputType([System.String])] - param( - [Parameter(Mandatory = $true)] - [System.Object[]] - $Categories - ) - - $StringContent = '@(' - $space = ' ' - $indent = ' ' - - $i = 1 - foreach ($category in $Categories) - { - if ($Categories.Count -gt 1) - { - $StringContent += "`r`n" - $StringContent += "$space" - } - - #Only export the displayName, not Id - $StringContent += "MSFT_DeviceManagementMobileAppCategory { `r`n" - $StringContent += "$($space)$($indent)displayName = '" + $category.displayName + "'`r`n" - $StringContent += "$space}" - - $i++ - } - - $StringContent += ')' - - return $StringContent -} - -function Get-M365DSCIntuneAppExcludedAppsAsString -{ - [CmdletBinding()] - [OutputType([System.String])] - param( - [Parameter(Mandatory = $true)] - [System.Object] - $ExcludedApps - ) - - # Create the embedded instance for ExcludedApps - $StringContent = "MSFT_DeviceManagementMobileAppExcludedApp {" - foreach ($key in $ExcludedApps.Keys) { - $value = if ($ExcludedApps[$key]) { '$true' } else { '$false' } - $StringContent += "`n $key = $value;" - } - $StringContent += "`n}" - - return $StringContent -} - -function Get-M365DSCIntuneMobileWindowsOfficeSuiteAppAdditionalProperties { - [CmdletBinding()] - [OutputType([System.Collections.Hashtable])] - param ( - [Parameter(Mandatory = $true)] - [System.Collections.Hashtable] $Properties - ) - - # Define the list of additional properties to include in the final payload - $additionalProperties = @('AutoAcceptEula', 'ExcludedApps') - - # Initialize a hashtable to store the additional properties - $results = @{'@odata.type' = '#microsoft.graph.officeSuiteApp'} - - # Loop through and process each property based on its type - foreach ($property in $Properties.Keys) { - if ($property -in $additionalProperties) { - $propertyName = $property.Substring(0, 1).ToLower() + $property.Substring(1) - $propertyValue = $Properties.$property - - # Handle ExcludedApps as a hashtable with camelCase properties - if ($propertyName -eq 'excludedApps' -and $propertyValue -is [System.Array]) { - $formattedExcludedApps = @{} - - # Iterate over each CIMInstance object and extract the Name/Value pairs, converting to camelCase - foreach ($app in $propertyValue) { - foreach ($instanceProperty in $app.CimInstanceProperties) { - $camelCaseKey = $instanceProperty.Name.Substring(0, 1).ToLower() + $instanceProperty.Name.Substring(1) - $formattedExcludedApps[$camelCaseKey] = $instanceProperty.Value - } - } - - # Add the formatted ExcludedApps to results - $results[$propertyName] = $formattedExcludedApps - } else { - # For simple types like Boolean (AutoAcceptEula), add directly - $results[$propertyName] = $propertyValue - } - } - } - return $results -} - -function Get-M365DSCIntuneAppLargeIconAsString #Get and Export -{ - [CmdletBinding()] - [OutputType([System.String])] - param( - [Parameter(Mandatory = $true)] - [System.Object] - $LargeIcon - ) - - $space = ' ' - $indent = ' ' - - if ($null -ne $LargeIcon.Value) - { - $StringContent += "`r`n" - $StringContent += "$space" - - $base64String = [System.Convert]::ToBase64String($LargeIcon.Value) # This exports the base64 string (blob) of the byte array, same as we see in Graph API response - - $StringContent += "MSFT_DeviceManagementMimeContent { `r`n" - $StringContent += "$($space)$($indent)type = '" + $LargeIcon.Type + "'`r`n" - $StringContent += "$($space)$($indent)value = '" + $base64String + "'`r`n" - $StringContent += "$space}" - } - - return $StringContent - } - -function ConvertTo-M365DSCIntuneAppLargeIcon #set -{ - [OutputType([System.Object])] - param( - [Parameter(Mandatory = $true)] - [System.Object] - $LargeIcon - ) - - $result = @{ - type = $LargeIcon.Type - value = $iconValue - } - - return $result -} - -#endregion Helper functions - Export-ModuleMember -Function *-TargetResource From 3dcd4d0d99d9426b5023ef195fc9fc59eabc7e98 Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Sun, 13 Oct 2024 12:25:43 -0700 Subject: [PATCH 198/252] change to cim instance not cim instance [] --- ...IntuneMobileAppsWindowsOfficeSuiteApp.psm1 | 69 +++++++------------ 1 file changed, 24 insertions(+), 45 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 index 16a0858546..b5d33dcc05 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 @@ -65,7 +65,7 @@ function Get-TargetResource $ProductIds, [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance[]] + [Microsoft.Management.Infrastructure.CimInstance] $ExcludedApps, [Parameter()] @@ -221,22 +221,12 @@ function Get-TargetResource $complexCategories += $myCategory } - $complexExcludedApps = [ordered]@{ - "access" = $instance.AdditionalProperties.excludedApps["access"] - "bing" = $instance.AdditionalProperties.excludedApps["bing"] - "excel" = $instance.AdditionalProperties.excludedApps["excel"] - "groove" = $instance.AdditionalProperties.excludedApps["groove"] - "infoPath" = $instance.AdditionalProperties.excludedApps["infoPath"] - "lync" = $instance.AdditionalProperties.excludedApps["lync"] - "oneDrive" = $instance.AdditionalProperties.excludedApps["oneDrive"] - "oneNote" = $instance.AdditionalProperties.excludedApps["oneNote"] - "outlook" = $instance.AdditionalProperties.excludedApps["outlook"] - "powerPoint" = $instance.AdditionalProperties.excludedApps["powerPoint"] - "publisher" = $instance.AdditionalProperties.excludedApps["publisher"] - "sharePointDesigner" = $instance.AdditionalProperties.excludedApps["sharePointDesigner"] - "teams" = $instance.AdditionalProperties.excludedApps["teams"] - "visio" = $instance.AdditionalProperties.excludedApps["visio"] - "word" = $instance.AdditionalProperties.excludedApps["word"] + $complexExcludedApps = [ordered]@{} + if ($null -ne $instance.AdditionalProperties.excludedApps) { + foreach ($property in $instance.AdditionalProperties.excludedApps.CimInstanceProperties) { + $camelCaseName = $property.Name.Substring(0, 1).ToLower() + $property.Name.Substring(1) + $complexExcludedApps[$camelCaseName] = $property.Value + } } $complexLargeIcon = @{} @@ -383,7 +373,7 @@ function Set-TargetResource $ProductIds, [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance[]] + [Microsoft.Management.Infrastructure.CimInstance] $ExcludedApps, [Parameter()] @@ -560,35 +550,24 @@ function Set-TargetResource Write-Host "Initial ExcludedApps Data:" $ExcludedApps if ($UpdateParameters.ContainsKey('ExcludedApps')) { - # Convert ExcludedApps into an ordered hashtable using the same pattern as in the helper functions - $excludedAppsDict = [ordered]@{} - - # Define the list of known apps to exclude - $excludedAppsKeys = @( - 'access', 'bing', 'excel', 'groove', 'infoPath', 'lync', - 'oneDrive', 'oneNote', 'outlook', 'powerPoint', 'publisher', - 'sharePointDesigner', 'teams', 'visio', 'word' - ) - - # Loop through the known app keys and dynamically populate the dictionary - foreach ($key in $excludedAppsKeys) { - if ($AdditionalProperties['excludedApps'].ContainsKey($key)) { - $excludedAppsDict[$key] = $AdditionalProperties['excludedApps'][$key] - } else { - # Set default values for each key if not explicitly provided - if ($key -in @('groove', 'infoPath', 'lync', 'sharePointDesigner')) { - $excludedAppsDict[$key] = $true - } else { - $excludedAppsDict[$key] = $false - } + if ($ExcludedApps -ne $null) { + $excludedAppsDict = [ordered]@{} + + foreach ($property in $ExcludedApps.CimInstanceProperties) { + $camelCaseName = $property.Name.Substring(0, 1).ToLower() + $property.Name.Substring(1) + $excludedAppsDict[$camelCaseName] = $property.Value } - } - # Convert to JSON before sending to the API - $excludedAppsJson = $excludedAppsDict | ConvertTo-Json -Depth 3 + # Convert the hashtable to a dictionary for API submission + $excludedAppsDictTyped = [System.Collections.Generic.Dictionary[string, bool]]::new() + foreach ($key in $excludedAppsDict.Keys) { + $excludedAppsDictTyped.Add($key, $excludedAppsDict[$key]) + } - # Add this JSON to your parameters for the API - $UpdateParameters['excludedApps'] = $excludedAppsJson + $UpdateParameters['excludedApps'] = $excludedAppsDictTyped + } else { + Write-Host "ExcludedApps is null." + } } else { Write-Host "ExcludedApps parameter not found in UpdateParameters." } @@ -710,7 +689,7 @@ function Test-TargetResource $ProductIds, [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance[]] + [Microsoft.Management.Infrastructure.CimInstance] $ExcludedApps, [Parameter()] From 5d170dab17c0af29182eb1e104dc5705a7e79a84 Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Sun, 13 Oct 2024 12:43:29 -0700 Subject: [PATCH 199/252] not working excluded apps without dictionary conversion --- ...IntuneMobileAppsWindowsOfficeSuiteApp.psm1 | 57 +++++++++++-------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 index b5d33dcc05..8b9a78e64e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 @@ -221,13 +221,13 @@ function Get-TargetResource $complexCategories += $myCategory } - $complexExcludedApps = [ordered]@{} - if ($null -ne $instance.AdditionalProperties.excludedApps) { - foreach ($property in $instance.AdditionalProperties.excludedApps.CimInstanceProperties) { - $camelCaseName = $property.Name.Substring(0, 1).ToLower() + $property.Name.Substring(1) - $complexExcludedApps[$camelCaseName] = $property.Value - } - } + # $complexExcludedApps = [ordered]@{} + # if ($null -ne $instance.AdditionalProperties.excludedApps) { + # foreach ($property in $instance.AdditionalProperties.excludedApps.CimInstanceProperties) { + # $camelCaseName = $property.Name.Substring(0, 1).ToLower() + $property.Name.Substring(1) + # $complexExcludedApps[$camelCaseName] = $property.Value + # } + # } $complexLargeIcon = @{} if ($null -ne $instance.LargeIcon.Value) @@ -261,7 +261,7 @@ function Get-TargetResource UpdateVersion = $instance.AdditionalProperties.updateVersion OfficeConfigurationXml = $instance.AdditionalProperties.officeConfigurationXml LargeIcon = $complexLargeIcon - ExcludedApps = $complexExcludedApps + ExcludedApps = $instance.AdditionalProperties.excludedApps Categories = $complexCategories Ensure = 'Present' Credential = $Credential @@ -549,27 +549,36 @@ function Set-TargetResource $UpdateParameters.Remove('RoleScopeTagIds') | Out-Null Write-Host "Initial ExcludedApps Data:" $ExcludedApps + # if ($UpdateParameters.ContainsKey('ExcludedApps')) { + # if ($ExcludedApps -ne $null) { + # $excludedAppsDict = [ordered]@{} + + # foreach ($property in $ExcludedApps.CimInstanceProperties) { + # $camelCaseName = $property.Name.Substring(0, 1).ToLower() + $property.Name.Substring(1) + # $excludedAppsDict[$camelCaseName] = $property.Value + # } + + # # Convert the hashtable to a dictionary for API submission + # $excludedAppsDictTyped = [System.Collections.Generic.Dictionary[string, bool]]::new() + # foreach ($key in $excludedAppsDict.Keys) { + # $excludedAppsDictTyped.Add($key, $excludedAppsDict[$key]) + # } + + # $UpdateParameters['excludedApps'] = $excludedAppsDictTyped + # } else { + # Write-Host "ExcludedApps is null." + # } + # } else { + # Write-Host "ExcludedApps parameter not found in UpdateParameters." + # } + if ($UpdateParameters.ContainsKey('ExcludedApps')) { if ($ExcludedApps -ne $null) { - $excludedAppsDict = [ordered]@{} - - foreach ($property in $ExcludedApps.CimInstanceProperties) { - $camelCaseName = $property.Name.Substring(0, 1).ToLower() + $property.Name.Substring(1) - $excludedAppsDict[$camelCaseName] = $property.Value - } - - # Convert the hashtable to a dictionary for API submission - $excludedAppsDictTyped = [System.Collections.Generic.Dictionary[string, bool]]::new() - foreach ($key in $excludedAppsDict.Keys) { - $excludedAppsDictTyped.Add($key, $excludedAppsDict[$key]) - } - - $UpdateParameters['excludedApps'] = $excludedAppsDictTyped + # Directly assign the CimInstance to the UpdateParameters without converting + $UpdateParameters['excludedApps'] = $ExcludedApps } else { Write-Host "ExcludedApps is null." } - } else { - Write-Host "ExcludedApps parameter not found in UpdateParameters." } # Print the entire UpdateParameters being sent to the API From 9cd3671de0fa4926a3c0fb8dff4cf2210260be68 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 14 Oct 2024 08:50:32 -0400 Subject: [PATCH 200/252] TeamsUpgradePolicy - Added support for tenant wide --- CHANGELOG.md | 3 +++ .../MSFT_TeamsUpgradePolicy.psm1 | 18 +++++++++++++++--- .../MSFT_TeamsUpgradePolicy.schema.mof | 2 +- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b6d19afb3..96235bb179 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,9 @@ * Initial release. * PPPowerAppPolicyUrlPatterns * Initial release. +* TeamsUpgradePolicy + * Added support for tenant wide changes using the * value for users. + FIXES [#5174](https://github.com/microsoft/Microsoft365DSC/issues/5174) * M365DSCDRGUtil * Fixes an issue for the handling of skipped one-property elements in the Settings Catalog. FIXES [#5086](https://github.com/microsoft/Microsoft365DSC/issues/5086) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsUpgradePolicy/MSFT_TeamsUpgradePolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsUpgradePolicy/MSFT_TeamsUpgradePolicy.psm1 index 1bc09914bf..20ecfd0716 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsUpgradePolicy/MSFT_TeamsUpgradePolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsUpgradePolicy/MSFT_TeamsUpgradePolicy.psm1 @@ -175,10 +175,22 @@ function Set-TargetResource $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftTeams' ` -InboundParameters $PSBoundParameters - foreach ($user in $Users) + if ($Identity -eq 'Global' -and $Users.Length -eq 1 -and $Users[0] -eq '*') { - Write-Verbose -Message "Granting TeamsUpgradePolicy {$Identity} to User {$user} with MigrateMeetingsToTeams=$MigrateMeetingsToTeams" - Grant-CsTeamsUpgradePolicy -PolicyName $Identity -Identity $user -MigrateMeetingsToTeams:$MigrateMeetingsToTeams + Write-Verbose -Message "Granting TeamsUpgradePolicy {$Identity} to all Users with MigrateMeetingsToTeams=$MigrateMeetingsToTeams" + Grant-CsTeamsUpgradePolicy -PolicyName $Identity ` + -MigrateMeetingsToTeams:$MigrateMeetingsToTeams ` + -Global + } + else + { + foreach ($user in $Users) + { + Write-Verbose -Message "Granting TeamsUpgradePolicy {$Identity} to User {$user} with MigrateMeetingsToTeams=$MigrateMeetingsToTeams" + Grant-CsTeamsUpgradePolicy -PolicyName $Identity ` + -Identity $user ` + -MigrateMeetingsToTeams:$MigrateMeetingsToTeams + } } } diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsUpgradePolicy/MSFT_TeamsUpgradePolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsUpgradePolicy/MSFT_TeamsUpgradePolicy.schema.mof index 96c8e8e81a..dcd1b3df49 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsUpgradePolicy/MSFT_TeamsUpgradePolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsUpgradePolicy/MSFT_TeamsUpgradePolicy.schema.mof @@ -2,7 +2,7 @@ class MSFT_TeamsUpgradePolicy : OMI_BaseResource { [Key, Description("Identity of the Teams Upgrade Policy.")] String Identity; - [Write, Description("List of users that will be granted the Upgrade Policy to.")] String Users[]; + [Write, Description("List of users that will be granted the Upgrade Policy to. Use value * to apply the policy globally.")] String Users[]; [Write, Description("Specifies whether to move existing Skype for Business meetings organized by the user to Teams. This parameter can only be true if the mode of the specified policy instance is either TeamsOnly or SfBWithTeamsCollabAndMeetings, and if the policy instance is being granted to a specific user. It not possible to trigger meeting migration when granting TeamsUpgradePolicy to the entire tenant.")] Boolean MigrateMeetingsToTeams; [Write, Description("Credentials of the Teams Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; From c5f39d4a8632e06b953723d3c0e368334ba5870c Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 14 Oct 2024 13:45:13 +0000 Subject: [PATCH 201/252] Updated Resources and Cmdlet documentation pages --- .../resources/intune/IntuneAppCategory.md | 2 +- .../intune/IntuneDerivedCredential.md | 150 ++++++++++++++++++ .../intune/IntuneMobileAppsMacOSLobApp.md | 11 +- 3 files changed, 157 insertions(+), 6 deletions(-) create mode 100644 docs/docs/resources/intune/IntuneDerivedCredential.md diff --git a/docs/docs/resources/intune/IntuneAppCategory.md b/docs/docs/resources/intune/IntuneAppCategory.md index 062055e54c..99193c9196 100644 --- a/docs/docs/resources/intune/IntuneAppCategory.md +++ b/docs/docs/resources/intune/IntuneAppCategory.md @@ -4,7 +4,7 @@ | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | -| **DisplayName** | Key | String | The name of the app category. | | +| **DisplayName** | Key | String | The name of the app. | | | **Id** | Write | String | The unique identifier for an entity. Read-only. | | | **Ensure** | Write | String | Present ensures the instance exists, absent ensures it is removed. | `Present`, `Absent` | | **Credential** | Write | PSCredential | Credentials of the workload's Admin | | diff --git a/docs/docs/resources/intune/IntuneDerivedCredential.md b/docs/docs/resources/intune/IntuneDerivedCredential.md new file mode 100644 index 0000000000..c43b79bec9 --- /dev/null +++ b/docs/docs/resources/intune/IntuneDerivedCredential.md @@ -0,0 +1,150 @@ +# IntuneDerivedCredential + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **DisplayName** | Key | String | The name of the app category. | | +| **Id** | Write | String | The unique identifier for an entity. Read-only. | | +| **HelpUrl** | Write | String | The URL that will be accessible to end users as they retrieve a derived credential using the Company Portal. | | +| **RenewalThresholdPercentage** | Write | UInt32 | The nominal percentage of time before certificate renewal is initiated by the client. | | +| **Issuer** | Write | String | Supported values for the derived credential issuer. | `intercede`, `entrustDatacard`, `purebred` | +| **NotificationType** | Write | String | Supported values for the notification type to use. | `none`, `email`, `companyPortal` | +| **Ensure** | Write | String | Supported values for the notification type to use. | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials of the Intune Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | +| **ApplicationSecret** | Write | PSCredential | Secret of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +## Create new navigation property to derivedCredentials for deviceManagement for Intune. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - None + +- **Update** + + - None + +## Examples + +### Example 1 + + +```powershell +Configuration Example { + param( + [Parameter()] + [System.String] $ApplicationId, + + [Parameter()] + [System.String] $TenantId, + + [Parameter()] + [System.String] $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + + node localhost { + IntuneDerivedCredential "IntuneDerivedCredential-K5" + { + DisplayName = "K5"; + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; + Ensure = "Present"; + } + } +} +``` + +### Example 2 + + +```powershell +Configuration Example { + param( + [Parameter()] + [System.String] $ApplicationId, + + [Parameter()] + [System.String] $TenantId, + + [Parameter()] + [System.String] $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + + node localhost { + IntuneDerivedCredential "IntuneDerivedCredential-K5" + { + DisplayName = "K5"; + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; + Ensure = "Present"; + } + } +} +``` + +### Example 3 + + +```powershell +Configuration Example { + param( + [Parameter()] + [System.String] $ApplicationId, + + [Parameter()] + [System.String] $TenantId, + + [Parameter()] + [System.String] $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + + node localhost { + IntuneDerivedCredential "IntuneDerivedCredential-K5" + { + DisplayName = "K5"; + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; + Ensure = "Absent"; + } + } +} +``` + diff --git a/docs/docs/resources/intune/IntuneMobileAppsMacOSLobApp.md b/docs/docs/resources/intune/IntuneMobileAppsMacOSLobApp.md index 42df970079..cdb64c20a7 100644 --- a/docs/docs/resources/intune/IntuneMobileAppsMacOSLobApp.md +++ b/docs/docs/resources/intune/IntuneMobileAppsMacOSLobApp.md @@ -14,12 +14,12 @@ | **Owner** | Write | String | The owner of the app. Inherited from mobileApp. | | | **PrivacyInformationUrl** | Write | String | The privacy statement Url. Inherited from mobileApp. | | | **Publisher** | Write | String | The publisher of the app. Inherited from mobileApp. | | +| **PublishingState** | Write | String | The publishing state for the app. The app cannot be assigned unless the app is published. Inherited from mobileApp. | `notPublished`, `processing`, `published` | | **BundleId** | Write | String | The bundleId of the app. | | | **BuildNumber** | Write | String | The build number of the app. | | | **VersionNumber** | Write | String | The version number of the app. | | | **RoleScopeTagIds** | Write | StringArray[] | List of Scope Tag IDs for mobile app. | | | **IgnoreVersionDetection** | Write | Boolean | Whether to ignore the version of the app or not. | | -| **InstallAsManaged** | Write | Boolean | Install the app as managed. Requires macOS 11.0. | | | **LargeIcon** | Write | MSFT_DeviceManagementMimeContent | The icon for this app. | | | **MinimumSupportedOperatingSystem** | Write | MSFT_DeviceManagementMinimumOperatingSystem | The minimum supported operating system to install the app. | | | **Categories** | Write | MSFT_DeviceManagementMobileAppCategory[] | The list of categories for this app. | | @@ -170,7 +170,7 @@ Configuration Example PrivacyInformationUrl = ""; Publisher = "Contoso"; Assignments = @( - MSFT_DeviceManagementMobileAppAssignment{ + MSFT_DeviceManagementMobileAppAssignment { groupDisplayName = 'All devices' deviceAndAppManagementAssignmentFilterType = 'none' dataType = '#microsoft.graph.allDevicesAssignmentTarget' @@ -234,14 +234,15 @@ Configuration Example Owner = ""; PrivacyInformationUrl = ""; Publisher = "Contoso"; - Assignments = @( - MSFT_DeviceManagementMobileAppAssignment{ + PublishingState = "published"; + Assignments = @( + MSFT_DeviceManagementMobileAppAssignment { groupDisplayName = 'All devices' deviceAndAppManagementAssignmentFilterType = 'none' dataType = '#microsoft.graph.allDevicesAssignmentTarget' intent = 'required' } - MSFT_DeviceManagementMobileAppAssignment{ + MSFT_DeviceManagementMobileAppAssignment { deviceAndAppManagementAssignmentFilterType = 'none' dataType = '#microsoft.graph.groupAssignmentTarget' groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' From f7fd425d04141e6e45efbd523fa9474b5a8e73da Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 14 Oct 2024 13:48:02 +0000 Subject: [PATCH 202/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 85 +++++++++++++++++-- 1 file changed, 80 insertions(+), 5 deletions(-) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 4844f64a3c..b405f20354 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -21849,6 +21849,81 @@ } ] }, + { + "ClassName": "MSFT_IntuneDerivedCredential", + "Parameters": [ + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "Id", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "HelpUrl", + "Option": "Write" + }, + { + "CIMType": "Uint32", + "Name": "RenewalThresholdPercentage", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Issuer", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "NotificationType", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "ApplicationSecret", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_IntuneDeviceAndAppManagementAssignmentFilter", "Parameters": [ @@ -35882,6 +35957,11 @@ "Name": "Publisher", "Option": "Write" }, + { + "CIMType": "String", + "Name": "PublishingState", + "Option": "Write" + }, { "CIMType": "String", "Name": "BundleId", @@ -35907,11 +35987,6 @@ "Name": "IgnoreVersionDetection", "Option": "Write" }, - { - "CIMType": "Boolean", - "Name": "InstallAsManaged", - "Option": "Write" - }, { "CIMType": "MSFT_DeviceManagementMimeContent", "Name": "LargeIcon", From e068f8f8c69866844085e1521ddfb4dad9f3e7f6 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 14 Oct 2024 13:48:16 +0000 Subject: [PATCH 203/252] Updated {Create} Intune Integration Tests --- .../M365DSCIntegration.INTUNE.Create.Tests.ps1 | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 index 26e65f5d12..dadb7d572a 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 @@ -305,6 +305,15 @@ TenantId = $TenantId; CertificateThumbprint = $CertificateThumbprint; } + IntuneDerivedCredential 'IntuneDerivedCredential-K5' + { + DisplayName = "K5"; + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; + Ensure = "Present"; + } IntuneDeviceAndAppManagementAssignmentFilter 'AssignmentFilter' { DisplayName = 'Test Device Filter' @@ -2542,7 +2551,7 @@ PrivacyInformationUrl = ""; Publisher = "Contoso"; Assignments = @( - MSFT_DeviceManagementMobileAppAssignment{ + MSFT_DeviceManagementMobileAppAssignment { groupDisplayName = 'All devices' deviceAndAppManagementAssignmentFilterType = 'none' dataType = '#microsoft.graph.allDevicesAssignmentTarget' From 0b9f328f10f37a14d33f6add64092010ef76f6cf Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Mon, 14 Oct 2024 08:27:41 -0700 Subject: [PATCH 204/252] fix for excluded apps --- ...IntuneMobileAppsWindowsOfficeSuiteApp.psm1 | 125 +++--------------- ...MobileAppsWindowsOfficeSuiteApp.schema.mof | 6 +- 2 files changed, 23 insertions(+), 108 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 index 8b9a78e64e..ad4600d8fe 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 @@ -18,10 +18,6 @@ function Get-TargetResource [System.String] $Description, - [Parameter()] - [System.String] - $Publisher, - [Parameter()] [System.Boolean] $IsFeatured, @@ -34,23 +30,10 @@ function Get-TargetResource [System.String] $InformationUrl, - [Parameter()] - [System.String] - $Owner, - - [Parameter()] - [System.String] - $Developer, - [Parameter()] [System.String] $Notes, - [Parameter()] - [System.String] - [ValidateSet('notPublished', 'processing','published')] - $PublishingState, - [Parameter()] [System.String[]] $RoleScopeTagIds, @@ -221,13 +204,13 @@ function Get-TargetResource $complexCategories += $myCategory } - # $complexExcludedApps = [ordered]@{} - # if ($null -ne $instance.AdditionalProperties.excludedApps) { - # foreach ($property in $instance.AdditionalProperties.excludedApps.CimInstanceProperties) { - # $camelCaseName = $property.Name.Substring(0, 1).ToLower() + $property.Name.Substring(1) - # $complexExcludedApps[$camelCaseName] = $property.Value - # } - # } + $complexExcludedApps = @{} + if ($null -ne $instance.AdditionalProperties.excludedApps) + { + $instance.AdditionalProperties.excludedApps.GetEnumerator() | Foreach-Object { + $complexExcludedApps.Add($_.Key, $_.Value) + } + } $complexLargeIcon = @{} if ($null -ne $instance.LargeIcon.Value) @@ -240,12 +223,9 @@ function Get-TargetResource Id = $instance.Id DisplayName = $instance.DisplayName Description = $instance.Description - Publisher = $instance.Publisher IsFeatured = $instance.IsFeatured PrivacyInformationUrl = $instance.PrivacyInformationUrl InformationUrl = $instance.InformationUrl - Owner = $instance.Owner - Developer = $instance.Developer Notes = $instance.Notes RoleScopeTagIds = $instance.RoleScopeTagIds AutoAcceptEula = $instance.AdditionalProperties.autoAcceptEula @@ -261,7 +241,7 @@ function Get-TargetResource UpdateVersion = $instance.AdditionalProperties.updateVersion OfficeConfigurationXml = $instance.AdditionalProperties.officeConfigurationXml LargeIcon = $complexLargeIcon - ExcludedApps = $instance.AdditionalProperties.excludedApps + ExcludedApps = $complexExcludedApps Categories = $complexCategories Ensure = 'Present' Credential = $Credential @@ -326,10 +306,6 @@ function Set-TargetResource [System.String] $Description, - [Parameter()] - [System.String] - $Publisher, - [Parameter()] [System.Boolean] $IsFeatured, @@ -342,23 +318,10 @@ function Set-TargetResource [System.String] $InformationUrl, - [Parameter()] - [System.String] - $Owner, - - [Parameter()] - [System.String] - $Developer, - [Parameter()] [System.String] $Notes, - [Parameter()] - [System.String] - [ValidateSet('notPublished', 'processing','published')] - $PublishingState, - [Parameter()] [System.String[]] $RoleScopeTagIds, @@ -492,6 +455,9 @@ function Set-TargetResource $CreateParameters = Rename-M365DSCCimInstanceParameter -Properties $CreateParameters $CreateParameters.Remove('Id') | Out-Null $CreateParameters.Remove('Categories') | Out-Null + $CreateParameters.Add('Publisher', 'Microsoft') + $CreateParameters.Add('Developer', 'Microsoft') + $CreateParameters.Add('Owner', 'Microsoft') foreach ($key in ($CreateParameters.Clone()).Keys) { @@ -508,7 +474,7 @@ function Set-TargetResource { if ($category.Id) { - $currentCategory = Get-MgBetaDeviceAppManagementMobileAppCategory -CategoryId $category.Id + $currentCategory = Get-MgBetaDeviceAppManagementMobileAppCategory -MobileAppCategoryId $category.Id } else { @@ -520,7 +486,7 @@ function Set-TargetResource throw "Mobile App Category with DisplayName $($category.DisplayName) not found." } - Invoke-MgBetaGraphRequest -Uri "/beta/deviceAppManagement/mobileApps/$($app.Id)/categories/`$ref" -Method 'POST' -Body @{ + Invoke-MgGraphRequest -Uri "/beta/deviceAppManagement/mobileApps/$($app.Id)/categories/`$ref" -Method 'POST' -Body @{ '@odata.id' = "https://graph.microsoft.com/beta/deviceAppManagement/mobileAppCategories/$($currentCategory.Id)" } } @@ -543,47 +509,16 @@ function Set-TargetResource $UpdateParameters.Remove('Id') | Out-Null $UpdateParameters.Remove('Categories') | Out-Null $UpdateParameters.Remove('OfficePlatformArchitecture') | Out-Null - $UpdateParameters.Remove('Developer') | Out-Null - $UpdateParameters.Remove('Owner') | Out-Null - $UpdateParameters.Remove('Publisher') | Out-Null - $UpdateParameters.Remove('RoleScopeTagIds') | Out-Null - Write-Host "Initial ExcludedApps Data:" $ExcludedApps - - # if ($UpdateParameters.ContainsKey('ExcludedApps')) { - # if ($ExcludedApps -ne $null) { - # $excludedAppsDict = [ordered]@{} - - # foreach ($property in $ExcludedApps.CimInstanceProperties) { - # $camelCaseName = $property.Name.Substring(0, 1).ToLower() + $property.Name.Substring(1) - # $excludedAppsDict[$camelCaseName] = $property.Value - # } - - # # Convert the hashtable to a dictionary for API submission - # $excludedAppsDictTyped = [System.Collections.Generic.Dictionary[string, bool]]::new() - # foreach ($key in $excludedAppsDict.Keys) { - # $excludedAppsDictTyped.Add($key, $excludedAppsDict[$key]) - # } - - # $UpdateParameters['excludedApps'] = $excludedAppsDictTyped - # } else { - # Write-Host "ExcludedApps is null." - # } - # } else { - # Write-Host "ExcludedApps parameter not found in UpdateParameters." - # } - - if ($UpdateParameters.ContainsKey('ExcludedApps')) { - if ($ExcludedApps -ne $null) { - # Directly assign the CimInstance to the UpdateParameters without converting - $UpdateParameters['excludedApps'] = $ExcludedApps - } else { - Write-Host "ExcludedApps is null." + + foreach ($key in ($UpdateParameters.Clone()).Keys) + { + if ($null -ne $UpdateParameters.$key -and $UpdateParameters.$key.GetType().Name -like '*CimInstance*') + { + $UpdateParameters.$key = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $UpdateParameters.$key } } - # Print the entire UpdateParameters being sent to the API - Write-Host "Now ExcludedApps Data:" $UpdateParameters['excludedApps'] - + $UpdateParameters.Add('@odata.type', '#microsoft.graph.officeSuiteApp') Update-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id -BodyParameter $UpdateParameters [array]$referenceObject = if ($null -ne $currentInstance.Categories.DisplayName) { $currentInstance.Categories.DisplayName } else { ,@() } @@ -651,10 +586,6 @@ function Test-TargetResource [System.String] $Description, - [Parameter()] - [System.String] - $Publisher, - [Parameter()] [System.Boolean] $IsFeatured, @@ -667,23 +598,10 @@ function Test-TargetResource [System.String] $InformationUrl, - [Parameter()] - [System.String] - $Owner, - - [Parameter()] - [System.String] - $Developer, - [Parameter()] [System.String] $Notes, - [Parameter()] - [System.String] - [ValidateSet('notPublished', 'processing','published')] - $PublishingState, - [Parameter()] [System.String[]] $RoleScopeTagIds, @@ -843,6 +761,7 @@ function Test-TargetResource $PSBoundParameters.Remove('LargeIcon') | Out-Null $ValuesToCheck.Remove('Id') | Out-Null + $ValuesToCheck.Remove('OfficePlatformArchitecture') | Out-Null # Cannot be changed after creation $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" @@ -1043,7 +962,7 @@ function Export-TargetResource if ($null -ne $Results.ExcludedApps) { - $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'ExcludedApps' -IsCIMArray:$true + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'ExcludedApps' -IsCIMArray:$false } if ($null -ne $Results.LargeIcon) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof index c91163da06..a21a984fca 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof @@ -46,14 +46,10 @@ class MSFT_IntuneMobileAppsWindowsOfficeSuiteApp : OMI_BaseResource [Write, Description("The unique identifier for an entity. Read-only. Inherited from mobileApp object.")] String Id; [Write, Description("The description of the app. Inherited from mobileApp.")] String Description; - [Write, Description("The publisher of the app. Inherited from mobileApp.")] String Publisher; [Write, Description("The value indicating whether the app is marked as featured by the admin. Inherited from mobileApp.")] Boolean IsFeatured; [Write, Description("The privacy statement Url. Inherited from mobileApp.")] String PrivacyInformationUrl; [Write, Description("The InformationUrl of the app. Inherited from mobileApp.")] String InformationUrl; - [Write, Description("The owner of the app. Inherited from mobileApp.")] String Owner; - [Write, Description("The dewveloper of the app. Inherited from mobileApp.")] String Developer; [Write, Description("Notes for the app. Inherited from mobileApp.")] String Notes; - [Write, Description("The publishing state for the app. The app cannot be assigned unless the app is published. Inherited from mobileApp."), ValueMap{"notPublished", "processing","published"}, Values{"notPublished", "processing", "published"}] String PublishingState; [Write, Description("List of Scope Tag IDs for mobile app.")] String RoleScopeTagIds[]; [Write, Description("The icon for this app."), EmbeddedInstance("MSFT_DeviceManagementMimeContent")] String LargeIcon; [Write, Description("Specifies if the EULA is accepted automatically on the end user's device.")] Boolean AutoAcceptEula; @@ -61,7 +57,7 @@ class MSFT_IntuneMobileAppsWindowsOfficeSuiteApp : OMI_BaseResource [Write, Description("Indicates whether shared computer activation is used for Office installations.")] Boolean UseSharedComputerActivation; [Write, Description("Specifies the update channel for the Office 365 app suite, such as 'Current' or 'Deferred'.")] String UpdateChannel; [Write, Description("Specifies the default file format type for Office apps, such as 'OfficeOpenXMLFormat' or 'OfficeOpenDocumentFormat'.")] String OfficeSuiteAppDefaultFileFormat; - [Write, Description("The architecture of the Office installation (e.g., 'X86', 'X64', or 'Arm64').")] String OfficePlatformArchitecture; + [Write, Description("The architecture of the Office installation (e.g., 'X86', 'X64', or 'Arm64'). Cannot be changed after creation.")] String OfficePlatformArchitecture; [Write, Description("Specifies the locales to be installed when the Office 365 apps are deployed. Uses the standard RFC 5646 format (e.g., 'en-US', 'fr-FR').")] String LocalesToInstall[]; [Write, Description("Specifies the display level of the installation progress for Office apps. Use 'Full' to display the installation UI, or 'None' for a silent installation.")] String InstallProgressDisplayLevel; [Write, Description("Indicates whether older versions of Office should be uninstalled when deploying the Office 365 app suite.")] Boolean ShouldUninstallOlderVersionsOfOffice; From 33cf7c8ace29bd68bebfbee2823129164dad0bbf Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Mon, 14 Oct 2024 08:59:03 -0700 Subject: [PATCH 205/252] remove large icon because not supported for office windows suite app --- ...IntuneMobileAppsWindowsOfficeSuiteApp.psm1 | 76 +++++++++---------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 index ad4600d8fe..f10634ed10 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.psm1 @@ -103,9 +103,9 @@ function Get-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $Assignments, - [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance] - $LargeIcon, + # [Parameter()] + # [Microsoft.Management.Infrastructure.CimInstance] + # $LargeIcon, #endregion @@ -212,12 +212,12 @@ function Get-TargetResource } } - $complexLargeIcon = @{} - if ($null -ne $instance.LargeIcon.Value) - { - $complexLargeIcon.Add('Value', [System.Convert]::ToBase64String($instance.LargeIcon.Value)) - $complexLargeIcon.Add('Type', $instance.LargeIcon.Type) - } + # $complexLargeIcon = @{} + # if ($null -ne $instance.LargeIcon.Value) + # { + # $complexLargeIcon.Add('Value', [System.Convert]::ToBase64String($instance.LargeIcon.Value)) + # $complexLargeIcon.Add('Type', $instance.LargeIcon.Type) + # } $results = @{ Id = $instance.Id @@ -240,7 +240,7 @@ function Get-TargetResource TargetVersion = $instance.AdditionalProperties.targetVersion UpdateVersion = $instance.AdditionalProperties.updateVersion OfficeConfigurationXml = $instance.AdditionalProperties.officeConfigurationXml - LargeIcon = $complexLargeIcon + # LargeIcon = $complexLargeIcon ExcludedApps = $complexExcludedApps Categories = $complexCategories Ensure = 'Present' @@ -391,9 +391,9 @@ function Set-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $Assignments, - [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance] - $LargeIcon, + # [Parameter()] + # [Microsoft.Management.Infrastructure.CimInstance] + # $LargeIcon, #endregion @@ -561,7 +561,7 @@ function Set-TargetResource } elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { - Write-Host "Remove the Intune MacOS Lob App with Id {$($currentInstance.Id)}" + Write-Host "Remove the Intune Windows Office Suite App with Id {$($currentInstance.Id)}" Remove-MgBetaDeviceAppManagementMobileApp -MobileAppId $currentInstance.Id -Confirm:$false } } @@ -671,9 +671,9 @@ function Test-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $Assignments, - [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance] - $LargeIcon, + # [Parameter()] + # [Microsoft.Management.Infrastructure.CimInstance] + # $LargeIcon, #endregion @@ -757,8 +757,8 @@ function Test-TargetResource # Prevent screen from filling up with the LargeIcon value # Comparison will already be done because it's a CimInstance - $CurrentValues.Remove('LargeIcon') | Out-Null - $PSBoundParameters.Remove('LargeIcon') | Out-Null + # $CurrentValues.Remove('LargeIcon') | Out-Null + # $PSBoundParameters.Remove('LargeIcon') | Out-Null $ValuesToCheck.Remove('Id') | Out-Null $ValuesToCheck.Remove('OfficePlatformArchitecture') | Out-Null # Cannot be changed after creation @@ -912,21 +912,21 @@ function Export-TargetResource } } - if ($null -ne $Results.LargeIcon) - { - $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` - -ComplexObject $Results.LargeIcon ` - -CIMInstanceName 'DeviceManagementMimeContent' - - if (-not [System.String]::IsNullOrWhiteSpace($complexTypeStringResult)) - { - $Results.LargeIcon = $complexTypeStringResult - } - else - { - $Results.Remove('LargeIcon') | Out-Null - } - } + # if ($null -ne $Results.LargeIcon) + # { + # $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + # -ComplexObject $Results.LargeIcon ` + # -CIMInstanceName 'DeviceManagementMimeContent' + + # if (-not [System.String]::IsNullOrWhiteSpace($complexTypeStringResult)) + # { + # $Results.LargeIcon = $complexTypeStringResult + # } + # else + # { + # $Results.Remove('LargeIcon') | Out-Null + # } + # } if ($null -ne $Results.Assignments) { @@ -965,10 +965,10 @@ function Export-TargetResource $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'ExcludedApps' -IsCIMArray:$false } - if ($null -ne $Results.LargeIcon) - { - $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'LargeIcon' -IsCIMArray:$false - } + # if ($null -ne $Results.LargeIcon) + # { + # $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'LargeIcon' -IsCIMArray:$false + # } if ($null -ne $Results.Assignments) { From daf2bd68a020a09a34290110efb2bd2cd9b0ec3b Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Mon, 14 Oct 2024 11:19:15 -0700 Subject: [PATCH 206/252] remove large icon from mof --- .../MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof index a21a984fca..9d07d216db 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp/MSFT_IntuneMobileAppsWindowsOfficeSuiteApp.schema.mof @@ -51,7 +51,6 @@ class MSFT_IntuneMobileAppsWindowsOfficeSuiteApp : OMI_BaseResource [Write, Description("The InformationUrl of the app. Inherited from mobileApp.")] String InformationUrl; [Write, Description("Notes for the app. Inherited from mobileApp.")] String Notes; [Write, Description("List of Scope Tag IDs for mobile app.")] String RoleScopeTagIds[]; - [Write, Description("The icon for this app."), EmbeddedInstance("MSFT_DeviceManagementMimeContent")] String LargeIcon; [Write, Description("Specifies if the EULA is accepted automatically on the end user's device.")] Boolean AutoAcceptEula; [Write, Description("The Product IDs that represent the Office 365 Suite SKU, such as 'O365ProPlusRetail' or 'VisioProRetail'.")] String ProductIds[]; [Write, Description("Indicates whether shared computer activation is used for Office installations.")] Boolean UseSharedComputerActivation; From f1ede66f6b51ee7195212bbde2e7231c5ba8d009 Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Mon, 14 Oct 2024 15:34:03 -0700 Subject: [PATCH 207/252] add tests --- ...eMobileAppsWindowsOfficeSuiteApp.Tests.ps1 | 261 ++++++++++++++---- 1 file changed, 208 insertions(+), 53 deletions(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 index 780e0f343d..189cbc3534 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 @@ -31,128 +31,262 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Confirm-M365DSCDependencies -MockWith { } + Mock -CommandName Get-PSSession -MockWith { + } + + Mock -CommandName Remove-PSSession -MockWith { + } + Mock -CommandName New-M365DSCConnection -MockWith { return "Credentials" } - ##TODO - Mock any Remove/Set/New cmdlets + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { + } + Mock -CommandName New-MgBetaDeviceAppManagementMobileApp -MockWith { + } + Mock -CommandName Update-MgBetaDeviceAppManagementMobileApp -MockWith { + } + Mock -CommandName Remove-MgBetaDeviceAppManagementMobileApp -MockWith { + } + + Mock -CommandName Update-MgBetaDeviceAppManagementMobileAppAssignment -MockWith{} # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { } + $Script:exportedInstances =$null $Script:ExportMode = $false } + # Test contexts - Context -Name "The instance should exist but it DOES NOT" -Fixture { + Context -Name "1. The instance should exist but it DOES NOT" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; + Id = "8d027f94-0682-431e-97c1-827d1879fa79" + Categories = @() + Description = "Microsoft 365 Apps for Windows 10 and later" + Developer = "Contoso" + DisplayName = "Microsoft 365 Apps for Windows 10 and later" + InformationUrl = "" + IsFeatured = $False + MinimumSupportedOperatingSystem = [CimInstance]( + New-CimInstance -ClassName MSFT_DeviceManagementMinimumOperatingSystem -Property @{ + v11_0 = $true + } -ClientOnly) + Notes = "" + Owner = "" + PrivacyInformationUrl = "" + Publisher = "Contoso" + RoleScopeTagIds = @() + Ensure = 'Present' + Credential = $Credential } - ##TODO - Mock the Get-Cmdlet to return $null - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { return $null } } - It 'Should return Values from the Get method' { + + It '1.1 Should return Values from the Get method' { (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' } - It 'Should return false from the Test method' { + It '1.2 Should return false from the Test method' { Test-TargetResource @testParams | Should -Be $false } - - It 'Should create a new instance from the Set method' { - ##TODO - Replace the New-Cmdlet by the appropriate one + It '1.3 Should create a new instance from the Set method' { Set-TargetResource @testParams - Should -Invoke -CommandName New-Cmdlet -Exactly 1 + Should -Invoke -CommandName New-MgBetaDeviceAppManagementMobileApp -Exactly 1 } } - Context -Name "The instance exists but it SHOULD NOT" -Fixture { + Context -Name "2. The instance exists but it SHOULD NOT" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Absent' - Credential = $Credential; + Id = "ad027f94-0682-431e-97c1-827d1879fa79" + Categories = @() + Description = "Microsoft 365 Apps for Windows 10 and later" + Developer = "Contoso" + DisplayName = "Microsoft 365 Apps for Windows 10 and later" + InformationUrl = "" + IsFeatured = $False + MinimumSupportedOperatingSystem = [CimInstance]( + New-CimInstance -ClassName MSFT_DeviceManagementMinimumOperatingSystem -Property @{ + v11_0 = $true + } -ClientOnly) + Notes = "" + Owner = "" + PrivacyInformationUrl = "" + Publisher = "Contoso" + RoleScopeTagIds = @() + IgnoreVersionDetection = $True + Ensure = 'Absent' + Credential = $Credential } - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { return @{ - + Id = "ad027f94-0682-431e-97c1-827d1879fa79" + Categories = @() + Description = "Microsoft 365 Apps for Windows 10 and laterr" + Developer = "Contoso" + DisplayName = "Microsoft 365 Apps for Windows 10 and later" + InformationUrl = "" + IsFeatured = $False + Notes = "" + Owner = "" + PrivacyInformationUrl = "" + Publisher = "Contoso" + PublishingState = "published" + RoleScopeTagIds = @() + IgnoreVersionDetection = $True + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.officeSuiteApp' + minimumSupportedOperatingSystem = @{ + v11_0 = $true + } + } + Ensure = 'Present' } } + + Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppAssignment -MockWith{ + return $null + } } - It 'Should return Values from the Get method' { + + It '2.1 Should return Values from the Get method' { (Get-TargetResource @testParams).Ensure | Should -Be 'Present' } - It 'Should return false from the Test method' { + It '2.2 Should return false from the Test method' { Test-TargetResource @testParams | Should -Be $false } - - It 'Should remove the instance from the Set method' { + It '2.3 Should remove the instance from the Set method' { Set-TargetResource @testParams - ##TODO - Replace the Remove-Cmdlet by the appropriate one - Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + Should -Invoke -CommandName Remove-MgBetaDeviceAppManagementMobileApp -Exactly 1 } } - Context -Name "The instance exists and values are already in the desired state" -Fixture { + Context -Name "3. The instance exists and values are already in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; + Id = "8d027f94-0682-431e-97c1-827d1879fa79" + Categories = @() + Description = "Microsoft 365 Apps for Windows 10 and later" + Developer = "Contoso" + DisplayName = "Microsoft 365 Apps for Windows 10 and later" + InformationUrl = "" + IsFeatured = $False + MinimumSupportedOperatingSystem = [CimInstance]( + New-CimInstance -ClassName MSFT_DeviceManagementMinimumOperatingSystem -Property @{ + v11_0 = $true + } -ClientOnly) + Notes = "" + Owner = "" + PrivacyInformationUrl = "" + Publisher = "Contoso" + RoleScopeTagIds = @() + Ensure = 'Present' + Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return the desired values - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { return @{ - + Id = "8d027f94-0682-431e-97c1-827d1879fa79" + Categories = @() + Description = "Microsoft 365 Apps for Windows 10 and later" + Developer = "Contoso" + DisplayName = "Microsoft 365 Apps for Windows 10 and later" + InformationUrl = "" + IsFeatured = $False + Notes = "" + Owner = "" + PrivacyInformationUrl = "" + Publisher = "Contoso" + PublishingState = "published" + RoleScopeTagIds = @() + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.officeSuiteApp' + minimumSupportedOperatingSystem = @{ + v11_0 = $true + } + } } } + Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppAssignment -MockWith{ + return $null + } } - It 'Should return true from the Test method' { + It '3.0 Should return true from the Test method' { Test-TargetResource @testParams | Should -Be $true } } - Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + Context -Name "4. The instance exists and values are NOT in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; + Id = "8d027f94-0682-431e-97c1-827d1879fa79" + Categories = @() + Description = "Microsoft 365 Apps for Windows 10 and later" + Developer = "Contoso" + DisplayName = "Microsoft 365 Apps for Windows 10 and later" + InformationUrl = "" + IsFeatured = $False + MinimumSupportedOperatingSystem = [CimInstance]( + New-CimInstance -ClassName MSFT_DeviceManagementMinimumOperatingSystem -Property @{ + v11_0 = $true + } -ClientOnly) + Notes = "" + Owner = "" + PrivacyInformationUrl = "" + Publisher = "Contoso" + RoleScopeTagIds = @() + Ensure = 'Present' + Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return a drift - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { return @{ - + Id = "8d027f94-0682-431e-97c1-827d1879fa79" + Categories = @() + Description = "Microsoft 365 Apps for Windows 10 and later" + Developer = "Contoso" + DisplayName = "Microsoft 365 Apps for Windows 10 and later drift" + InformationUrl = "" + IsFeatured = $False + Notes = "" + Owner = "" + PrivacyInformationUrl = "" + Publisher = "Contoso" + PublishingState = "published" + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.officeSuiteApp' + minimumSupportedOperatingSystem = @{ + v11_0 = $true + } + } } } + Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppAssignment -MockWith{ + return $null + } } - It 'Should return Values from the Get method' { + It '4.1 Should return Values from the Get method' { (Get-TargetResource @testParams).Ensure | Should -Be 'Present' } - - It 'Should return false from the Test method' { + It '4.2 Should return false from the Test method' { Test-TargetResource @testParams | Should -Be $false } - - It 'Should call the Set method' { + It '4.3 Should call the Set method' { Set-TargetResource @testParams - ##TODO - Replace the Update-Cmdlet by the appropriate one - Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + Should -Invoke -CommandName Update-MgBetaDeviceAppManagementMobileApp -Exactly 1 } } - Context -Name 'ReverseDSC Tests' -Fixture { + Context -Name '5. ReverseDSC Tests' -Fixture { BeforeAll { $Global:CurrentModeIsExport = $true $Global:PartialExportFileName = "$(New-Guid).partial.ps1" @@ -160,14 +294,35 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { return @{ - + Id = "8d027f94-0682-431e-97c1-827d1879fa79" + Categories = @() + Description = "Microsoft 365 Apps for Windows 10 and later" + Developer = "Contoso" + DisplayName = "Microsoft 365 Apps for Windows 10 and later drift" + InformationUrl = "" + IsFeatured = $False + Notes = "" + Owner = "" + PrivacyInformationUrl = "" + Publisher = "Contoso" + PublishingState = "published" + RoleScopeTagIds = @() + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.officeSuiteApp' + minimumSupportedOperatingSystem = @{ + v11_0 = $true + } + } } } + Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppAssignment -MockWith{ + return $null + } } - It 'Should Reverse Engineer resource from the Export method' { + + It '5.0 Should Reverse Engineer resource from the Export method' { $result = Export-TargetResource @testParams $result | Should -Not -BeNullOrEmpty } From 5117eefe70f7d65358d7b6bd8f87daf3e1d14af6 Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Mon, 14 Oct 2024 15:59:15 -0700 Subject: [PATCH 208/252] fix tests --- ...soft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 index 189cbc3534..b1a272ed47 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 @@ -67,7 +67,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Id = "8d027f94-0682-431e-97c1-827d1879fa79" Categories = @() Description = "Microsoft 365 Apps for Windows 10 and later" - Developer = "Contoso" DisplayName = "Microsoft 365 Apps for Windows 10 and later" InformationUrl = "" IsFeatured = $False @@ -75,10 +74,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { New-CimInstance -ClassName MSFT_DeviceManagementMinimumOperatingSystem -Property @{ v11_0 = $true } -ClientOnly) - Notes = "" - Owner = "" PrivacyInformationUrl = "" - Publisher = "Contoso" RoleScopeTagIds = @() Ensure = 'Present' Credential = $Credential From 7fd57884b9dc3181b4926b9f47150a01469e3bab Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Mon, 14 Oct 2024 17:01:44 -0700 Subject: [PATCH 209/252] update tests --- ...eMobileAppsWindowsOfficeSuiteApp.Tests.ps1 | 181 +++++++++++++----- 1 file changed, 128 insertions(+), 53 deletions(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 index b1a272ed47..67ac460a73 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 @@ -70,12 +70,26 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { DisplayName = "Microsoft 365 Apps for Windows 10 and later" InformationUrl = "" IsFeatured = $False - MinimumSupportedOperatingSystem = [CimInstance]( - New-CimInstance -ClassName MSFT_DeviceManagementMinimumOperatingSystem -Property @{ - v11_0 = $true - } -ClientOnly) PrivacyInformationUrl = "" + ExcludedApps = (New-CimInstance -ClassName MSFT_DeviceManagementMobileAppExcludedApp -Property @{ + teams = $false + sharePointDesigner = $true + powerPoint = $false + outlook = $false + groove = $true + word = $false + lync = $true + oneNote = $false + oneDrive = $false + publisher = $false + bing = $false + visio = $false + access = $false + infoPath = $true + excel = $false + } -ClientOnly) RoleScopeTagIds = @() + Notes = "" Ensure = 'Present' Credential = $Credential } @@ -103,20 +117,29 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Id = "ad027f94-0682-431e-97c1-827d1879fa79" Categories = @() Description = "Microsoft 365 Apps for Windows 10 and later" - Developer = "Contoso" DisplayName = "Microsoft 365 Apps for Windows 10 and later" InformationUrl = "" IsFeatured = $False - MinimumSupportedOperatingSystem = [CimInstance]( - New-CimInstance -ClassName MSFT_DeviceManagementMinimumOperatingSystem -Property @{ - v11_0 = $true + ExcludedApps = (New-CimInstance -ClassName MSFT_DeviceManagementMobileAppExcludedApp -Property @{ + teams = $false + sharePointDesigner = $true + powerPoint = $false + outlook = $false + groove = $true + word = $false + lync = $true + oneNote = $false + oneDrive = $false + publisher = $false + bing = $false + visio = $false + access = $false + infoPath = $true + excel = $false } -ClientOnly) Notes = "" - Owner = "" PrivacyInformationUrl = "" - Publisher = "Contoso" RoleScopeTagIds = @() - IgnoreVersionDetection = $True Ensure = 'Absent' Credential = $Credential } @@ -126,23 +149,29 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Id = "ad027f94-0682-431e-97c1-827d1879fa79" Categories = @() Description = "Microsoft 365 Apps for Windows 10 and laterr" - Developer = "Contoso" DisplayName = "Microsoft 365 Apps for Windows 10 and later" InformationUrl = "" IsFeatured = $False Notes = "" - Owner = "" PrivacyInformationUrl = "" - Publisher = "Contoso" - PublishingState = "published" RoleScopeTagIds = @() - IgnoreVersionDetection = $True - AdditionalProperties = @{ - '@odata.type' = '#microsoft.graph.officeSuiteApp' - minimumSupportedOperatingSystem = @{ - v11_0 = $true - } - } + ExcludedApps = (New-CimInstance -ClassName MSFT_DeviceManagementMobileAppExcludedApp -Property @{ + teams = $false + sharePointDesigner = $true + powerPoint = $false + outlook = $false + groove = $true + word = $false + lync = $true + oneNote = $false + oneDrive = $false + publisher = $false + bing = $false + visio = $false + access = $false + infoPath = $true + excel = $false + } -ClientOnly) Ensure = 'Present' } } @@ -170,18 +199,28 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Id = "8d027f94-0682-431e-97c1-827d1879fa79" Categories = @() Description = "Microsoft 365 Apps for Windows 10 and later" - Developer = "Contoso" DisplayName = "Microsoft 365 Apps for Windows 10 and later" InformationUrl = "" IsFeatured = $False - MinimumSupportedOperatingSystem = [CimInstance]( - New-CimInstance -ClassName MSFT_DeviceManagementMinimumOperatingSystem -Property @{ - v11_0 = $true - } -ClientOnly) Notes = "" - Owner = "" PrivacyInformationUrl = "" - Publisher = "Contoso" + ExcludedApps = (New-CimInstance -ClassName MSFT_DeviceManagementMobileAppExcludedApp -Property @{ + teams = $false + sharePointDesigner = $true + powerPoint = $false + outlook = $false + groove = $true + word = $false + lync = $true + oneNote = $false + oneDrive = $false + publisher = $false + bing = $false + visio = $false + access = $false + infoPath = $true + excel = $false + } -ClientOnly) RoleScopeTagIds = @() Ensure = 'Present' Credential = $Credential; @@ -192,22 +231,39 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Id = "8d027f94-0682-431e-97c1-827d1879fa79" Categories = @() Description = "Microsoft 365 Apps for Windows 10 and later" - Developer = "Contoso" DisplayName = "Microsoft 365 Apps for Windows 10 and later" InformationUrl = "" IsFeatured = $False Notes = "" - Owner = "" PrivacyInformationUrl = "" - Publisher = "Contoso" - PublishingState = "published" RoleScopeTagIds = @() - AdditionalProperties = @{ - '@odata.type' = '#microsoft.graph.officeSuiteApp' - minimumSupportedOperatingSystem = @{ - v11_0 = $true - } - } + ExcludedApps = (New-CimInstance -ClassName MSFT_DeviceManagementMobileAppExcludedApp -Property @{ + teams = $false + sharePointDesigner = $true + powerPoint = $false + outlook = $false + groove = $true + word = $false + lync = $true + oneNote = $false + oneDrive = $false + publisher = $false + bing = $false + visio = $false + access = $false + infoPath = $true + excel = $false + } -ClientOnly) + Assignments = @( + (New-CimInstance -ClassName MSFT_DeviceManagementMobileAppAssignment -Property @{ + deviceAndAppManagementAssignmentFilterType = 'none' + source = 'direct' + dataType = '#microsoft.graph.groupAssignmentTarget' + groupId = '42c02b60-f28c-4eef-b3e1-973184cc4a6c' + intent = 'required' + } -ClientOnly) + ) + Ensure = 'Present' } } Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppAssignment -MockWith{ @@ -226,18 +282,28 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Id = "8d027f94-0682-431e-97c1-827d1879fa79" Categories = @() Description = "Microsoft 365 Apps for Windows 10 and later" - Developer = "Contoso" DisplayName = "Microsoft 365 Apps for Windows 10 and later" InformationUrl = "" IsFeatured = $False - MinimumSupportedOperatingSystem = [CimInstance]( - New-CimInstance -ClassName MSFT_DeviceManagementMinimumOperatingSystem -Property @{ - v11_0 = $true + ExcludedApps = (New-CimInstance -ClassName MSFT_DeviceManagementMobileAppExcludedApp -Property @{ + teams = $false + sharePointDesigner = $true + powerPoint = $false + outlook = $false + groove = $true + word = $false + lync = $true + oneNote = $false + oneDrive = $false + publisher = $false + bing = $false + visio = $false + access = $false + infoPath = $true + excel = $false } -ClientOnly) Notes = "" - Owner = "" PrivacyInformationUrl = "" - Publisher = "Contoso" RoleScopeTagIds = @() Ensure = 'Present' Credential = $Credential; @@ -248,15 +314,28 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Id = "8d027f94-0682-431e-97c1-827d1879fa79" Categories = @() Description = "Microsoft 365 Apps for Windows 10 and later" - Developer = "Contoso" DisplayName = "Microsoft 365 Apps for Windows 10 and later drift" InformationUrl = "" IsFeatured = $False Notes = "" - Owner = "" PrivacyInformationUrl = "" - Publisher = "Contoso" - PublishingState = "published" + ExcludedApps = (New-CimInstance -ClassName MSFT_DeviceManagementMobileAppExcludedApp -Property @{ + teams = $false + sharePointDesigner = $true + powerPoint = $false + outlook = $false + groove = $true + word = $false + lync = $true + oneNote = $false + oneDrive = $false + publisher = $false + bing = $false + visio = $false + access = $false + infoPath = $true + excel = $false + } -ClientOnly) AdditionalProperties = @{ '@odata.type' = '#microsoft.graph.officeSuiteApp' minimumSupportedOperatingSystem = @{ @@ -295,15 +374,11 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Id = "8d027f94-0682-431e-97c1-827d1879fa79" Categories = @() Description = "Microsoft 365 Apps for Windows 10 and later" - Developer = "Contoso" DisplayName = "Microsoft 365 Apps for Windows 10 and later drift" InformationUrl = "" IsFeatured = $False Notes = "" - Owner = "" PrivacyInformationUrl = "" - Publisher = "Contoso" - PublishingState = "published" RoleScopeTagIds = @() AdditionalProperties = @{ '@odata.type' = '#microsoft.graph.officeSuiteApp' From 2686169279c93649903ae31cc8db16c300d5226f Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Mon, 14 Oct 2024 17:22:37 -0700 Subject: [PATCH 210/252] update test failure --- ...eMobileAppsWindowsOfficeSuiteApp.Tests.ps1 | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 index 67ac460a73..c5c90fe479 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 @@ -223,7 +223,16 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } -ClientOnly) RoleScopeTagIds = @() Ensure = 'Present' - Credential = $Credential; + Credential = $Credential + Assignments = @( + (New-CimInstance -ClassName MSFT_DeviceManagementMobileAppAssignment -Property @{ + deviceAndAppManagementAssignmentFilterType = 'none' + source = 'direct' + dataType = '#microsoft.graph.groupAssignmentTarget' + groupId = '42c02b60-f28c-4eef-b3e1-973184cc4a6c' + intent = 'required' + } -ClientOnly) + ) } Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { @@ -254,6 +263,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { infoPath = $true excel = $false } -ClientOnly) + Ensure = 'Present' + Credential = $Credential Assignments = @( (New-CimInstance -ClassName MSFT_DeviceManagementMobileAppAssignment -Property @{ deviceAndAppManagementAssignmentFilterType = 'none' @@ -263,7 +274,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { intent = 'required' } -ClientOnly) ) - Ensure = 'Present' } } Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppAssignment -MockWith{ @@ -380,6 +390,23 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Notes = "" PrivacyInformationUrl = "" RoleScopeTagIds = @() + ExcludedApps = (New-CimInstance -ClassName MSFT_DeviceManagementMobileAppExcludedApp -Property @{ + teams = $false + sharePointDesigner = $true + powerPoint = $false + outlook = $false + groove = $true + word = $false + lync = $true + oneNote = $false + oneDrive = $false + publisher = $false + bing = $false + visio = $false + access = $false + infoPath = $true + excel = $false + } -ClientOnly) AdditionalProperties = @{ '@odata.type' = '#microsoft.graph.officeSuiteApp' minimumSupportedOperatingSystem = @{ From a317433674b6e8b334cf15fa255fecf5e4c322a7 Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Mon, 14 Oct 2024 17:47:24 -0700 Subject: [PATCH 211/252] fix test --- .../1-Create.ps1 | 38 ++++++- ...eMobileAppsWindowsOfficeSuiteApp.Tests.ps1 | 107 ++++++++---------- 2 files changed, 85 insertions(+), 60 deletions(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 index b516274848..6dae38e4d8 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 @@ -18,9 +18,45 @@ Configuration Example [System.String] $CertificateThumbprint ) + Import-DscResource -ModuleName Microsoft365DSC node localhost { - + IntuneMobileAppsWindowsOfficeSuiteApp "IntuneMobileAppsWindowsOfficeSuiteApp-TeamsForBusinessInstaller" + { + Id = "8d027f94-0682-431e-97c1-827d1879fa79"; + Description = "TeamsForBusinessInstaller"; + Developer = "Contoso"; + DisplayName = "TeamsForBusinessInstaller"; + Ensure = "Present"; + InformationUrl = ""; + IsFeatured = $False; + MinimumSupportedOperatingSystem = MSFT_DeviceManagementMinimumOperatingSystem{ + v11_0 = $true + } + Notes = ""; + Owner = ""; + PrivacyInformationUrl = ""; + Publisher = "Contoso"; + Assignments = @( + MSFT_DeviceManagementMobileAppAssignment{ + groupDisplayName = 'All devices' + deviceAndAppManagementAssignmentFilterType = 'none' + dataType = '#microsoft.graph.allDevicesAssignmentTarget' + intent = 'required' + } + MSFT_DeviceManagementMobileAppAssignment{ + deviceAndAppManagementAssignmentFilterType = 'none' + dataType = '#microsoft.graph.groupAssignmentTarget' + groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' + intent = 'required' + } + ); + Categories = @( + MSFT_DeviceManagementMobileAppCategory { + Id = '1bff2652-03ec-4a48-941c-152e93736515' + DisplayName = 'Kajal 3' + }); + } } } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 index c5c90fe479..5cbb2b37f8 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 @@ -194,8 +194,40 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } Context -Name "3. The instance exists and values are already in the desired state" -Fixture { - BeforeAll { - $testParams = @{ + BeforeAll { + $testParams = @{ + Id = "8d027f94-0682-431e-97c1-827d1879fa79" + Categories = @() + Description = "Microsoft 365 Apps for Windows 10 and later" + DisplayName = "Microsoft 365 Apps for Windows 10 and later" + InformationUrl = "" + IsFeatured = $False + Notes = "" + PrivacyInformationUrl = "" + ExcludedApps = (New-CimInstance -ClassName MSFT_DeviceManagementMobileAppExcludedApp -Property @{ + teams = $false + sharePointDesigner = $true + powerPoint = $false + outlook = $false + groove = $true + word = $false + lync = $true + oneNote = $false + oneDrive = $false + publisher = $false + bing = $false + visio = $false + access = $false + infoPath = $true + excel = $false + } -ClientOnly) + RoleScopeTagIds = @() + Ensure = 'Present' + Credential = $Credential + } + + Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { + return @{ Id = "8d027f94-0682-431e-97c1-827d1879fa79" Categories = @() Description = "Microsoft 365 Apps for Windows 10 and later" @@ -222,70 +254,27 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { excel = $false } -ClientOnly) RoleScopeTagIds = @() - Ensure = 'Present' - Credential = $Credential - Assignments = @( - (New-CimInstance -ClassName MSFT_DeviceManagementMobileAppAssignment -Property @{ - deviceAndAppManagementAssignmentFilterType = 'none' - source = 'direct' - dataType = '#microsoft.graph.groupAssignmentTarget' - groupId = '42c02b60-f28c-4eef-b3e1-973184cc4a6c' - intent = 'required' - } -ClientOnly) - ) - } - - Mock -CommandName Get-MgBetaDeviceAppManagementMobileApp -MockWith { - return @{ - Id = "8d027f94-0682-431e-97c1-827d1879fa79" - Categories = @() - Description = "Microsoft 365 Apps for Windows 10 and later" - DisplayName = "Microsoft 365 Apps for Windows 10 and later" - InformationUrl = "" - IsFeatured = $False - Notes = "" - PrivacyInformationUrl = "" - RoleScopeTagIds = @() - ExcludedApps = (New-CimInstance -ClassName MSFT_DeviceManagementMobileAppExcludedApp -Property @{ - teams = $false - sharePointDesigner = $true - powerPoint = $false - outlook = $false - groove = $true - word = $false - lync = $true - oneNote = $false - oneDrive = $false - publisher = $false - bing = $false - visio = $false - access = $false - infoPath = $true - excel = $false - } -ClientOnly) - Ensure = 'Present' - Credential = $Credential - Assignments = @( - (New-CimInstance -ClassName MSFT_DeviceManagementMobileAppAssignment -Property @{ - deviceAndAppManagementAssignmentFilterType = 'none' - source = 'direct' - dataType = '#microsoft.graph.groupAssignmentTarget' - groupId = '42c02b60-f28c-4eef-b3e1-973184cc4a6c' - intent = 'required' - } -ClientOnly) - ) + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.officeSuiteApp' + minimumSupportedOperatingSystem = @{ + v11_0 = $true + } } - } - Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppAssignment -MockWith{ - return $null + Ensure = 'Present' } } - It '3.0 Should return true from the Test method' { - Test-TargetResource @testParams | Should -Be $true + # Remove Assignments logic for now as we debug this part + Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppAssignment -MockWith{ + return $null } } + It '3.0 Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + Context -Name "4. The instance exists and values are NOT in the desired state" -Fixture { BeforeAll { $testParams = @{ From 3fb01c6d2d43c5e0f31fd5ba47dd06387cae2e77 Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Mon, 14 Oct 2024 17:59:10 -0700 Subject: [PATCH 212/252] update create ps1 --- .../1-Create.ps1 | 74 +++++++++---------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 index 6dae38e4d8..bbcca611da 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 @@ -19,44 +19,44 @@ Configuration Example $CertificateThumbprint ) - Import-DscResource -ModuleName Microsoft365DSC + # Import-DscResource -ModuleName Microsoft365DSC node localhost { - IntuneMobileAppsWindowsOfficeSuiteApp "IntuneMobileAppsWindowsOfficeSuiteApp-TeamsForBusinessInstaller" - { - Id = "8d027f94-0682-431e-97c1-827d1879fa79"; - Description = "TeamsForBusinessInstaller"; - Developer = "Contoso"; - DisplayName = "TeamsForBusinessInstaller"; - Ensure = "Present"; - InformationUrl = ""; - IsFeatured = $False; - MinimumSupportedOperatingSystem = MSFT_DeviceManagementMinimumOperatingSystem{ - v11_0 = $true - } - Notes = ""; - Owner = ""; - PrivacyInformationUrl = ""; - Publisher = "Contoso"; - Assignments = @( - MSFT_DeviceManagementMobileAppAssignment{ - groupDisplayName = 'All devices' - deviceAndAppManagementAssignmentFilterType = 'none' - dataType = '#microsoft.graph.allDevicesAssignmentTarget' - intent = 'required' - } - MSFT_DeviceManagementMobileAppAssignment{ - deviceAndAppManagementAssignmentFilterType = 'none' - dataType = '#microsoft.graph.groupAssignmentTarget' - groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' - intent = 'required' - } - ); - Categories = @( - MSFT_DeviceManagementMobileAppCategory { - Id = '1bff2652-03ec-4a48-941c-152e93736515' - DisplayName = 'Kajal 3' - }); - } + # IntuneMobileAppsWindowsOfficeSuiteApp "IntuneMobileAppsWindowsOfficeSuiteApp-TeamsForBusinessInstaller" + # { + # Id = "8d027f94-0682-431e-97c1-827d1879fa79"; + # Description = "TeamsForBusinessInstaller"; + # Developer = "Contoso"; + # DisplayName = "TeamsForBusinessInstaller"; + # Ensure = "Present"; + # InformationUrl = ""; + # IsFeatured = $False; + # MinimumSupportedOperatingSystem = MSFT_DeviceManagementMinimumOperatingSystem{ + # v11_0 = $true + # } + # Notes = ""; + # Owner = ""; + # PrivacyInformationUrl = ""; + # Publisher = "Contoso"; + # Assignments = @( + # MSFT_DeviceManagementMobileAppAssignment{ + # groupDisplayName = 'All devices' + # deviceAndAppManagementAssignmentFilterType = 'none' + # dataType = '#microsoft.graph.allDevicesAssignmentTarget' + # intent = 'required' + # } + # MSFT_DeviceManagementMobileAppAssignment{ + # deviceAndAppManagementAssignmentFilterType = 'none' + # dataType = '#microsoft.graph.groupAssignmentTarget' + # groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' + # intent = 'required' + # } + # ); + # Categories = @( + # MSFT_DeviceManagementMobileAppCategory { + # Id = '1bff2652-03ec-4a48-941c-152e93736515' + # DisplayName = 'Kajal 3' + # }); + # } } } From ac3712b60b5d3d24bab11c89b1640d6c0502c9f8 Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Mon, 14 Oct 2024 18:14:26 -0700 Subject: [PATCH 213/252] update 3rd test --- ...eMobileAppsWindowsOfficeSuiteApp.Tests.ps1 | 36 ++----------------- 1 file changed, 2 insertions(+), 34 deletions(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 index 5cbb2b37f8..cf98006de8 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 @@ -204,23 +204,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { IsFeatured = $False Notes = "" PrivacyInformationUrl = "" - ExcludedApps = (New-CimInstance -ClassName MSFT_DeviceManagementMobileAppExcludedApp -Property @{ - teams = $false - sharePointDesigner = $true - powerPoint = $false - outlook = $false - groove = $true - word = $false - lync = $true - oneNote = $false - oneDrive = $false - publisher = $false - bing = $false - visio = $false - access = $false - infoPath = $true - excel = $false - } -ClientOnly) + ExcludedApps = @() RoleScopeTagIds = @() Ensure = 'Present' Credential = $Credential @@ -236,23 +220,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { IsFeatured = $False Notes = "" PrivacyInformationUrl = "" - ExcludedApps = (New-CimInstance -ClassName MSFT_DeviceManagementMobileAppExcludedApp -Property @{ - teams = $false - sharePointDesigner = $true - powerPoint = $false - outlook = $false - groove = $true - word = $false - lync = $true - oneNote = $false - oneDrive = $false - publisher = $false - bing = $false - visio = $false - access = $false - infoPath = $true - excel = $false - } -ClientOnly) + ExcludedApps = @() RoleScopeTagIds = @() AdditionalProperties = @{ '@odata.type' = '#microsoft.graph.officeSuiteApp' From 009b0e16d0ec1769d6b400c2aa017cd2d1c0f28a Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Mon, 14 Oct 2024 18:28:36 -0700 Subject: [PATCH 214/252] update 3rd test --- ...t365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 index cf98006de8..e27aafd815 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 @@ -222,12 +222,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { PrivacyInformationUrl = "" ExcludedApps = @() RoleScopeTagIds = @() - AdditionalProperties = @{ - '@odata.type' = '#microsoft.graph.officeSuiteApp' - minimumSupportedOperatingSystem = @{ - v11_0 = $true - } - } + AdditionalProperties = @{} Ensure = 'Present' } } From 9afd258bbf9f8aa0b6174a318acdb7a99aa1ff90 Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Mon, 14 Oct 2024 18:30:21 -0700 Subject: [PATCH 215/252] update 3rd test --- ...65DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 index e27aafd815..ff169134f0 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneMobileAppsWindowsOfficeSuiteApp.Tests.ps1 @@ -204,7 +204,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { IsFeatured = $False Notes = "" PrivacyInformationUrl = "" - ExcludedApps = @() RoleScopeTagIds = @() Ensure = 'Present' Credential = $Credential @@ -220,9 +219,13 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { IsFeatured = $False Notes = "" PrivacyInformationUrl = "" - ExcludedApps = @() RoleScopeTagIds = @() - AdditionalProperties = @{} + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.officeSuiteApp' + minimumSupportedOperatingSystem = @{ + v11_0 = $true + } + } Ensure = 'Present' } } From b9dce320c88cc32e0b60f69b8b0613f8153189c5 Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Mon, 14 Oct 2024 18:56:28 -0700 Subject: [PATCH 216/252] update examples --- .../1-Create.ps1 | 79 ++++++++++--------- .../2-Update.ps1 | 45 ++++++++++- .../3-Remove.ps1 | 8 +- 3 files changed, 94 insertions(+), 38 deletions(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 index bbcca611da..8c29f5a67e 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 @@ -22,41 +22,48 @@ Configuration Example # Import-DscResource -ModuleName Microsoft365DSC node localhost { - # IntuneMobileAppsWindowsOfficeSuiteApp "IntuneMobileAppsWindowsOfficeSuiteApp-TeamsForBusinessInstaller" - # { - # Id = "8d027f94-0682-431e-97c1-827d1879fa79"; - # Description = "TeamsForBusinessInstaller"; - # Developer = "Contoso"; - # DisplayName = "TeamsForBusinessInstaller"; - # Ensure = "Present"; - # InformationUrl = ""; - # IsFeatured = $False; - # MinimumSupportedOperatingSystem = MSFT_DeviceManagementMinimumOperatingSystem{ - # v11_0 = $true - # } - # Notes = ""; - # Owner = ""; - # PrivacyInformationUrl = ""; - # Publisher = "Contoso"; - # Assignments = @( - # MSFT_DeviceManagementMobileAppAssignment{ - # groupDisplayName = 'All devices' - # deviceAndAppManagementAssignmentFilterType = 'none' - # dataType = '#microsoft.graph.allDevicesAssignmentTarget' - # intent = 'required' - # } - # MSFT_DeviceManagementMobileAppAssignment{ - # deviceAndAppManagementAssignmentFilterType = 'none' - # dataType = '#microsoft.graph.groupAssignmentTarget' - # groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' - # intent = 'required' - # } - # ); - # Categories = @( - # MSFT_DeviceManagementMobileAppCategory { - # Id = '1bff2652-03ec-4a48-941c-152e93736515' - # DisplayName = 'Kajal 3' - # }); - # } + IntuneMobileAppsWindowsOfficeSuiteApp "IntuneMobileAppsWindowsOfficeSuiteApp-Microsoft 365 Apps for Windows 10 and later" + { + Id = "8e683524-4ec1-4813-bb3e-6256b2f293d" + Categories = @() + Description = "Microsoft 365 Apps for Windows 10 and laterr" + DisplayName = "Microsoft 365 Apps for Windows 10 and later" + Ensure = "Present"; + InformationUrl = ""; + IsFeatured = $False; + Notes = "" + PrivacyInformationUrl = "" + RoleScopeTagIds = @() + ExcludedApps = (New-CimInstance -ClassName MSFT_DeviceManagementMobileAppExcludedApp -Property @{ + teams = $false + sharePointDesigner = $true + powerPoint = $false + outlook = $false + groove = $true + word = $false + lync = $true + oneNote = $false + oneDrive = $false + publisher = $false + bing = $false + visio = $false + access = $false + infoPath = $true + excel = $false + } -ClientOnly) + Assignments = @( + MSFT_DeviceManagementMobileAppAssignment{ + deviceAndAppManagementAssignmentFilterType = 'none' + dataType = '#microsoft.graph.groupAssignmentTarget' + groupId = '42c02b60-f28c-4eef-b3e1-973184cc4a6c' + intent = 'required' + } + ); + Categories = @( + MSFT_DeviceManagementMobileAppCategory { + Id = '8e683524-4ec1-4813-bb3e-6256b2f293d8' + DisplayName = 'Productivity' + }); + } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/2-Update.ps1 index b516274848..58e03f975d 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/2-Update.ps1 @@ -18,9 +18,52 @@ Configuration Example [System.String] $CertificateThumbprint ) + Import-DscResource -ModuleName Microsoft365DSC node localhost { - + IntuneMobileAppsWindowsOfficeSuiteApp "IntuneMobileAppsWindowsOfficeSuiteApp-Microsoft 365 Apps for Windows 10 and later" + { + Id = "8e683524-4ec1-4813-bb3e-6256b2f293d" + Categories = @() + Description = "Microsoft 365 Apps for Windows 10 and laterr" + DisplayName = "Microsoft 365 Apps for Windows 10 and later" + Ensure = "Present"; + InformationUrl = ""; + IsFeatured = $False; + Notes = "" + PrivacyInformationUrl = "" + RoleScopeTagIds = @() + ExcludedApps = (New-CimInstance -ClassName MSFT_DeviceManagementMobileAppExcludedApp -Property @{ + teams = $false + sharePointDesigner = $true + powerPoint = $false + outlook = $false + groove = $true + word = $false + lync = $true + oneNote = $false + oneDrive = $false + publisher = $false + bing = $false + visio = $false + access = $false + infoPath = $true + excel = $false + } -ClientOnly) + Assignments = @( + MSFT_DeviceManagementMobileAppAssignment{ + deviceAndAppManagementAssignmentFilterType = 'none' + dataType = '#microsoft.graph.groupAssignmentTarget' + groupId = '42c02b60-f28c-4eef-b3e1-973184cc4a6c' + intent = 'required' + } + ); + Categories = @( + MSFT_DeviceManagementMobileAppCategory { + Id = '8e683524-4ec1-4813-bb3e-6256b2f293d8' + DisplayName = 'Productivity' + }); + } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/3-Remove.ps1 index b516274848..da1bb82e9b 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/3-Remove.ps1 @@ -18,9 +18,15 @@ Configuration Example [System.String] $CertificateThumbprint ) + Import-DscResource -ModuleName Microsoft365DSC node localhost { - + IntuneMobileAppsWindowsOfficeSuiteApp "IntuneMobileAppsWindowsOfficeSuiteApp-Microsoft 365 Apps for Windows 10 and later" + { + Id = "8e683524-4ec1-4813-bb3e-6256b2f293d8"; + DisplayName = "Microsoft 365 Apps for Windows 10 and later"; + Ensure = "Absent"; + } } } From e3cf023c54b81e870c3cafa74d70ca8922644f53 Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Mon, 14 Oct 2024 19:05:26 -0700 Subject: [PATCH 217/252] remove duplicate categories --- .../Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 | 1 - .../Resources/IntuneMobileAppsWindowsOfficeSuiteApp/2-Update.ps1 | 1 - 2 files changed, 2 deletions(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 index 8c29f5a67e..8012f27878 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 @@ -25,7 +25,6 @@ Configuration Example IntuneMobileAppsWindowsOfficeSuiteApp "IntuneMobileAppsWindowsOfficeSuiteApp-Microsoft 365 Apps for Windows 10 and later" { Id = "8e683524-4ec1-4813-bb3e-6256b2f293d" - Categories = @() Description = "Microsoft 365 Apps for Windows 10 and laterr" DisplayName = "Microsoft 365 Apps for Windows 10 and later" Ensure = "Present"; diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/2-Update.ps1 index 58e03f975d..fe80df05c4 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/2-Update.ps1 @@ -25,7 +25,6 @@ Configuration Example IntuneMobileAppsWindowsOfficeSuiteApp "IntuneMobileAppsWindowsOfficeSuiteApp-Microsoft 365 Apps for Windows 10 and later" { Id = "8e683524-4ec1-4813-bb3e-6256b2f293d" - Categories = @() Description = "Microsoft 365 Apps for Windows 10 and laterr" DisplayName = "Microsoft 365 Apps for Windows 10 and later" Ensure = "Present"; From 908a878db2d2d8d35eda34fba8376b5ebcda046a Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Mon, 14 Oct 2024 19:17:11 -0700 Subject: [PATCH 218/252] include import resource --- .../IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 index 8012f27878..fe80df05c4 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 @@ -19,7 +19,7 @@ Configuration Example $CertificateThumbprint ) - # Import-DscResource -ModuleName Microsoft365DSC + Import-DscResource -ModuleName Microsoft365DSC node localhost { IntuneMobileAppsWindowsOfficeSuiteApp "IntuneMobileAppsWindowsOfficeSuiteApp-Microsoft 365 Apps for Windows 10 and later" From 58362018faa8a6ddbf0cacb34e7463fb6a8c0def Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Mon, 14 Oct 2024 19:17:59 -0700 Subject: [PATCH 219/252] update examples --- .../1-Create.ps1 | 17 ----------------- .../2-Update.ps1 | 17 ----------------- 2 files changed, 34 deletions(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 index fe80df05c4..0ae915356e 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 @@ -33,23 +33,6 @@ Configuration Example Notes = "" PrivacyInformationUrl = "" RoleScopeTagIds = @() - ExcludedApps = (New-CimInstance -ClassName MSFT_DeviceManagementMobileAppExcludedApp -Property @{ - teams = $false - sharePointDesigner = $true - powerPoint = $false - outlook = $false - groove = $true - word = $false - lync = $true - oneNote = $false - oneDrive = $false - publisher = $false - bing = $false - visio = $false - access = $false - infoPath = $true - excel = $false - } -ClientOnly) Assignments = @( MSFT_DeviceManagementMobileAppAssignment{ deviceAndAppManagementAssignmentFilterType = 'none' diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/2-Update.ps1 index fe80df05c4..0ae915356e 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/2-Update.ps1 @@ -33,23 +33,6 @@ Configuration Example Notes = "" PrivacyInformationUrl = "" RoleScopeTagIds = @() - ExcludedApps = (New-CimInstance -ClassName MSFT_DeviceManagementMobileAppExcludedApp -Property @{ - teams = $false - sharePointDesigner = $true - powerPoint = $false - outlook = $false - groove = $true - word = $false - lync = $true - oneNote = $false - oneDrive = $false - publisher = $false - bing = $false - visio = $false - access = $false - infoPath = $true - excel = $false - } -ClientOnly) Assignments = @( MSFT_DeviceManagementMobileAppAssignment{ deviceAndAppManagementAssignmentFilterType = 'none' From 204ad5e956f216a29ed8ce0a66caf7d0f15bd3f1 Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Mon, 14 Oct 2024 19:45:40 -0700 Subject: [PATCH 220/252] update macoslosbapp to remove beta as requested --- .../MSFT_IntuneMobileAppsMacOSLobApp.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 index f0e7cd245e..739c2c80d7 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.psm1 @@ -450,7 +450,7 @@ function Set-TargetResource throw "Mobile App Category with DisplayName $($category.DisplayName) not found." } - Invoke-MgBetaGraphRequest -Uri "/beta/deviceAppManagement/mobileApps/$($app.Id)/categories/`$ref" -Method 'POST' -Body @{ + Invoke-MgGraphRequest -Uri "/beta/deviceAppManagement/mobileApps/$($app.Id)/categories/`$ref" -Method 'POST' -Body @{ '@odata.id' = "https://graph.microsoft.com/beta/deviceAppManagement/mobileAppCategories/$($currentCategory.Id)" } } From b7679dccfc4eb7e0d431c3245ddbee8dfc24018d Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Tue, 15 Oct 2024 13:21:47 +0200 Subject: [PATCH 221/252] Add Intune Security Baseline for Microsoft 365 Apps for Enterprise --- ...BaselineMicrosoft365AppsForEnterprise.psm1 | 1110 +++++++++++++++++ ...neMicrosoft365AppsForEnterprise.schema.mof | 476 +++++++ .../readme.md | 6 + .../settings.json | 32 + .../1-Create.ps1 | 58 + .../2-Update.ps1 | 58 + .../3-Remove.ps1 | 34 + .../Modules/M365DSCDRGUtil.psm1 | 96 +- .../M365DSCResourceGenerator.psm1 | 63 +- ...ineMicrosoft365AppsForEnterprise.Tests.ps1 | 500 ++++++++ 10 files changed, 2389 insertions(+), 44 deletions(-) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise/MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise/MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneSecurityBaselineMicrosoft365AppsForEnterprise/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneSecurityBaselineMicrosoft365AppsForEnterprise/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneSecurityBaselineMicrosoft365AppsForEnterprise/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneSecurityBaselineMicrosoft365AppsForEnterprise.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise/MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise/MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise.psm1 new file mode 100644 index 0000000000..9958ba28ca --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise/MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise.psm1 @@ -0,0 +1,1110 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $DeviceSettings, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $UserSettings, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + #endregion + + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + try + { + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + + $getValue = $null + #region resource generator code + $getValue = Get-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $Id -ErrorAction SilentlyContinue + + if ($null -eq $getValue) + { + Write-Verbose -Message "Could not find an Intune Security Baseline Microsoft365 Apps For Enterprise with Id {$Id}" + + if (-not [System.String]::IsNullOrEmpty($DisplayName)) + { + $getValue = Get-MgBetaDeviceManagementConfigurationPolicy ` + -Filter "Name eq '$DisplayName'" ` + -ErrorAction SilentlyContinue + } + } + #endregion + if ($null -eq $getValue) + { + Write-Verbose -Message "Could not find an Intune Security Baseline Microsoft365 Apps For Enterprise with Name {$DisplayName}." + return $nullResult + } + $Id = $getValue.Id + Write-Verbose -Message "An Intune Security Baseline Microsoft365 Apps For Enterprise with Id {$Id} and Name {$DisplayName} was found" + + # Retrieve policy specific settings + [array]$settings = Get-MgBetaDeviceManagementConfigurationPolicySetting ` + -DeviceManagementConfigurationPolicyId $Id ` + -ExpandProperty 'settingDefinitions' ` + -All ` + -ErrorAction Stop + + $policySettings = @{} + $policySettings = Export-IntuneSettingCatalogPolicySettings -Settings $settings -ReturnHashtable $policySettings -ContainsDeviceAndUserSettings + + #region resource generator code + $complexDeviceSettings = @{} + $complexDeviceSettings.Add('Pol_SecGuide_A001_Block_Flash', $policySettings.DeviceSettings.pol_SecGuide_A001_Block_Flash) + $complexDeviceSettings.Add('Pol_SecGuide_Block_Flash', $policySettings.DeviceSettings.pol_SecGuide_Block_Flash) + $complexDeviceSettings.Add('Pol_SecGuide_Legacy_JScript', $policySettings.DeviceSettings.pol_SecGuide_Legacy_JScript) + $complexDeviceSettings.Add('POL_SG_powerpnt', $policySettings.DeviceSettings.pOL_SG_powerpnt) + $complexDeviceSettings.Add('POL_SG_onenote', $policySettings.DeviceSettings.pOL_SG_onenote) + $complexDeviceSettings.Add('POL_SG_mspub', $policySettings.DeviceSettings.pOL_SG_mspub) + $complexDeviceSettings.Add('POL_SG_msaccess', $policySettings.DeviceSettings.pOL_SG_msaccess) + $complexDeviceSettings.Add('POL_SG_winproj', $policySettings.DeviceSettings.pOL_SG_winproj) + $complexDeviceSettings.Add('POL_SG_visio', $policySettings.DeviceSettings.pOL_SG_visio) + $complexDeviceSettings.Add('POL_SG_outlook', $policySettings.DeviceSettings.pOL_SG_outlook) + $complexDeviceSettings.Add('POL_SG_winword', $policySettings.DeviceSettings.pOL_SG_winword) + $complexDeviceSettings.Add('POL_SG_excel', $policySettings.DeviceSettings.pOL_SG_excel) + $complexDeviceSettings.Add('L_PolicyEnableSIPHighSecurityMode', $policySettings.DeviceSettings.l_PolicyEnableSIPHighSecurityMode) + $complexDeviceSettings.Add('L_PolicyDisableHttpConnect', $policySettings.DeviceSettings.l_PolicyDisableHttpConnect) + $complexDeviceSettings.Add('L_AddonManagement', $policySettings.DeviceSettings.l_AddonManagement) + $complexDeviceSettings.Add('L_powerpntexe17', $policySettings.DeviceSettings.l_powerpntexe17) + $complexDeviceSettings.Add('L_excelexe15', $policySettings.DeviceSettings.l_excelexe15) + $complexDeviceSettings.Add('L_visioexe19', $policySettings.DeviceSettings.l_visioexe19) + $complexDeviceSettings.Add('L_onenoteexe26', $policySettings.DeviceSettings.l_onenoteexe26) + $complexDeviceSettings.Add('L_outlookexe22', $policySettings.DeviceSettings.l_outlookexe22) + $complexDeviceSettings.Add('L_pptviewexe18', $policySettings.DeviceSettings.l_pptviewexe18) + $complexDeviceSettings.Add('L_winwordexe21', $policySettings.DeviceSettings.l_winwordexe21) + $complexDeviceSettings.Add('L_exprwdexe24', $policySettings.DeviceSettings.l_exprwdexe24) + $complexDeviceSettings.Add('L_spdesignexe23', $policySettings.DeviceSettings.l_spdesignexe23) + $complexDeviceSettings.Add('L_winprojexe20', $policySettings.DeviceSettings.l_winprojexe20) + $complexDeviceSettings.Add('L_grooveexe14', $policySettings.DeviceSettings.l_grooveexe14) + $complexDeviceSettings.Add('L_mspubexe16', $policySettings.DeviceSettings.l_mspubexe16) + $complexDeviceSettings.Add('L_mse7exe27', $policySettings.DeviceSettings.l_mse7exe27) + $complexDeviceSettings.Add('L_msaccessexe25', $policySettings.DeviceSettings.l_msaccessexe25) + $complexDeviceSettings.Add('L_ConsistentMimeHandling', $policySettings.DeviceSettings.l_ConsistentMimeHandling) + $complexDeviceSettings.Add('L_excelexe43', $policySettings.DeviceSettings.l_excelexe43) + $complexDeviceSettings.Add('L_spdesignexe51', $policySettings.DeviceSettings.l_spdesignexe51) + $complexDeviceSettings.Add('L_onenoteexe54', $policySettings.DeviceSettings.l_onenoteexe54) + $complexDeviceSettings.Add('L_outlookexe50', $policySettings.DeviceSettings.l_outlookexe50) + $complexDeviceSettings.Add('L_pptviewexe46', $policySettings.DeviceSettings.l_pptviewexe46) + $complexDeviceSettings.Add('L_mspubexe44', $policySettings.DeviceSettings.l_mspubexe44) + $complexDeviceSettings.Add('L_visioexe47', $policySettings.DeviceSettings.l_visioexe47) + $complexDeviceSettings.Add('L_winprojexe48', $policySettings.DeviceSettings.l_winprojexe48) + $complexDeviceSettings.Add('L_msaccessexe53', $policySettings.DeviceSettings.l_msaccessexe53) + $complexDeviceSettings.Add('L_powerpntexe45', $policySettings.DeviceSettings.l_powerpntexe45) + $complexDeviceSettings.Add('L_grooveexe42', $policySettings.DeviceSettings.l_grooveexe42) + $complexDeviceSettings.Add('L_mse7exe55', $policySettings.DeviceSettings.l_mse7exe55) + $complexDeviceSettings.Add('L_winwordexe49', $policySettings.DeviceSettings.l_winwordexe49) + $complexDeviceSettings.Add('L_exprwdexe52', $policySettings.DeviceSettings.l_exprwdexe52) + $complexDeviceSettings.Add('L_Disableusernameandpassword', $policySettings.DeviceSettings.l_Disableusernameandpassword) + $complexDeviceSettings.Add('L_excelexe127', $policySettings.DeviceSettings.l_excelexe127) + $complexDeviceSettings.Add('L_grooveexe126', $policySettings.DeviceSettings.l_grooveexe126) + $complexDeviceSettings.Add('L_onenoteexe138', $policySettings.DeviceSettings.l_onenoteexe138) + $complexDeviceSettings.Add('L_mse7exe139', $policySettings.DeviceSettings.l_mse7exe139) + $complexDeviceSettings.Add('L_mspubexe128', $policySettings.DeviceSettings.l_mspubexe128) + $complexDeviceSettings.Add('L_visioexe131', $policySettings.DeviceSettings.l_visioexe131) + $complexDeviceSettings.Add('L_exprwdexe136', $policySettings.DeviceSettings.l_exprwdexe136) + $complexDeviceSettings.Add('L_msaccessexe137', $policySettings.DeviceSettings.l_msaccessexe137) + $complexDeviceSettings.Add('L_spdesignexe135', $policySettings.DeviceSettings.l_spdesignexe135) + $complexDeviceSettings.Add('L_winwordexe133', $policySettings.DeviceSettings.l_winwordexe133) + $complexDeviceSettings.Add('L_powerpntexe129', $policySettings.DeviceSettings.l_powerpntexe129) + $complexDeviceSettings.Add('L_outlookexe134', $policySettings.DeviceSettings.l_outlookexe134) + $complexDeviceSettings.Add('L_winprojexe132', $policySettings.DeviceSettings.l_winprojexe132) + $complexDeviceSettings.Add('L_pptviewexe130', $policySettings.DeviceSettings.l_pptviewexe130) + $complexDeviceSettings.Add('L_Informationbar', $policySettings.DeviceSettings.l_Informationbar) + $complexDeviceSettings.Add('L_excelexe113', $policySettings.DeviceSettings.l_excelexe113) + $complexDeviceSettings.Add('L_mspubexe114', $policySettings.DeviceSettings.l_mspubexe114) + $complexDeviceSettings.Add('L_msaccessexe123', $policySettings.DeviceSettings.l_msaccessexe123) + $complexDeviceSettings.Add('L_onenoteexe124', $policySettings.DeviceSettings.l_onenoteexe124) + $complexDeviceSettings.Add('L_outlookexe120', $policySettings.DeviceSettings.l_outlookexe120) + $complexDeviceSettings.Add('L_winprojexe118', $policySettings.DeviceSettings.l_winprojexe118) + $complexDeviceSettings.Add('L_powerpntexe115', $policySettings.DeviceSettings.l_powerpntexe115) + $complexDeviceSettings.Add('L_spdesignexe121', $policySettings.DeviceSettings.l_spdesignexe121) + $complexDeviceSettings.Add('L_grooveexe112', $policySettings.DeviceSettings.l_grooveexe112) + $complexDeviceSettings.Add('L_visioexe117', $policySettings.DeviceSettings.l_visioexe117) + $complexDeviceSettings.Add('L_mse7exe125', $policySettings.DeviceSettings.l_mse7exe125) + $complexDeviceSettings.Add('L_winwordexe119', $policySettings.DeviceSettings.l_winwordexe119) + $complexDeviceSettings.Add('L_exprwdexe122', $policySettings.DeviceSettings.l_exprwdexe122) + $complexDeviceSettings.Add('L_pptviewexe116', $policySettings.DeviceSettings.l_pptviewexe116) + $complexDeviceSettings.Add('L_LocalMachineZoneLockdownSecurity', $policySettings.DeviceSettings.l_LocalMachineZoneLockdownSecurity) + $complexDeviceSettings.Add('L_mse7exe41', $policySettings.DeviceSettings.l_mse7exe41) + $complexDeviceSettings.Add('L_powerpntexe31', $policySettings.DeviceSettings.l_powerpntexe31) + $complexDeviceSettings.Add('L_mspubexe30', $policySettings.DeviceSettings.l_mspubexe30) + $complexDeviceSettings.Add('L_outlookexe36', $policySettings.DeviceSettings.l_outlookexe36) + $complexDeviceSettings.Add('L_pptviewexe32', $policySettings.DeviceSettings.l_pptviewexe32) + $complexDeviceSettings.Add('L_excelexe29', $policySettings.DeviceSettings.l_excelexe29) + $complexDeviceSettings.Add('L_exprwdexe38', $policySettings.DeviceSettings.l_exprwdexe38) + $complexDeviceSettings.Add('L_grooveexe28', $policySettings.DeviceSettings.l_grooveexe28) + $complexDeviceSettings.Add('L_winwordexe35', $policySettings.DeviceSettings.l_winwordexe35) + $complexDeviceSettings.Add('L_msaccessexe39', $policySettings.DeviceSettings.l_msaccessexe39) + $complexDeviceSettings.Add('L_spdesignexe37', $policySettings.DeviceSettings.l_spdesignexe37) + $complexDeviceSettings.Add('L_visioexe33', $policySettings.DeviceSettings.l_visioexe33) + $complexDeviceSettings.Add('L_onenoteexe40', $policySettings.DeviceSettings.l_onenoteexe40) + $complexDeviceSettings.Add('L_winprojexe34', $policySettings.DeviceSettings.l_winprojexe34) + $complexDeviceSettings.Add('L_MimeSniffingSafetyFature', $policySettings.DeviceSettings.l_MimeSniffingSafetyFature) + $complexDeviceSettings.Add('L_powerpntexe59', $policySettings.DeviceSettings.l_powerpntexe59) + $complexDeviceSettings.Add('L_exprwdexe66', $policySettings.DeviceSettings.l_exprwdexe66) + $complexDeviceSettings.Add('L_grooveexe56', $policySettings.DeviceSettings.l_grooveexe56) + $complexDeviceSettings.Add('L_visioexe61', $policySettings.DeviceSettings.l_visioexe61) + $complexDeviceSettings.Add('L_outlookexe64', $policySettings.DeviceSettings.l_outlookexe64) + $complexDeviceSettings.Add('L_mspubexe58', $policySettings.DeviceSettings.l_mspubexe58) + $complexDeviceSettings.Add('L_mse7exe69', $policySettings.DeviceSettings.l_mse7exe69) + $complexDeviceSettings.Add('L_msaccessexe67', $policySettings.DeviceSettings.l_msaccessexe67) + $complexDeviceSettings.Add('L_pptviewexe60', $policySettings.DeviceSettings.l_pptviewexe60) + $complexDeviceSettings.Add('L_winprojexe62', $policySettings.DeviceSettings.l_winprojexe62) + $complexDeviceSettings.Add('L_spdesignexe65', $policySettings.DeviceSettings.l_spdesignexe65) + $complexDeviceSettings.Add('L_onenoteexe68', $policySettings.DeviceSettings.l_onenoteexe68) + $complexDeviceSettings.Add('L_winwordexe63', $policySettings.DeviceSettings.l_winwordexe63) + $complexDeviceSettings.Add('L_excelexe57', $policySettings.DeviceSettings.l_excelexe57) + $complexDeviceSettings.Add('L_NavigateURL', $policySettings.DeviceSettings.l_NavigateURL) + $complexDeviceSettings.Add('L_spdesignexe177', $policySettings.DeviceSettings.l_spdesignexe177) + $complexDeviceSettings.Add('L_onenoteexe180', $policySettings.DeviceSettings.l_onenoteexe180) + $complexDeviceSettings.Add('L_pptviewexe172', $policySettings.DeviceSettings.l_pptviewexe172) + $complexDeviceSettings.Add('L_outlookexe176', $policySettings.DeviceSettings.l_outlookexe176) + $complexDeviceSettings.Add('L_winprojexe174', $policySettings.DeviceSettings.l_winprojexe174) + $complexDeviceSettings.Add('L_msaccessexe179', $policySettings.DeviceSettings.l_msaccessexe179) + $complexDeviceSettings.Add('L_winwordexe175', $policySettings.DeviceSettings.l_winwordexe175) + $complexDeviceSettings.Add('L_excelexe169', $policySettings.DeviceSettings.l_excelexe169) + $complexDeviceSettings.Add('L_mspubexe170', $policySettings.DeviceSettings.l_mspubexe170) + $complexDeviceSettings.Add('L_exprwdexe178', $policySettings.DeviceSettings.l_exprwdexe178) + $complexDeviceSettings.Add('L_powerpntexe171', $policySettings.DeviceSettings.l_powerpntexe171) + $complexDeviceSettings.Add('L_visioexe173', $policySettings.DeviceSettings.l_visioexe173) + $complexDeviceSettings.Add('L_mse7exe181', $policySettings.DeviceSettings.l_mse7exe181) + $complexDeviceSettings.Add('L_grooveexe168', $policySettings.DeviceSettings.l_grooveexe168) + $complexDeviceSettings.Add('L_ObjectCachingProtection', $policySettings.DeviceSettings.l_ObjectCachingProtection) + $complexDeviceSettings.Add('L_winwordexe77', $policySettings.DeviceSettings.l_winwordexe77) + $complexDeviceSettings.Add('L_powerpntexe73', $policySettings.DeviceSettings.l_powerpntexe73) + $complexDeviceSettings.Add('L_spdesignexe79', $policySettings.DeviceSettings.l_spdesignexe79) + $complexDeviceSettings.Add('L_mse7exe83', $policySettings.DeviceSettings.l_mse7exe83) + $complexDeviceSettings.Add('L_mspubexe72', $policySettings.DeviceSettings.l_mspubexe72) + $complexDeviceSettings.Add('L_msaccessexe81', $policySettings.DeviceSettings.l_msaccessexe81) + $complexDeviceSettings.Add('L_onenoteexe82', $policySettings.DeviceSettings.l_onenoteexe82) + $complexDeviceSettings.Add('L_outlookexe78', $policySettings.DeviceSettings.l_outlookexe78) + $complexDeviceSettings.Add('L_grooveexe70', $policySettings.DeviceSettings.l_grooveexe70) + $complexDeviceSettings.Add('L_excelexe71', $policySettings.DeviceSettings.l_excelexe71) + $complexDeviceSettings.Add('L_visioexe75', $policySettings.DeviceSettings.l_visioexe75) + $complexDeviceSettings.Add('L_pptviewexe74', $policySettings.DeviceSettings.l_pptviewexe74) + $complexDeviceSettings.Add('L_winprojexe76', $policySettings.DeviceSettings.l_winprojexe76) + $complexDeviceSettings.Add('L_exprwdexe80', $policySettings.DeviceSettings.l_exprwdexe80) + $complexDeviceSettings.Add('L_ProtectionFromZoneElevation', $policySettings.DeviceSettings.l_ProtectionFromZoneElevation) + $complexDeviceSettings.Add('L_mspubexe100', $policySettings.DeviceSettings.l_mspubexe100) + $complexDeviceSettings.Add('L_visioexe103', $policySettings.DeviceSettings.l_visioexe103) + $complexDeviceSettings.Add('L_powerpntexe101', $policySettings.DeviceSettings.l_powerpntexe101) + $complexDeviceSettings.Add('L_excelexe99', $policySettings.DeviceSettings.l_excelexe99) + $complexDeviceSettings.Add('L_mse7exe111', $policySettings.DeviceSettings.l_mse7exe111) + $complexDeviceSettings.Add('L_winwordexe105', $policySettings.DeviceSettings.l_winwordexe105) + $complexDeviceSettings.Add('L_exprwdexe108', $policySettings.DeviceSettings.l_exprwdexe108) + $complexDeviceSettings.Add('L_msaccessexe109', $policySettings.DeviceSettings.l_msaccessexe109) + $complexDeviceSettings.Add('L_spdesignexe107', $policySettings.DeviceSettings.l_spdesignexe107) + $complexDeviceSettings.Add('L_onenoteexe110', $policySettings.DeviceSettings.l_onenoteexe110) + $complexDeviceSettings.Add('L_pptviewexe102', $policySettings.DeviceSettings.l_pptviewexe102) + $complexDeviceSettings.Add('L_winprojexe104', $policySettings.DeviceSettings.l_winprojexe104) + $complexDeviceSettings.Add('L_grooveexe98', $policySettings.DeviceSettings.l_grooveexe98) + $complexDeviceSettings.Add('L_outlookexe106', $policySettings.DeviceSettings.l_outlookexe106) + $complexDeviceSettings.Add('L_RestrictActiveXInstall', $policySettings.DeviceSettings.l_RestrictActiveXInstall) + $complexDeviceSettings.Add('L_mse7exe', $policySettings.DeviceSettings.l_mse7exe) + $complexDeviceSettings.Add('L_powerpntexe', $policySettings.DeviceSettings.l_powerpntexe) + $complexDeviceSettings.Add('L_spDesignexe', $policySettings.DeviceSettings.l_spDesignexe) + $complexDeviceSettings.Add('L_onenoteexe', $policySettings.DeviceSettings.l_onenoteexe) + $complexDeviceSettings.Add('L_excelexe', $policySettings.DeviceSettings.l_excelexe) + $complexDeviceSettings.Add('L_mspubexe', $policySettings.DeviceSettings.l_mspubexe) + $complexDeviceSettings.Add('L_visioexe', $policySettings.DeviceSettings.l_visioexe) + $complexDeviceSettings.Add('L_exprwdexe', $policySettings.DeviceSettings.l_exprwdexe) + $complexDeviceSettings.Add('L_outlookexe', $policySettings.DeviceSettings.l_outlookexe) + $complexDeviceSettings.Add('L_pptviewexe', $policySettings.DeviceSettings.l_pptviewexe) + $complexDeviceSettings.Add('L_winprojexe', $policySettings.DeviceSettings.l_winprojexe) + $complexDeviceSettings.Add('L_winwordexe', $policySettings.DeviceSettings.l_winwordexe) + $complexDeviceSettings.Add('L_grooveexe', $policySettings.DeviceSettings.l_grooveexe) + $complexDeviceSettings.Add('L_msaccessexe', $policySettings.DeviceSettings.l_msaccessexe) + $complexDeviceSettings.Add('L_RestrictFileDownload', $policySettings.DeviceSettings.l_RestrictFileDownload) + $complexDeviceSettings.Add('L_visioexe5', $policySettings.DeviceSettings.l_visioexe5) + $complexDeviceSettings.Add('L_winprojexe6', $policySettings.DeviceSettings.l_winprojexe6) + $complexDeviceSettings.Add('L_msaccessexe11', $policySettings.DeviceSettings.l_msaccessexe11) + $complexDeviceSettings.Add('L_spdesignexe9', $policySettings.DeviceSettings.l_spdesignexe9) + $complexDeviceSettings.Add('L_excelexe1', $policySettings.DeviceSettings.l_excelexe1) + $complexDeviceSettings.Add('L_powerpntexe3', $policySettings.DeviceSettings.l_powerpntexe3) + $complexDeviceSettings.Add('L_mspubexe2', $policySettings.DeviceSettings.l_mspubexe2) + $complexDeviceSettings.Add('L_exprwdexe10', $policySettings.DeviceSettings.l_exprwdexe10) + $complexDeviceSettings.Add('L_outlookexe8', $policySettings.DeviceSettings.l_outlookexe8) + $complexDeviceSettings.Add('L_pptviewexe4', $policySettings.DeviceSettings.l_pptviewexe4) + $complexDeviceSettings.Add('L_winwordexe7', $policySettings.DeviceSettings.l_winwordexe7) + $complexDeviceSettings.Add('L_onenoteexe12', $policySettings.DeviceSettings.l_onenoteexe12) + $complexDeviceSettings.Add('L_mse7exe13', $policySettings.DeviceSettings.l_mse7exe13) + $complexDeviceSettings.Add('L_grooveexe0', $policySettings.DeviceSettings.l_grooveexe0) + $complexDeviceSettings.Add('L_SavedfromURL', $policySettings.DeviceSettings.l_SavedfromURL) + $complexDeviceSettings.Add('L_pptviewexe158', $policySettings.DeviceSettings.l_pptviewexe158) + $complexDeviceSettings.Add('L_exprwdexe164', $policySettings.DeviceSettings.l_exprwdexe164) + $complexDeviceSettings.Add('L_mse7exe167', $policySettings.DeviceSettings.l_mse7exe167) + $complexDeviceSettings.Add('L_spdesignexe163', $policySettings.DeviceSettings.l_spdesignexe163) + $complexDeviceSettings.Add('L_winprojexe160', $policySettings.DeviceSettings.l_winprojexe160) + $complexDeviceSettings.Add('L_mspubexe156', $policySettings.DeviceSettings.l_mspubexe156) + $complexDeviceSettings.Add('L_visioexe159', $policySettings.DeviceSettings.l_visioexe159) + $complexDeviceSettings.Add('L_winwordexe161', $policySettings.DeviceSettings.l_winwordexe161) + $complexDeviceSettings.Add('L_msaccessexe165', $policySettings.DeviceSettings.l_msaccessexe165) + $complexDeviceSettings.Add('L_onenoteexe166', $policySettings.DeviceSettings.l_onenoteexe166) + $complexDeviceSettings.Add('L_outlookexe162', $policySettings.DeviceSettings.l_outlookexe162) + $complexDeviceSettings.Add('L_grooveexe154', $policySettings.DeviceSettings.l_grooveexe154) + $complexDeviceSettings.Add('L_excelexe155', $policySettings.DeviceSettings.l_excelexe155) + $complexDeviceSettings.Add('L_powerpntexe157', $policySettings.DeviceSettings.l_powerpntexe157) + $complexDeviceSettings.Add('L_ScriptedWindowSecurityRestrictions', $policySettings.DeviceSettings.l_ScriptedWindowSecurityRestrictions) + $complexDeviceSettings.Add('L_exprwdexe94', $policySettings.DeviceSettings.l_exprwdexe94) + $complexDeviceSettings.Add('L_mse7exe97', $policySettings.DeviceSettings.l_mse7exe97) + $complexDeviceSettings.Add('L_mspubexe86', $policySettings.DeviceSettings.l_mspubexe86) + $complexDeviceSettings.Add('L_outlookexe92', $policySettings.DeviceSettings.l_outlookexe92) + $complexDeviceSettings.Add('L_msaccessexe95', $policySettings.DeviceSettings.l_msaccessexe95) + $complexDeviceSettings.Add('L_powerpntexe87', $policySettings.DeviceSettings.l_powerpntexe87) + $complexDeviceSettings.Add('L_grooveexe84', $policySettings.DeviceSettings.l_grooveexe84) + $complexDeviceSettings.Add('L_excelexe85', $policySettings.DeviceSettings.l_excelexe85) + $complexDeviceSettings.Add('L_pptviewexe88', $policySettings.DeviceSettings.l_pptviewexe88) + $complexDeviceSettings.Add('L_spdesignexe93', $policySettings.DeviceSettings.l_spdesignexe93) + $complexDeviceSettings.Add('L_visioexe89', $policySettings.DeviceSettings.l_visioexe89) + $complexDeviceSettings.Add('L_onenoteexe96', $policySettings.DeviceSettings.l_onenoteexe96) + $complexDeviceSettings.Add('L_winprojexe90', $policySettings.DeviceSettings.l_winprojexe90) + $complexDeviceSettings.Add('L_winwordexe91', $policySettings.DeviceSettings.l_winwordexe91) + if ($complexDeviceSettings.values.Where({$null -ne $_}).Count -eq 0) + { + $complexDeviceSettings = $null + } + $policySettings.Remove('DeviceSettings') | Out-Null + + $complexUserSettings = @{} + $complexUserSettings.Add('MicrosoftAccess_Security_TrustCenter_L_BlockMacroExecutionFromInternet', $policySettings.UserSettings.microsoftAccess_Security_TrustCenter_L_BlockMacroExecutionFromInternet) + $complexUserSettings.Add('MicrosoftAccess_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned', $policySettings.UserSettings.microsoftAccess_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned) + $complexUserSettings.Add('MicrosoftAccess_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned', $policySettings.UserSettings.microsoftAccess_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned) + $complexUserSettings.Add('MicrosoftAccess_Security_TrustCenterTrustedLocations_L_AllowTrustedLocationsOnTheNetwork', $policySettings.UserSettings.microsoftAccess_Security_TrustCenterTrustedLocations_L_AllowTrustedLocationsOnTheNetwork) + $complexUserSettings.Add('MicrosoftAccess_Security_TrustCenter_L_VBAWarningsPolicy', $policySettings.UserSettings.microsoftAccess_Security_TrustCenter_L_VBAWarningsPolicy) + $complexUserSettings.Add('MicrosoftAccess_Security_TrustCenter_L_VBAWarningsPolicy_L_Empty', $policySettings.UserSettings.microsoftAccess_Security_TrustCenter_L_VBAWarningsPolicy_L_Empty) + $complexUserSettings.Add('L_Donotshowdataextractionoptionswhenopeningcorruptworkbooks', $policySettings.UserSettings.l_Donotshowdataextractionoptionswhenopeningcorruptworkbooks) + $complexUserSettings.Add('L_Asktoupdateautomaticlinks', $policySettings.UserSettings.l_Asktoupdateautomaticlinks) + $complexUserSettings.Add('L_LoadpicturesfromWebpagesnotcreatedinExcel', $policySettings.UserSettings.l_LoadpicturesfromWebpagesnotcreatedinExcel) + $complexUserSettings.Add('L_DisableAutoRepublish', $policySettings.UserSettings.l_DisableAutoRepublish) + $complexUserSettings.Add('L_DoNotShowAutoRepublishWarningAlert', $policySettings.UserSettings.l_DoNotShowAutoRepublishWarningAlert) + $complexUserSettings.Add('L_Forcefileextenstionstomatch', $policySettings.UserSettings.l_Forcefileextenstionstomatch) + $complexUserSettings.Add('L_Forcefileextenstionstomatch_L_Empty', $policySettings.UserSettings.l_Forcefileextenstionstomatch_L_Empty) + $complexUserSettings.Add('L_DeterminewhethertoforceencryptedExcel', $policySettings.UserSettings.l_DeterminewhethertoforceencryptedExcel) + $complexUserSettings.Add('L_DeterminewhethertoforceencryptedExcelDropID', $policySettings.UserSettings.l_DeterminewhethertoforceencryptedExcelDropID) + $complexUserSettings.Add('L_BlockXLLFromInternet', $policySettings.UserSettings.l_BlockXLLFromInternet) + $complexUserSettings.Add('L_BlockXLLFromInternetEnum', $policySettings.UserSettings.l_BlockXLLFromInternetEnum) + $complexUserSettings.Add('MicrosoftExcel_Security_TrustCenter_L_BlockMacroExecutionFromInternet', $policySettings.UserSettings.microsoftExcel_Security_TrustCenter_L_BlockMacroExecutionFromInternet) + $complexUserSettings.Add('MicrosoftExcel_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned', $policySettings.UserSettings.microsoftExcel_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned) + $complexUserSettings.Add('L_EnableBlockUnsecureQueryFiles', $policySettings.UserSettings.l_EnableBlockUnsecureQueryFiles) + $complexUserSettings.Add('L_DBaseIIIANDIVFiles', $policySettings.UserSettings.l_DBaseIIIANDIVFiles) + $complexUserSettings.Add('L_DBaseIIIANDIVFilesDropID', $policySettings.UserSettings.l_DBaseIIIANDIVFilesDropID) + $complexUserSettings.Add('L_DifAndSylkFiles', $policySettings.UserSettings.l_DifAndSylkFiles) + $complexUserSettings.Add('L_DifAndSylkFilesDropID', $policySettings.UserSettings.l_DifAndSylkFilesDropID) + $complexUserSettings.Add('L_Excel2MacrosheetsAndAddInFiles', $policySettings.UserSettings.l_Excel2MacrosheetsAndAddInFiles) + $complexUserSettings.Add('L_Excel2MacrosheetsAndAddInFilesDropID', $policySettings.UserSettings.l_Excel2MacrosheetsAndAddInFilesDropID) + $complexUserSettings.Add('L_Excel2Worksheets', $policySettings.UserSettings.l_Excel2Worksheets) + $complexUserSettings.Add('L_Excel2WorksheetsDropID', $policySettings.UserSettings.l_Excel2WorksheetsDropID) + $complexUserSettings.Add('L_Excel3MacrosheetsAndAddInFiles', $policySettings.UserSettings.l_Excel3MacrosheetsAndAddInFiles) + $complexUserSettings.Add('L_Excel3MacrosheetsAndAddInFilesDropID', $policySettings.UserSettings.l_Excel3MacrosheetsAndAddInFilesDropID) + $complexUserSettings.Add('L_Excel3Worksheets', $policySettings.UserSettings.l_Excel3Worksheets) + $complexUserSettings.Add('L_Excel3WorksheetsDropID', $policySettings.UserSettings.l_Excel3WorksheetsDropID) + $complexUserSettings.Add('L_Excel4MacrosheetsAndAddInFiles', $policySettings.UserSettings.l_Excel4MacrosheetsAndAddInFiles) + $complexUserSettings.Add('L_Excel4MacrosheetsAndAddInFilesDropID', $policySettings.UserSettings.l_Excel4MacrosheetsAndAddInFilesDropID) + $complexUserSettings.Add('L_Excel4Workbooks', $policySettings.UserSettings.l_Excel4Workbooks) + $complexUserSettings.Add('L_Excel4WorkbooksDropID', $policySettings.UserSettings.l_Excel4WorkbooksDropID) + $complexUserSettings.Add('L_Excel4Worksheets', $policySettings.UserSettings.l_Excel4Worksheets) + $complexUserSettings.Add('L_Excel4WorksheetsDropID', $policySettings.UserSettings.l_Excel4WorksheetsDropID) + $complexUserSettings.Add('L_Excel95Workbooks', $policySettings.UserSettings.l_Excel95Workbooks) + $complexUserSettings.Add('L_Excel95WorkbooksDropID', $policySettings.UserSettings.l_Excel95WorkbooksDropID) + $complexUserSettings.Add('L_Excel9597WorkbooksAndTemplates', $policySettings.UserSettings.l_Excel9597WorkbooksAndTemplates) + $complexUserSettings.Add('L_Excel9597WorkbooksAndTemplatesDropID', $policySettings.UserSettings.l_Excel9597WorkbooksAndTemplatesDropID) + $complexUserSettings.Add('L_Excel972003WorkbooksAndTemplates', $policySettings.UserSettings.l_Excel972003WorkbooksAndTemplates) + $complexUserSettings.Add('L_Excel972003WorkbooksAndTemplatesDropID', $policySettings.UserSettings.l_Excel972003WorkbooksAndTemplatesDropID) + $complexUserSettings.Add('MicrosoftExcel_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehavior', $policySettings.UserSettings.microsoftExcel_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehavior) + $complexUserSettings.Add('MicrosoftExcel_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehaviorDropID', $policySettings.UserSettings.microsoftExcel_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehaviorDropID) + $complexUserSettings.Add('L_WebPagesAndExcel2003XMLSpreadsheets', $policySettings.UserSettings.l_WebPagesAndExcel2003XMLSpreadsheets) + $complexUserSettings.Add('L_WebPagesAndExcel2003XMLSpreadsheetsDropID', $policySettings.UserSettings.l_WebPagesAndExcel2003XMLSpreadsheetsDropID) + $complexUserSettings.Add('L_XL4KillSwitchPolicy', $policySettings.UserSettings.l_XL4KillSwitchPolicy) + $complexUserSettings.Add('L_EnableDataBaseFileProtectedView', $policySettings.UserSettings.l_EnableDataBaseFileProtectedView) + $complexUserSettings.Add('MicrosoftExcel_Security_TrustCenterProtectedView_L_DoNotOpenFilesFromTheInternetZoneInProtectedView', $policySettings.UserSettings.microsoftExcel_Security_TrustCenterProtectedView_L_DoNotOpenFilesFromTheInternetZoneInProtectedView) + $complexUserSettings.Add('MicrosoftExcel_Security_TrustCenterProtectedView_L_DoNotOpenFilesInUnsafeLocationsInProtectedView', $policySettings.UserSettings.microsoftExcel_Security_TrustCenterProtectedView_L_DoNotOpenFilesInUnsafeLocationsInProtectedView) + $complexUserSettings.Add('MicrosoftExcel_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails', $policySettings.UserSettings.microsoftExcel_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails) + $complexUserSettings.Add('MicrosoftExcel_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsStr3', $policySettings.UserSettings.microsoftExcel_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsStr3) + $complexUserSettings.Add('MicrosoftExcel_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsDropID', $policySettings.UserSettings.microsoftExcel_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsDropID) + $complexUserSettings.Add('MicrosoftExcel_Security_TrustCenterProtectedView_L_TurnOffProtectedViewForAttachmentsOpenedFromOutlook', $policySettings.UserSettings.microsoftExcel_Security_TrustCenterProtectedView_L_TurnOffProtectedViewForAttachmentsOpenedFromOutlook) + $complexUserSettings.Add('MicrosoftExcel_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned', $policySettings.UserSettings.microsoftExcel_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned) + $complexUserSettings.Add('MicrosoftExcel_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2', $policySettings.UserSettings.microsoftExcel_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2) + $complexUserSettings.Add('MicrosoftExcel_Security_TrustCenterTrustedLocations_L_AllowTrustedLocationsOnTheNetwork', $policySettings.UserSettings.microsoftExcel_Security_TrustCenterTrustedLocations_L_AllowTrustedLocationsOnTheNetwork) + $complexUserSettings.Add('MicrosoftExcel_Security_TrustCenter_L_VBAWarningsPolicy', $policySettings.UserSettings.microsoftExcel_Security_TrustCenter_L_VBAWarningsPolicy) + $complexUserSettings.Add('L_empty4', $policySettings.UserSettings.l_empty4) + $complexUserSettings.Add('MicrosoftExcel_Security_L_TurnOffFileValidation', $policySettings.UserSettings.microsoftExcel_Security_L_TurnOffFileValidation) + $complexUserSettings.Add('L_WebContentWarningLevel', $policySettings.UserSettings.l_WebContentWarningLevel) + $complexUserSettings.Add('L_WebContentWarningLevelValue', $policySettings.UserSettings.l_WebContentWarningLevelValue) + $complexUserSettings.Add('L_NoExtensibilityCustomizationFromDocumentPolicy', $policySettings.UserSettings.l_NoExtensibilityCustomizationFromDocumentPolicy) + $complexUserSettings.Add('L_NoExtensibilityCustomizationFromDocumentPolicyWord', $policySettings.UserSettings.l_NoExtensibilityCustomizationFromDocumentPolicyWord) + $complexUserSettings.Add('L_NoExtensibilityCustomizationFromDocumentPolicyExcel', $policySettings.UserSettings.l_NoExtensibilityCustomizationFromDocumentPolicyExcel) + $complexUserSettings.Add('L_NoExtensibilityCustomizationFromDocumentPolicyVisio', $policySettings.UserSettings.l_NoExtensibilityCustomizationFromDocumentPolicyVisio) + $complexUserSettings.Add('L_NoExtensibilityCustomizationFromDocumentPolicyPowerPoint', $policySettings.UserSettings.l_NoExtensibilityCustomizationFromDocumentPolicyPowerPoint) + $complexUserSettings.Add('L_NoExtensibilityCustomizationFromDocumentPolicyPublisher', $policySettings.UserSettings.l_NoExtensibilityCustomizationFromDocumentPolicyPublisher) + $complexUserSettings.Add('L_NoExtensibilityCustomizationFromDocumentPolicyOutlook', $policySettings.UserSettings.l_NoExtensibilityCustomizationFromDocumentPolicyOutlook) + $complexUserSettings.Add('L_NoExtensibilityCustomizationFromDocumentPolicyProject', $policySettings.UserSettings.l_NoExtensibilityCustomizationFromDocumentPolicyProject) + $complexUserSettings.Add('L_NoExtensibilityCustomizationFromDocumentPolicyAccess', $policySettings.UserSettings.l_NoExtensibilityCustomizationFromDocumentPolicyAccess) + $complexUserSettings.Add('L_NoExtensibilityCustomizationFromDocumentPolicyInfoPath', $policySettings.UserSettings.l_NoExtensibilityCustomizationFromDocumentPolicyInfoPath) + $complexUserSettings.Add('L_ActiveXControlInitialization', $policySettings.UserSettings.l_ActiveXControlInitialization) + $complexUserSettings.Add('L_ActiveXControlInitializationcolon', $policySettings.UserSettings.l_ActiveXControlInitializationcolon) + $complexUserSettings.Add('L_BasicAuthProxyBehavior', $policySettings.UserSettings.l_BasicAuthProxyBehavior) + $complexUserSettings.Add('L_AllowVbaIntranetRefs', $policySettings.UserSettings.l_AllowVbaIntranetRefs) + $complexUserSettings.Add('L_AutomationSecurity', $policySettings.UserSettings.l_AutomationSecurity) + $complexUserSettings.Add('L_SettheAutomationSecuritylevel', $policySettings.UserSettings.l_SettheAutomationSecuritylevel) + $complexUserSettings.Add('L_AuthenticationFBABehavior', $policySettings.UserSettings.l_AuthenticationFBABehavior) + $complexUserSettings.Add('L_AuthenticationFBAEnabledHostsID', $policySettings.UserSettings.l_AuthenticationFBAEnabledHostsID) + $complexUserSettings.Add('L_authenticationFBABehaviorEnum', $policySettings.UserSettings.l_authenticationFBABehaviorEnum) + $complexUserSettings.Add('L_DisableStrictVbaRefsSecurityPolicy', $policySettings.UserSettings.l_DisableStrictVbaRefsSecurityPolicy) + $complexUserSettings.Add('L_DisableallTrustBarnotificationsfor', $policySettings.UserSettings.l_DisableallTrustBarnotificationsfor) + $complexUserSettings.Add('L_Encryptiontypeforirm', $policySettings.UserSettings.l_Encryptiontypeforirm) + $complexUserSettings.Add('L_Encryptiontypeforirmcolon', $policySettings.UserSettings.l_Encryptiontypeforirmcolon) + $complexUserSettings.Add('L_Encryptiontypeforpasswordprotectedoffice972003', $policySettings.UserSettings.l_Encryptiontypeforpasswordprotectedoffice972003) + $complexUserSettings.Add('L_encryptiontypecolon318', $policySettings.UserSettings.l_encryptiontypecolon318) + $complexUserSettings.Add('L_Encryptiontypeforpasswordprotectedofficeopen', $policySettings.UserSettings.l_Encryptiontypeforpasswordprotectedofficeopen) + $complexUserSettings.Add('L_Encryptiontypecolon', $policySettings.UserSettings.l_Encryptiontypecolon) + $complexUserSettings.Add('L_LoadControlsinForms3', $policySettings.UserSettings.l_LoadControlsinForms3) + $complexUserSettings.Add('L_LoadControlsinForms3colon', $policySettings.UserSettings.l_LoadControlsinForms3colon) + $complexUserSettings.Add('L_MacroRuntimeScanScope', $policySettings.UserSettings.l_MacroRuntimeScanScope) + $complexUserSettings.Add('L_MacroRuntimeScanScopeEnum', $policySettings.UserSettings.l_MacroRuntimeScanScopeEnum) + $complexUserSettings.Add('L_Protectdocumentmetadataforrightsmanaged', $policySettings.UserSettings.l_Protectdocumentmetadataforrightsmanaged) + $complexUserSettings.Add('L_Allowmixofpolicyanduserlocations', $policySettings.UserSettings.l_Allowmixofpolicyanduserlocations) + $complexUserSettings.Add('L_DisabletheOfficeclientfrompolling', $policySettings.UserSettings.l_DisabletheOfficeclientfrompolling) + $complexUserSettings.Add('L_DisableSmartDocumentsuseofmanifests', $policySettings.UserSettings.l_DisableSmartDocumentsuseofmanifests) + $complexUserSettings.Add('L_OutlookSecurityMode', $policySettings.UserSettings.l_OutlookSecurityMode) + $complexUserSettings.Add('L_OOMAddressAccess', $policySettings.UserSettings.l_OOMAddressAccess) + $complexUserSettings.Add('L_OOMAddressAccess_Setting', $policySettings.UserSettings.l_OOMAddressAccess_Setting) + $complexUserSettings.Add('L_OOMMeetingTaskRequest', $policySettings.UserSettings.l_OOMMeetingTaskRequest) + $complexUserSettings.Add('L_OOMMeetingTaskRequest_Setting', $policySettings.UserSettings.l_OOMMeetingTaskRequest_Setting) + $complexUserSettings.Add('L_OOMSend', $policySettings.UserSettings.l_OOMSend) + $complexUserSettings.Add('L_OOMSend_Setting', $policySettings.UserSettings.l_OOMSend_Setting) + $complexUserSettings.Add('L_Preventusersfromcustomizingattachmentsecuritysettings', $policySettings.UserSettings.l_Preventusersfromcustomizingattachmentsecuritysettings) + $complexUserSettings.Add('L_RetrievingCRLsCertificateRevocationLists', $policySettings.UserSettings.l_RetrievingCRLsCertificateRevocationLists) + $complexUserSettings.Add('L_empty31', $policySettings.UserSettings.l_empty31) + $complexUserSettings.Add('L_OOMFormula', $policySettings.UserSettings.l_OOMFormula) + $complexUserSettings.Add('L_OOMFormula_Setting', $policySettings.UserSettings.l_OOMFormula_Setting) + $complexUserSettings.Add('L_AuthenticationwithExchangeServer', $policySettings.UserSettings.l_AuthenticationwithExchangeServer) + $complexUserSettings.Add('L_SelecttheauthenticationwithExchangeserver', $policySettings.UserSettings.l_SelecttheauthenticationwithExchangeserver) + $complexUserSettings.Add('L_EnableRPCEncryption', $policySettings.UserSettings.l_EnableRPCEncryption) + $complexUserSettings.Add('L_Enablelinksinemailmessages', $policySettings.UserSettings.l_Enablelinksinemailmessages) + $complexUserSettings.Add('L_OOMAddressBook', $policySettings.UserSettings.l_OOMAddressBook) + $complexUserSettings.Add('L_OOMAddressBook_Setting', $policySettings.UserSettings.l_OOMAddressBook_Setting) + $complexUserSettings.Add('L_OutlookSecurityPolicy', $policySettings.UserSettings.l_OutlookSecurityPolicy) + $complexUserSettings.Add('L_AllowUsersToLowerAttachments', $policySettings.UserSettings.l_AllowUsersToLowerAttachments) + $complexUserSettings.Add('L_AllowActiveXOneOffForms', $policySettings.UserSettings.l_AllowActiveXOneOffForms) + $complexUserSettings.Add('L_empty29', $policySettings.UserSettings.l_empty29) + $complexUserSettings.Add('L_EnableScriptsInOneOffForms', $policySettings.UserSettings.l_EnableScriptsInOneOffForms) + $complexUserSettings.Add('L_Level2RemoveFilePolicy', $policySettings.UserSettings.l_Level2RemoveFilePolicy) + $complexUserSettings.Add('L_removedextensions25', $policySettings.UserSettings.l_removedextensions25) + $complexUserSettings.Add('L_MSGUnicodeformatwhendraggingtofilesystem', $policySettings.UserSettings.l_MSGUnicodeformatwhendraggingtofilesystem) + $complexUserSettings.Add('L_OnExecuteCustomActionOOM', $policySettings.UserSettings.l_OnExecuteCustomActionOOM) + $complexUserSettings.Add('L_OnExecuteCustomActionOOM_Setting', $policySettings.UserSettings.l_OnExecuteCustomActionOOM_Setting) + $complexUserSettings.Add('L_DisableOutlookobjectmodelscriptsforpublicfolders', $policySettings.UserSettings.l_DisableOutlookobjectmodelscriptsforpublicfolders) + $complexUserSettings.Add('L_BlockInternet', $policySettings.UserSettings.l_BlockInternet) + $complexUserSettings.Add('L_SecurityLevelOutlook', $policySettings.UserSettings.l_SecurityLevelOutlook) + $complexUserSettings.Add('L_SecurityLevel', $policySettings.UserSettings.l_SecurityLevel) + $complexUserSettings.Add('L_Level1RemoveFilePolicy', $policySettings.UserSettings.l_Level1RemoveFilePolicy) + $complexUserSettings.Add('L_RemovedExtensions', $policySettings.UserSettings.l_RemovedExtensions) + $complexUserSettings.Add('L_SignatureWarning', $policySettings.UserSettings.l_SignatureWarning) + $complexUserSettings.Add('L_signaturewarning30', $policySettings.UserSettings.l_signaturewarning30) + $complexUserSettings.Add('L_Level1Attachments', $policySettings.UserSettings.l_Level1Attachments) + $complexUserSettings.Add('L_Minimumencryptionsettings', $policySettings.UserSettings.l_Minimumencryptionsettings) + $complexUserSettings.Add('L_Minimumkeysizeinbits', $policySettings.UserSettings.l_Minimumkeysizeinbits) + $complexUserSettings.Add('L_DisableOutlookobjectmodelscripts', $policySettings.UserSettings.l_DisableOutlookobjectmodelscripts) + $complexUserSettings.Add('L_OOMSaveAs', $policySettings.UserSettings.l_OOMSaveAs) + $complexUserSettings.Add('L_OOMSaveAs_Setting', $policySettings.UserSettings.l_OOMSaveAs_Setting) + $complexUserSettings.Add('L_JunkEmailprotectionlevel', $policySettings.UserSettings.l_JunkEmailprotectionlevel) + $complexUserSettings.Add('L_Selectlevel', $policySettings.UserSettings.l_Selectlevel) + $complexUserSettings.Add('L_RunPrograms', $policySettings.UserSettings.l_RunPrograms) + $complexUserSettings.Add('L_RunPrograms_L_Empty', $policySettings.UserSettings.l_RunPrograms_L_Empty) + $complexUserSettings.Add('L_Determinewhethertoforceencryptedppt', $policySettings.UserSettings.l_Determinewhethertoforceencryptedppt) + $complexUserSettings.Add('L_DeterminewhethertoforceencryptedpptDropID', $policySettings.UserSettings.l_DeterminewhethertoforceencryptedpptDropID) + $complexUserSettings.Add('MicrosoftPowerPoint_Security_TrustCenter_L_BlockMacroExecutionFromInternet', $policySettings.UserSettings.microsoftPowerPoint_Security_TrustCenter_L_BlockMacroExecutionFromInternet) + $complexUserSettings.Add('MicrosoftPowerPoint_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned', $policySettings.UserSettings.microsoftPowerPoint_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned) + $complexUserSettings.Add('L_PowerPoint972003PresentationsShowsTemplatesandAddInFiles', $policySettings.UserSettings.l_PowerPoint972003PresentationsShowsTemplatesandAddInFiles) + $complexUserSettings.Add('L_PowerPoint972003PresentationsShowsTemplatesandAddInFilesDropID', $policySettings.UserSettings.l_PowerPoint972003PresentationsShowsTemplatesandAddInFilesDropID) + $complexUserSettings.Add('MicrosoftPowerPoint_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehavior', $policySettings.UserSettings.microsoftPowerPoint_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehavior) + $complexUserSettings.Add('MicrosoftPowerPoint_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehaviorDropID', $policySettings.UserSettings.microsoftPowerPoint_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehaviorDropID) + $complexUserSettings.Add('MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_DoNotOpenFilesFromTheInternetZoneInProtectedView', $policySettings.UserSettings.microsoftPowerPoint_Security_TrustCenterProtectedView_L_DoNotOpenFilesFromTheInternetZoneInProtectedView) + $complexUserSettings.Add('MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_DoNotOpenFilesInUnsafeLocationsInProtectedView', $policySettings.UserSettings.microsoftPowerPoint_Security_TrustCenterProtectedView_L_DoNotOpenFilesInUnsafeLocationsInProtectedView) + $complexUserSettings.Add('MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails', $policySettings.UserSettings.microsoftPowerPoint_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails) + $complexUserSettings.Add('MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsStr3', $policySettings.UserSettings.microsoftPowerPoint_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsStr3) + $complexUserSettings.Add('MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsDropID', $policySettings.UserSettings.microsoftPowerPoint_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsDropID) + $complexUserSettings.Add('MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_TurnOffProtectedViewForAttachmentsOpenedFromOutlook', $policySettings.UserSettings.microsoftPowerPoint_Security_TrustCenterProtectedView_L_TurnOffProtectedViewForAttachmentsOpenedFromOutlook) + $complexUserSettings.Add('MicrosoftPowerPoint_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned', $policySettings.UserSettings.microsoftPowerPoint_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned) + $complexUserSettings.Add('MicrosoftPowerPoint_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2', $policySettings.UserSettings.microsoftPowerPoint_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2) + $complexUserSettings.Add('MicrosoftPowerPoint_Security_TrustCenterTrustedLocations_L_AllowTrustedLocationsOnTheNetwork', $policySettings.UserSettings.microsoftPowerPoint_Security_TrustCenterTrustedLocations_L_AllowTrustedLocationsOnTheNetwork) + $complexUserSettings.Add('MicrosoftPowerPoint_Security_TrustCenter_L_VBAWarningsPolicy', $policySettings.UserSettings.microsoftPowerPoint_Security_TrustCenter_L_VBAWarningsPolicy) + $complexUserSettings.Add('L_empty3', $policySettings.UserSettings.l_empty3) + $complexUserSettings.Add('MicrosoftPowerPoint_Security_L_TurnOffFileValidation', $policySettings.UserSettings.microsoftPowerPoint_Security_L_TurnOffFileValidation) + $complexUserSettings.Add('MicrosoftProject_Security_TrustCenter_L_AllowTrustedLocationsOnTheNetwork', $policySettings.UserSettings.microsoftProject_Security_TrustCenter_L_AllowTrustedLocationsOnTheNetwork) + $complexUserSettings.Add('MicrosoftProject_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned', $policySettings.UserSettings.microsoftProject_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned) + $complexUserSettings.Add('MicrosoftProject_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned', $policySettings.UserSettings.microsoftProject_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned) + $complexUserSettings.Add('MicrosoftProject_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2', $policySettings.UserSettings.microsoftProject_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2) + $complexUserSettings.Add('MicrosoftProject_Security_TrustCenter_L_VBAWarningsPolicy', $policySettings.UserSettings.microsoftProject_Security_TrustCenter_L_VBAWarningsPolicy) + $complexUserSettings.Add('MicrosoftProject_Security_TrustCenter_L_VBAWarningsPolicy_L_Empty', $policySettings.UserSettings.microsoftProject_Security_TrustCenter_L_VBAWarningsPolicy_L_Empty) + $complexUserSettings.Add('L_PublisherAutomationSecurityLevel', $policySettings.UserSettings.l_PublisherAutomationSecurityLevel) + $complexUserSettings.Add('L_PublisherAutomationSecurityLevel_L_Empty', $policySettings.UserSettings.l_PublisherAutomationSecurityLevel_L_Empty) + $complexUserSettings.Add('MicrosoftPublisherV3_Security_TrustCenter_L_BlockMacroExecutionFromInternet', $policySettings.UserSettings.microsoftPublisherV3_Security_TrustCenter_L_BlockMacroExecutionFromInternet) + $complexUserSettings.Add('MicrosoftPublisherV2_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned', $policySettings.UserSettings.microsoftPublisherV2_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned) + $complexUserSettings.Add('MicrosoftPublisherV2_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned', $policySettings.UserSettings.microsoftPublisherV2_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned) + $complexUserSettings.Add('MicrosoftPublisherV2_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2', $policySettings.UserSettings.microsoftPublisherV2_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2) + $complexUserSettings.Add('MicrosoftPublisherV2_Security_TrustCenter_L_VBAWarningsPolicy', $policySettings.UserSettings.microsoftPublisherV2_Security_TrustCenter_L_VBAWarningsPolicy) + $complexUserSettings.Add('L_empty0', $policySettings.UserSettings.l_empty0) + $complexUserSettings.Add('MicrosoftVisio_Security_TrustCenter_L_AllowTrustedLocationsOnTheNetwork', $policySettings.UserSettings.microsoftVisio_Security_TrustCenter_L_AllowTrustedLocationsOnTheNetwork) + $complexUserSettings.Add('MicrosoftVisio_Security_TrustCenter_L_BlockMacroExecutionFromInternet', $policySettings.UserSettings.microsoftVisio_Security_TrustCenter_L_BlockMacroExecutionFromInternet) + $complexUserSettings.Add('MicrosoftVisio_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned', $policySettings.UserSettings.microsoftVisio_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned) + $complexUserSettings.Add('L_Visio2000Files', $policySettings.UserSettings.l_Visio2000Files) + $complexUserSettings.Add('L_Visio2000FilesDropID', $policySettings.UserSettings.l_Visio2000FilesDropID) + $complexUserSettings.Add('L_Visio2003Files', $policySettings.UserSettings.l_Visio2003Files) + $complexUserSettings.Add('L_Visio2003FilesDropID', $policySettings.UserSettings.l_Visio2003FilesDropID) + $complexUserSettings.Add('L_Visio50AndEarlierFiles', $policySettings.UserSettings.l_Visio50AndEarlierFiles) + $complexUserSettings.Add('L_Visio50AndEarlierFilesDropID', $policySettings.UserSettings.l_Visio50AndEarlierFilesDropID) + $complexUserSettings.Add('MicrosoftVisio_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned', $policySettings.UserSettings.microsoftVisio_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned) + $complexUserSettings.Add('MicrosoftVisio_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2', $policySettings.UserSettings.microsoftVisio_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2) + $complexUserSettings.Add('MicrosoftVisio_Security_TrustCenter_L_VBAWarningsPolicy', $policySettings.UserSettings.microsoftVisio_Security_TrustCenter_L_VBAWarningsPolicy) + $complexUserSettings.Add('MicrosoftVisio_Security_TrustCenter_L_VBAWarningsPolicy_L_Empty', $policySettings.UserSettings.microsoftVisio_Security_TrustCenter_L_VBAWarningsPolicy_L_Empty) + $complexUserSettings.Add('MicrosoftWord_Security_TrustCenter_L_BlockMacroExecutionFromInternet', $policySettings.UserSettings.microsoftWord_Security_TrustCenter_L_BlockMacroExecutionFromInternet) + $complexUserSettings.Add('MicrosoftWord_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned', $policySettings.UserSettings.microsoftWord_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned) + $complexUserSettings.Add('L_AllowDDE', $policySettings.UserSettings.l_AllowDDE) + $complexUserSettings.Add('L_AllowDDEDropID', $policySettings.UserSettings.l_AllowDDEDropID) + $complexUserSettings.Add('MicrosoftWord_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehavior', $policySettings.UserSettings.microsoftWord_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehavior) + $complexUserSettings.Add('MicrosoftWord_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehaviorDropID', $policySettings.UserSettings.microsoftWord_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehaviorDropID) + $complexUserSettings.Add('L_Word2AndEarlierBinaryDocumentsAndTemplates', $policySettings.UserSettings.l_Word2AndEarlierBinaryDocumentsAndTemplates) + $complexUserSettings.Add('L_Word2AndEarlierBinaryDocumentsAndTemplatesDropID', $policySettings.UserSettings.l_Word2AndEarlierBinaryDocumentsAndTemplatesDropID) + $complexUserSettings.Add('L_Word2000BinaryDocumentsAndTemplates', $policySettings.UserSettings.l_Word2000BinaryDocumentsAndTemplates) + $complexUserSettings.Add('L_Word2000BinaryDocumentsAndTemplatesDropID', $policySettings.UserSettings.l_Word2000BinaryDocumentsAndTemplatesDropID) + $complexUserSettings.Add('L_Word2003BinaryDocumentsAndTemplates', $policySettings.UserSettings.l_Word2003BinaryDocumentsAndTemplates) + $complexUserSettings.Add('L_Word2003BinaryDocumentsAndTemplatesDropID', $policySettings.UserSettings.l_Word2003BinaryDocumentsAndTemplatesDropID) + $complexUserSettings.Add('L_Word2007AndLaterBinaryDocumentsAndTemplates', $policySettings.UserSettings.l_Word2007AndLaterBinaryDocumentsAndTemplates) + $complexUserSettings.Add('L_Word2007AndLaterBinaryDocumentsAndTemplatesDropID', $policySettings.UserSettings.l_Word2007AndLaterBinaryDocumentsAndTemplatesDropID) + $complexUserSettings.Add('L_Word6Pt0BinaryDocumentsAndTemplates', $policySettings.UserSettings.l_Word6Pt0BinaryDocumentsAndTemplates) + $complexUserSettings.Add('L_Word6Pt0BinaryDocumentsAndTemplatesDropID', $policySettings.UserSettings.l_Word6Pt0BinaryDocumentsAndTemplatesDropID) + $complexUserSettings.Add('L_Word95BinaryDocumentsAndTemplates', $policySettings.UserSettings.l_Word95BinaryDocumentsAndTemplates) + $complexUserSettings.Add('L_Word95BinaryDocumentsAndTemplatesDropID', $policySettings.UserSettings.l_Word95BinaryDocumentsAndTemplatesDropID) + $complexUserSettings.Add('L_Word97BinaryDocumentsAndTemplates', $policySettings.UserSettings.l_Word97BinaryDocumentsAndTemplates) + $complexUserSettings.Add('L_Word97BinaryDocumentsAndTemplatesDropID', $policySettings.UserSettings.l_Word97BinaryDocumentsAndTemplatesDropID) + $complexUserSettings.Add('L_WordXPBinaryDocumentsAndTemplates', $policySettings.UserSettings.l_WordXPBinaryDocumentsAndTemplates) + $complexUserSettings.Add('L_WordXPBinaryDocumentsAndTemplatesDropID', $policySettings.UserSettings.l_WordXPBinaryDocumentsAndTemplatesDropID) + $complexUserSettings.Add('MicrosoftWord_Security_TrustCenterProtectedView_L_DoNotOpenFilesFromTheInternetZoneInProtectedView', $policySettings.UserSettings.microsoftWord_Security_TrustCenterProtectedView_L_DoNotOpenFilesFromTheInternetZoneInProtectedView) + $complexUserSettings.Add('MicrosoftWord_Security_TrustCenterProtectedView_L_DoNotOpenFilesInUnsafeLocationsInProtectedView', $policySettings.UserSettings.microsoftWord_Security_TrustCenterProtectedView_L_DoNotOpenFilesInUnsafeLocationsInProtectedView) + $complexUserSettings.Add('MicrosoftWord_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails', $policySettings.UserSettings.microsoftWord_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails) + $complexUserSettings.Add('MicrosoftWord_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsDropID', $policySettings.UserSettings.microsoftWord_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsDropID) + $complexUserSettings.Add('MicrosoftWord_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsStr3', $policySettings.UserSettings.microsoftWord_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsStr3) + $complexUserSettings.Add('MicrosoftWord_Security_TrustCenterProtectedView_L_TurnOffProtectedViewForAttachmentsOpenedFromOutlook', $policySettings.UserSettings.microsoftWord_Security_TrustCenterProtectedView_L_TurnOffProtectedViewForAttachmentsOpenedFromOutlook) + $complexUserSettings.Add('MicrosoftWord_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned', $policySettings.UserSettings.microsoftWord_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned) + $complexUserSettings.Add('MicrosoftWord_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2', $policySettings.UserSettings.microsoftWord_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2) + $complexUserSettings.Add('L_DeterminewhethertoforceencryptedWord', $policySettings.UserSettings.l_DeterminewhethertoforceencryptedWord) + $complexUserSettings.Add('L_DeterminewhethertoforceencryptedWordDropID', $policySettings.UserSettings.l_DeterminewhethertoforceencryptedWordDropID) + $complexUserSettings.Add('MicrosoftWord_Security_TrustCenter_L_VBAWarningsPolicy', $policySettings.UserSettings.microsoftWord_Security_TrustCenter_L_VBAWarningsPolicy) + $complexUserSettings.Add('L_empty19', $policySettings.UserSettings.l_empty19) + $complexUserSettings.Add('MicrosoftWord_Security_L_TurnOffFileValidation', $policySettings.UserSettings.microsoftWord_Security_L_TurnOffFileValidation) + $complexUserSettings.Add('MicrosoftWord_Security_TrustCenterTrustedLocations_L_AllowTrustedLocationsOnTheNetwork', $policySettings.UserSettings.microsoftWord_Security_TrustCenterTrustedLocations_L_AllowTrustedLocationsOnTheNetwork) + if ($complexUserSettings.values.Where({$null -ne $_}).Count -eq 0) + { + $complexUserSettings = $null + } + $policySettings.Remove('UserSettings') | Out-Null + #endregion + + $results = @{ + #region resource generator code + Description = $getValue.Description + DisplayName = $getValue.Name + RoleScopeTagIds = $getValue.RoleScopeTagIds + Id = $getValue.Id + DeviceSettings = $complexDeviceSettings + UserSettings = $complexUserSettings + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + #endregion + } + $results += $policySettings + + $assignmentsValues = Get-MgBetaDeviceManagementConfigurationPolicyAssignment -DeviceManagementConfigurationPolicyId $Id + $assignmentResult = @() + if ($assignmentsValues.Count -gt 0) + { + $assignmentResult += ConvertFrom-IntunePolicyAssignment -Assignments $assignmentsValues -IncludeDeviceFilter $true + } + $results.Add('Assignments', $assignmentResult) + + return [System.Collections.Hashtable] $results + } + catch + { + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $DeviceSettings, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $UserSettings, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + #endregion + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + + $BoundParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + $templateReferenceId = '90316f12-246d-44c6-a767-f87692e86083_2' + $platforms = 'windows10' + $technologies = 'mdm' + + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + Write-Verbose -Message "Creating an Intune Security Baseline Microsoft365 Apps For Enterprise with Name {$DisplayName}" + $BoundParameters.Remove("Assignments") | Out-Null + + $settings = Get-IntuneSettingCatalogPolicySetting ` + -DSCParams ([System.Collections.Hashtable]$BoundParameters) ` + -TemplateId $templateReferenceId ` + -ContainsDeviceAndUserSettings + + $createParameters = @{ + Name = $DisplayName + Description = $Description + TemplateReference = @{ templateId = $templateReferenceId } + Platforms = $platforms + Technologies = $technologies + Settings = $settings + } + + #region resource generator code + $policy = New-MgBetaDeviceManagementConfigurationPolicy -BodyParameter $createParameters + + if ($policy.Id) + { + $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + Update-DeviceConfigurationPolicyAssignment ` + -DeviceConfigurationPolicyId $policy.Id ` + -Targets $assignmentsHash ` + -Repository 'deviceManagement/configurationPolicies' + } + #endregion + } + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Updating the Intune Security Baseline Microsoft365 Apps For Enterprise with Id {$($currentInstance.Id)}" + $BoundParameters.Remove("Assignments") | Out-Null + + $settings = Get-IntuneSettingCatalogPolicySetting ` + -DSCParams ([System.Collections.Hashtable]$BoundParameters) ` + -TemplateId $templateReferenceId ` + -ContainsDeviceAndUserSettings + + Update-IntuneDeviceConfigurationPolicy ` + -DeviceConfigurationPolicyId $currentInstance.Id ` + -Name $DisplayName ` + -Description $Description ` + -TemplateReferenceId $templateReferenceId ` + -Platforms $platforms ` + -Technologies $technologies ` + -Settings $settings + + #region resource generator code + $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + Update-DeviceConfigurationPolicyAssignment ` + -DeviceConfigurationPolicyId $currentInstance.Id ` + -Targets $assignmentsHash ` + -Repository 'deviceManagement/configurationPolicies' + #endregion + } + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Removing the Intune Security Baseline Microsoft365 Apps For Enterprise with Id {$($currentInstance.Id)}" + #region resource generator code + Remove-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $currentInstance.Id + #endregion + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $DeviceSettings, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $UserSettings, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + #endregion + + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + Write-Verbose -Message "Testing configuration of the Intune Security Baseline Microsoft365 Apps For Enterprise with Id {$Id} and Name {$DisplayName}" + + $CurrentValues = Get-TargetResource @PSBoundParameters + [Hashtable]$ValuesToCheck = @{} + $MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object { + if ($_.Key -notlike '*Variable' -or $_.Key -notin @('Verbose', 'Debug', 'ErrorAction', 'WarningAction', 'InformationAction')) + { + if ($null -ne $CurrentValues[$_.Key] -or $null -ne $PSBoundParameters[$_.Key]) + { + $ValuesToCheck.Add($_.Key, $null) + if (-not $PSBoundParameters.ContainsKey($_.Key)) + { + $PSBoundParameters.Add($_.Key, $null) + } + } + } + } + + if ($CurrentValues.Ensure -ne $Ensure) + { + Write-Verbose -Message "Test-TargetResource returned $false" + return $false + } + $testResult = $true + + #Compare Cim instances + foreach ($key in $PSBoundParameters.Keys) + { + $source = $PSBoundParameters.$key + $target = $CurrentValues.$key + if ($null -ne $source -and $source.GetType().Name -like '*CimInstance*') + { + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) -Verbose + + if (-not $testResult) + { + Write-Verbose "$key is different" -Verbose + break + } + + $ValuesToCheck.Remove($key) | Out-Null + } + } + + $ValuesToCheck.Remove('Id') | Out-Null + $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + + if ($testResult) + { + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + } + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + #region resource generator code + $policyTemplateID = "90316f12-246d-44c6-a767-f87692e86083_2" + [array]$getValue = Get-MgBetaDeviceManagementConfigurationPolicy ` + -Filter $Filter ` + -All ` + -ErrorAction Stop | Where-Object ` + -FilterScript { + $_.TemplateReference.TemplateId -eq $policyTemplateID + } + #endregion + + $i = 1 + $dscContent = '' + if ($getValue.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $getValue) + { + $displayedKey = $config.Id + if (-not [String]::IsNullOrEmpty($config.displayName)) + { + $displayedKey = $config.displayName + } + elseif (-not [string]::IsNullOrEmpty($config.name)) + { + $displayedKey = $config.name + } + Write-Host " |---[$i/$($getValue.Count)] $displayedKey" -NoNewline + $params = @{ + Id = $config.Id + DisplayName = $config.Name + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + if ($null -ne $Results.DeviceSettings) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.DeviceSettings ` + -CIMInstanceName 'MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneSecurityBaselineMicrosoft365AppsForEnterprise' + if (-not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.DeviceSettings = $complexTypeStringResult + } + else + { + $Results.Remove('DeviceSettings') | Out-Null + } + } + if ($null -ne $Results.UserSettings) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.UserSettings ` + -CIMInstanceName 'MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneSecurityBaselineMicrosoft365AppsForEnterprise' + if (-not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.UserSettings = $complexTypeStringResult + } + else + { + $Results.Remove('UserSettings') | Out-Null + } + } + + if ($Results.Assignments) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString -ComplexObject $Results.Assignments -CIMInstanceName DeviceManagementConfigurationPolicyAssignments + if ($complexTypeStringResult) + { + $Results.Assignments = $complexTypeStringResult + } + else + { + $Results.Remove('Assignments') | Out-Null + } + } + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + if ($Results.DeviceSettings) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "DeviceSettings" -IsCIMArray:$False + } + if ($Results.UserSettings) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "UserSettings" -IsCIMArray:$False + } + + if ($Results.Assignments) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "Assignments" -IsCIMArray:$true + } + + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise/MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise/MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise.schema.mof new file mode 100644 index 0000000000..a7811bfc7d --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise/MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise.schema.mof @@ -0,0 +1,476 @@ +[ClassVersion("1.0.0.0")] +class MSFT_DeviceManagementConfigurationPolicyAssignments +{ + [Write, Description("The type of the target assignment."), ValueMap{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget","#microsoft.graph.configurationManagerCollectionAssignmentTarget"}, Values{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget","#microsoft.graph.configurationManagerCollectionAssignmentTarget"}] String dataType; + [Write, Description("The type of filter of the target assignment i.e. Exclude or Include. Possible values are:none, include, exclude."), ValueMap{"none","include","exclude"}, Values{"none","include","exclude"}] String deviceAndAppManagementAssignmentFilterType; + [Write, Description("The Id of the filter for the target assignment.")] String deviceAndAppManagementAssignmentFilterId; + [Write, Description("The group Id that is the target of the assignment.")] String groupId; + [Write, Description("The group Display Name that is the target of the assignment.")] String groupDisplayName; + [Write, Description("The collection Id that is the target of the assignment.(ConfigMgr)")] String collectionId; +}; + +[ClassVersion("1.0.0.0")] +class MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneSecurityBaselineMicrosoft365AppsForEnterprise +{ + [Write, Description("Block Flash activation in Office documents (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String Pol_SecGuide_A001_Block_Flash; + [Write, Description("Block Flash player in Office (Device) - Depends on Pol_SecGuide_A001_Block_Flash (block all flash activation: Block all activation, block embedded flash activation only: Block embedding/linking, allow other activation, allow all flash activation: Allow all activation)"), ValueMap{"block all flash activation", "block embedded flash activation only", "allow all flash activation"}, Values{"block all flash activation", "block embedded flash activation only", "allow all flash activation"}] String Pol_SecGuide_Block_Flash; + [Write, Description("Restrict legacy JScript execution for Office (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String Pol_SecGuide_Legacy_JScript; + [Write, Description("PowerPoint: (Device) - Depends on Pol_SecGuide_Legacy_JScript")] SInt32 POL_SG_powerpnt; + [Write, Description("OneNote: (Device) - Depends on Pol_SecGuide_Legacy_JScript")] SInt32 POL_SG_onenote; + [Write, Description("Publisher: (Device) - Depends on Pol_SecGuide_Legacy_JScript")] SInt32 POL_SG_mspub; + [Write, Description("Access: (Device) - Depends on Pol_SecGuide_Legacy_JScript")] SInt32 POL_SG_msaccess; + [Write, Description("Project: (Device) - Depends on Pol_SecGuide_Legacy_JScript")] SInt32 POL_SG_winproj; + [Write, Description("Visio: (Device) - Depends on Pol_SecGuide_Legacy_JScript")] SInt32 POL_SG_visio; + [Write, Description("Outlook: (Device) - Depends on Pol_SecGuide_Legacy_JScript")] SInt32 POL_SG_outlook; + [Write, Description("Word: (Device) - Depends on Pol_SecGuide_Legacy_JScript")] SInt32 POL_SG_winword; + [Write, Description("Excel: (Device) - Depends on Pol_SecGuide_Legacy_JScript")] SInt32 POL_SG_excel; + [Write, Description("Configure SIP security mode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_PolicyEnableSIPHighSecurityMode; + [Write, Description("Disable HTTP fallback for SIP connection (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_PolicyDisableHttpConnect; + [Write, Description("Add-on Management (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_AddonManagement; + [Write, Description("powerpnt.exe (Device) - Depends on L_AddonManagement (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_powerpntexe17; + [Write, Description("excel.exe (Device) - Depends on L_AddonManagement (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_excelexe15; + [Write, Description("visio.exe (Device) - Depends on L_AddonManagement (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_visioexe19; + [Write, Description("onent.exe (Device) - Depends on L_AddonManagement (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_onenoteexe26; + [Write, Description("outlook.exe (Device) - Depends on L_AddonManagement (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_outlookexe22; + [Write, Description("pptview.exe (Device) - Depends on L_AddonManagement (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_pptviewexe18; + [Write, Description("winword.exe (Device) - Depends on L_AddonManagement (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winwordexe21; + [Write, Description("exprwd.exe (Device) - Depends on L_AddonManagement (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_exprwdexe24; + [Write, Description("spDesign.exe (Device) - Depends on L_AddonManagement (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_spdesignexe23; + [Write, Description("winproj.exe (Device) - Depends on L_AddonManagement (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winprojexe20; + [Write, Description("groove.exe (Device) - Depends on L_AddonManagement (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_grooveexe14; + [Write, Description("mspub.exe (Device) - Depends on L_AddonManagement (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mspubexe16; + [Write, Description("mse7.exe (Device) - Depends on L_AddonManagement (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mse7exe27; + [Write, Description("msaccess.exe (Device) - Depends on L_AddonManagement (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_msaccessexe25; + [Write, Description("Consistent Mime Handling (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_ConsistentMimeHandling; + [Write, Description("excel.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_excelexe43; + [Write, Description("spDesign.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_spdesignexe51; + [Write, Description("onent.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_onenoteexe54; + [Write, Description("outlook.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_outlookexe50; + [Write, Description("pptview.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_pptviewexe46; + [Write, Description("mspub.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mspubexe44; + [Write, Description("visio.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_visioexe47; + [Write, Description("winproj.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winprojexe48; + [Write, Description("msaccess.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_msaccessexe53; + [Write, Description("powerpnt.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_powerpntexe45; + [Write, Description("groove.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_grooveexe42; + [Write, Description("mse7.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mse7exe55; + [Write, Description("winword.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winwordexe49; + [Write, Description("exprwd.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_exprwdexe52; + [Write, Description("Disable user name and password (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Disableusernameandpassword; + [Write, Description("excel.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_excelexe127; + [Write, Description("groove.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_grooveexe126; + [Write, Description("onent.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_onenoteexe138; + [Write, Description("mse7.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mse7exe139; + [Write, Description("mspub.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mspubexe128; + [Write, Description("visio.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_visioexe131; + [Write, Description("exprwd.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_exprwdexe136; + [Write, Description("msaccess.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_msaccessexe137; + [Write, Description("spDesign.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_spdesignexe135; + [Write, Description("winword.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winwordexe133; + [Write, Description("powerpnt.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_powerpntexe129; + [Write, Description("outlook.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_outlookexe134; + [Write, Description("winproj.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winprojexe132; + [Write, Description("pptview.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_pptviewexe130; + [Write, Description("Information Bar (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Informationbar; + [Write, Description("excel.exe (Device) - Depends on L_Informationbar (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_excelexe113; + [Write, Description("mspub.exe (Device) - Depends on L_Informationbar (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mspubexe114; + [Write, Description("msaccess.exe (Device) - Depends on L_Informationbar (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_msaccessexe123; + [Write, Description("onent.exe (Device) - Depends on L_Informationbar (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_onenoteexe124; + [Write, Description("outlook.exe (Device) - Depends on L_Informationbar (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_outlookexe120; + [Write, Description("winproj.exe (Device) - Depends on L_Informationbar (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winprojexe118; + [Write, Description("powerpnt.exe (Device) - Depends on L_Informationbar (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_powerpntexe115; + [Write, Description("spDesign.exe (Device) - Depends on L_Informationbar (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_spdesignexe121; + [Write, Description("groove.exe (Device) - Depends on L_Informationbar (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_grooveexe112; + [Write, Description("visio.exe (Device) - Depends on L_Informationbar (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_visioexe117; + [Write, Description("mse7.exe (Device) - Depends on L_Informationbar (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mse7exe125; + [Write, Description("winword.exe (Device) - Depends on L_Informationbar (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winwordexe119; + [Write, Description("exprwd.exe (Device) - Depends on L_Informationbar (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_exprwdexe122; + [Write, Description("pptview.exe (Device) - Depends on L_Informationbar (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_pptviewexe116; + [Write, Description("Local Machine Zone Lockdown Security (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_LocalMachineZoneLockdownSecurity; + [Write, Description("mse7.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mse7exe41; + [Write, Description("powerpnt.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_powerpntexe31; + [Write, Description("mspub.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mspubexe30; + [Write, Description("outlook.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_outlookexe36; + [Write, Description("pptview.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_pptviewexe32; + [Write, Description("excel.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_excelexe29; + [Write, Description("exprwd.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_exprwdexe38; + [Write, Description("groove.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_grooveexe28; + [Write, Description("winword.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winwordexe35; + [Write, Description("msaccess.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_msaccessexe39; + [Write, Description("spDesign.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_spdesignexe37; + [Write, Description("visio.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_visioexe33; + [Write, Description("onent.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_onenoteexe40; + [Write, Description("winproj.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winprojexe34; + [Write, Description("Mime Sniffing Safety Feature (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_MimeSniffingSafetyFature; + [Write, Description("powerpnt.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_powerpntexe59; + [Write, Description("exprwd.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_exprwdexe66; + [Write, Description("groove.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_grooveexe56; + [Write, Description("visio.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_visioexe61; + [Write, Description("outlook.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_outlookexe64; + [Write, Description("mspub.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mspubexe58; + [Write, Description("mse7.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mse7exe69; + [Write, Description("msaccess.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_msaccessexe67; + [Write, Description("pptview.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_pptviewexe60; + [Write, Description("winproj.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winprojexe62; + [Write, Description("spDesign.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_spdesignexe65; + [Write, Description("onent.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_onenoteexe68; + [Write, Description("winword.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winwordexe63; + [Write, Description("excel.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_excelexe57; + [Write, Description("Navigate URL (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_NavigateURL; + [Write, Description("spDesign.exe (Device) - Depends on L_NavigateURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_spdesignexe177; + [Write, Description("onent.exe (Device) - Depends on L_NavigateURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_onenoteexe180; + [Write, Description("pptview.exe (Device) - Depends on L_NavigateURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_pptviewexe172; + [Write, Description("outlook.exe (Device) - Depends on L_NavigateURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_outlookexe176; + [Write, Description("winproj.exe (Device) - Depends on L_NavigateURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winprojexe174; + [Write, Description("msaccess.exe (Device) - Depends on L_NavigateURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_msaccessexe179; + [Write, Description("winword.exe (Device) - Depends on L_NavigateURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winwordexe175; + [Write, Description("excel.exe (Device) - Depends on L_NavigateURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_excelexe169; + [Write, Description("mspub.exe (Device) - Depends on L_NavigateURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mspubexe170; + [Write, Description("exprwd.exe (Device) - Depends on L_NavigateURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_exprwdexe178; + [Write, Description("powerpnt.exe (Device) - Depends on L_NavigateURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_powerpntexe171; + [Write, Description("visio.exe (Device) - Depends on L_NavigateURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_visioexe173; + [Write, Description("mse7.exe (Device) - Depends on L_NavigateURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mse7exe181; + [Write, Description("groove.exe (Device) - Depends on L_NavigateURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_grooveexe168; + [Write, Description("Object Caching Protection (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_ObjectCachingProtection; + [Write, Description("winword.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winwordexe77; + [Write, Description("powerpnt.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_powerpntexe73; + [Write, Description("spDesign.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_spdesignexe79; + [Write, Description("mse7.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mse7exe83; + [Write, Description("mspub.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mspubexe72; + [Write, Description("msaccess.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_msaccessexe81; + [Write, Description("onent.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_onenoteexe82; + [Write, Description("outlook.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_outlookexe78; + [Write, Description("groove.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_grooveexe70; + [Write, Description("excel.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_excelexe71; + [Write, Description("visio.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_visioexe75; + [Write, Description("pptview.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_pptviewexe74; + [Write, Description("winproj.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winprojexe76; + [Write, Description("exprwd.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_exprwdexe80; + [Write, Description("Protection From Zone Elevation (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_ProtectionFromZoneElevation; + [Write, Description("mspub.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mspubexe100; + [Write, Description("visio.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_visioexe103; + [Write, Description("powerpnt.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_powerpntexe101; + [Write, Description("excel.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_excelexe99; + [Write, Description("mse7.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mse7exe111; + [Write, Description("winword.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winwordexe105; + [Write, Description("exprwd.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_exprwdexe108; + [Write, Description("msaccess.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_msaccessexe109; + [Write, Description("spDesign.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_spdesignexe107; + [Write, Description("onent.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_onenoteexe110; + [Write, Description("pptview.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_pptviewexe102; + [Write, Description("winproj.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winprojexe104; + [Write, Description("groove.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_grooveexe98; + [Write, Description("outlook.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_outlookexe106; + [Write, Description("Restrict ActiveX Install (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_RestrictActiveXInstall; + [Write, Description("mse7.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mse7exe; + [Write, Description("powerpnt.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_powerpntexe; + [Write, Description("spDesign.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_spDesignexe; + [Write, Description("onent.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_onenoteexe; + [Write, Description("excel.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_excelexe; + [Write, Description("mspub.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mspubexe; + [Write, Description("visio.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_visioexe; + [Write, Description("exprwd.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_exprwdexe; + [Write, Description("outlook.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_outlookexe; + [Write, Description("pptview.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_pptviewexe; + [Write, Description("winproj.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winprojexe; + [Write, Description("winword.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winwordexe; + [Write, Description("groove.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_grooveexe; + [Write, Description("msaccess.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_msaccessexe; + [Write, Description("Restrict File Download (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_RestrictFileDownload; + [Write, Description("visio.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_visioexe5; + [Write, Description("winproj.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winprojexe6; + [Write, Description("msaccess.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_msaccessexe11; + [Write, Description("spDesign.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_spdesignexe9; + [Write, Description("excel.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_excelexe1; + [Write, Description("powerpnt.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_powerpntexe3; + [Write, Description("mspub.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mspubexe2; + [Write, Description("exprwd.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_exprwdexe10; + [Write, Description("outlook.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_outlookexe8; + [Write, Description("pptview.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_pptviewexe4; + [Write, Description("winword.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winwordexe7; + [Write, Description("onent.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_onenoteexe12; + [Write, Description("mse7.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mse7exe13; + [Write, Description("groove.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_grooveexe0; + [Write, Description("Saved from URL (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_SavedfromURL; + [Write, Description("pptview.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_pptviewexe158; + [Write, Description("exprwd.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_exprwdexe164; + [Write, Description("mse7.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mse7exe167; + [Write, Description("spDesign.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_spdesignexe163; + [Write, Description("winproj.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winprojexe160; + [Write, Description("mspub.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mspubexe156; + [Write, Description("visio.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_visioexe159; + [Write, Description("winword.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winwordexe161; + [Write, Description("msaccess.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_msaccessexe165; + [Write, Description("onent.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_onenoteexe166; + [Write, Description("outlook.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_outlookexe162; + [Write, Description("groove.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_grooveexe154; + [Write, Description("excel.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_excelexe155; + [Write, Description("powerpnt.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_powerpntexe157; + [Write, Description("Scripted Window Security Restrictions (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_ScriptedWindowSecurityRestrictions; + [Write, Description("exprwd.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_exprwdexe94; + [Write, Description("mse7.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mse7exe97; + [Write, Description("mspub.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_mspubexe86; + [Write, Description("outlook.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_outlookexe92; + [Write, Description("msaccess.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_msaccessexe95; + [Write, Description("powerpnt.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_powerpntexe87; + [Write, Description("groove.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_grooveexe84; + [Write, Description("excel.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_excelexe85; + [Write, Description("pptview.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_pptviewexe88; + [Write, Description("spDesign.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_spdesignexe93; + [Write, Description("visio.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_visioexe89; + [Write, Description("onent.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_onenoteexe96; + [Write, Description("winproj.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winprojexe90; + [Write, Description("winword.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_winwordexe91; +}; + +[ClassVersion("1.0.0.0")] +class MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneSecurityBaselineMicrosoft365AppsForEnterprise +{ + [Write, Description("Block macros from running in Office files from the Internet (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftAccess_Security_TrustCenter_L_BlockMacroExecutionFromInternet; + [Write, Description("Disable Trust Bar Notification for unsigned application add-ins and block them (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftAccess_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned; + [Write, Description("Require that application add-ins are signed by Trusted Publisher (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftAccess_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned; + [Write, Description("Allow Trusted Locations on the network (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftAccess_Security_TrustCenterTrustedLocations_L_AllowTrustedLocationsOnTheNetwork; + [Write, Description("VBA Macro Notification Settings (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftAccess_Security_TrustCenter_L_VBAWarningsPolicy; + [Write, Description(" - Depends on MicrosoftAccess_Security_TrustCenter_L_VBAWarningsPolicy (2: Disable all with notification, 3: Disable all except digitally signed macros, 4: Disable all without notification, 1: Enable all macros (not recommended))"), ValueMap{"2", "3", "4", "1"}, Values{"2", "3", "4", "1"}] String MicrosoftAccess_Security_TrustCenter_L_VBAWarningsPolicy_L_Empty; + [Write, Description("Do not show data extraction options when opening corrupt workbooks (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Donotshowdataextractionoptionswhenopeningcorruptworkbooks; + [Write, Description("Ask to update automatic links (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Asktoupdateautomaticlinks; + [Write, Description("Load pictures from Web pages not created in Excel (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_LoadpicturesfromWebpagesnotcreatedinExcel; + [Write, Description("Disable AutoRepublish (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_DisableAutoRepublish; + [Write, Description("Do not show AutoRepublish warning alert (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_DoNotShowAutoRepublishWarningAlert; + [Write, Description("Force file extension to match file type (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Forcefileextenstionstomatch; + [Write, Description(" - Depends on L_Forcefileextenstionstomatch (0: Allow different, 1: Allow different, but warn, 2: Always match file type)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String L_Forcefileextenstionstomatch_L_Empty; + [Write, Description("Scan encrypted macros in Excel Open XML workbooks (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_DeterminewhethertoforceencryptedExcel; + [Write, Description(" - Depends on L_DeterminewhethertoforceencryptedExcel (0: Scan encrypted macros (default), 1: Scan if anti-virus software available, 2: Load macros without scanning)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String L_DeterminewhethertoforceencryptedExcelDropID; + [Write, Description("Block Excel XLL Add-ins that come from an untrusted source (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_BlockXLLFromInternet; + [Write, Description(" - Depends on L_BlockXLLFromInternet (1: Block, 0: Show Additional Warning, 2: Allow)"), ValueMap{"1", "0", "2"}, Values{"1", "0", "2"}] String L_BlockXLLFromInternetEnum; + [Write, Description("Block macros from running in Office files from the Internet (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftExcel_Security_TrustCenter_L_BlockMacroExecutionFromInternet; + [Write, Description("Disable Trust Bar Notification for unsigned application add-ins and block them (User) (Deprecated) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftExcel_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned; + [Write, Description("Always prevent untrusted Microsoft Query files from opening (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_EnableBlockUnsecureQueryFiles; + [Write, Description("dBase III / IV files (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_DBaseIIIANDIVFiles; + [Write, Description("File block setting: (User) - Depends on L_DBaseIIIANDIVFiles (0: Do not block, 2: Open/Save blocked, use open policy)"), ValueMap{"0", "2"}, Values{"0", "2"}] String L_DBaseIIIANDIVFilesDropID; + [Write, Description("Dif and Sylk files (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_DifAndSylkFiles; + [Write, Description("File block setting: (User) - Depends on L_DifAndSylkFiles (0: Do not block, 1: Save blocked, 2: Open/Save blocked, use open policy)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String L_DifAndSylkFilesDropID; + [Write, Description("Excel 2 macrosheets and add-in files (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Excel2MacrosheetsAndAddInFiles; + [Write, Description("File block setting: (User) - Depends on L_Excel2MacrosheetsAndAddInFiles (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View)"), ValueMap{"0", "2", "3", "4", "5"}, Values{"0", "2", "3", "4", "5"}] String L_Excel2MacrosheetsAndAddInFilesDropID; + [Write, Description("Excel 2 worksheets (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Excel2Worksheets; + [Write, Description("File block setting: (User) - Depends on L_Excel2Worksheets (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View)"), ValueMap{"0", "2", "3", "4", "5"}, Values{"0", "2", "3", "4", "5"}] String L_Excel2WorksheetsDropID; + [Write, Description("Excel 3 macrosheets and add-in files (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Excel3MacrosheetsAndAddInFiles; + [Write, Description("File block setting: (User) - Depends on L_Excel3MacrosheetsAndAddInFiles (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View)"), ValueMap{"0", "2", "3", "4", "5"}, Values{"0", "2", "3", "4", "5"}] String L_Excel3MacrosheetsAndAddInFilesDropID; + [Write, Description("Excel 3 worksheets (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Excel3Worksheets; + [Write, Description("File block setting: (User) - Depends on L_Excel3Worksheets (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View)"), ValueMap{"0", "2", "3", "4", "5"}, Values{"0", "2", "3", "4", "5"}] String L_Excel3WorksheetsDropID; + [Write, Description("Excel 4 macrosheets and add-in files (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Excel4MacrosheetsAndAddInFiles; + [Write, Description("File block setting: (User) - Depends on L_Excel4MacrosheetsAndAddInFiles (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View)"), ValueMap{"0", "2", "3", "4", "5"}, Values{"0", "2", "3", "4", "5"}] String L_Excel4MacrosheetsAndAddInFilesDropID; + [Write, Description("Excel 4 workbooks (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Excel4Workbooks; + [Write, Description("File block setting: (User) - Depends on L_Excel4Workbooks (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View)"), ValueMap{"0", "2", "3", "4", "5"}, Values{"0", "2", "3", "4", "5"}] String L_Excel4WorkbooksDropID; + [Write, Description("Excel 4 worksheets (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Excel4Worksheets; + [Write, Description("File block setting: (User) - Depends on L_Excel4Worksheets (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View)"), ValueMap{"0", "2", "3", "4", "5"}, Values{"0", "2", "3", "4", "5"}] String L_Excel4WorksheetsDropID; + [Write, Description("Excel 95 workbooks (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Excel95Workbooks; + [Write, Description("File block setting: (User) - Depends on L_Excel95Workbooks (0: Do not block, 1: Save blocked, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View)"), ValueMap{"0", "1", "2", "3", "4", "5"}, Values{"0", "1", "2", "3", "4", "5"}] String L_Excel95WorkbooksDropID; + [Write, Description("Excel 95-97 workbooks and templates (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Excel9597WorkbooksAndTemplates; + [Write, Description("File block setting: (User) - Depends on L_Excel9597WorkbooksAndTemplates (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View)"), ValueMap{"0", "2", "3", "4", "5"}, Values{"0", "2", "3", "4", "5"}] String L_Excel9597WorkbooksAndTemplatesDropID; + [Write, Description("Excel 97-2003 workbooks and templates (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Excel972003WorkbooksAndTemplates; + [Write, Description("File block setting: (User) - Depends on L_Excel972003WorkbooksAndTemplates (0: Do not block, 1: Save blocked, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View)"), ValueMap{"0", "1", "2", "3", "4", "5"}, Values{"0", "1", "2", "3", "4", "5"}] String L_Excel972003WorkbooksAndTemplatesDropID; + [Write, Description("Set default file block behavior (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftExcel_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehavior; + [Write, Description(" - Depends on MicrosoftExcel_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehavior (0: Blocked files are not opened, 1: Blocked files open in Protected View and can not be edited, 2: Blocked files open in Protected View and can be edited)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String MicrosoftExcel_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehaviorDropID; + [Write, Description("Web pages and Excel 2003 XML spreadsheets (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_WebPagesAndExcel2003XMLSpreadsheets; + [Write, Description("File block setting: (User) - Depends on L_WebPagesAndExcel2003XMLSpreadsheets (0: Do not block, 1: Save blocked, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View)"), ValueMap{"0", "1", "2", "3", "4", "5"}, Values{"0", "1", "2", "3", "4", "5"}] String L_WebPagesAndExcel2003XMLSpreadsheetsDropID; + [Write, Description("Prevent Excel from running XLM macros (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_XL4KillSwitchPolicy; + [Write, Description("Always open untrusted database files in Protected View (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_EnableDataBaseFileProtectedView; + [Write, Description("Do not open files from the Internet zone in Protected View (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftExcel_Security_TrustCenterProtectedView_L_DoNotOpenFilesFromTheInternetZoneInProtectedView; + [Write, Description("Do not open files in unsafe locations in Protected View (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftExcel_Security_TrustCenterProtectedView_L_DoNotOpenFilesInUnsafeLocationsInProtectedView; + [Write, Description("Set document behavior if file validation fails (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftExcel_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails; + [Write, Description("Checked: Allow edit. Unchecked: Do not allow edit. (User) - Depends on MicrosoftExcel_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftExcel_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsStr3; + [Write, Description(" - Depends on MicrosoftExcel_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails (0: Block files, 1: Open in Protected View)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftExcel_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsDropID; + [Write, Description("Turn off Protected View for attachments opened from Outlook (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftExcel_Security_TrustCenterProtectedView_L_TurnOffProtectedViewForAttachmentsOpenedFromOutlook; + [Write, Description("Require that application add-ins are signed by Trusted Publisher (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftExcel_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned; + [Write, Description("Disable Trust Bar Notification for unsigned application add-ins and block them (User) - Depends on MicrosoftExcel_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftExcel_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2; + [Write, Description("Allow Trusted Locations on the network (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftExcel_Security_TrustCenterTrustedLocations_L_AllowTrustedLocationsOnTheNetwork; + [Write, Description("VBA Macro Notification Settings (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftExcel_Security_TrustCenter_L_VBAWarningsPolicy; + [Write, Description(" - Depends on MicrosoftExcel_Security_TrustCenter_L_VBAWarningsPolicy (2: Disable VBA macros with notification, 3: Disable VBA macros except digitally signed macros, 4: Disable VBA macros without notification, 1: Enable VBA macros (not recommended))"), ValueMap{"2", "3", "4", "1"}, Values{"2", "3", "4", "1"}] String L_empty4; + [Write, Description("Turn off file validation (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftExcel_Security_L_TurnOffFileValidation; + [Write, Description("WEBSERVICE Function Notification Settings (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_WebContentWarningLevel; + [Write, Description(" - Depends on L_WebContentWarningLevel (0: Enable all WEBSERVICE functions (not recommended), 1: Disable all with notification, 2: Disable all without notification)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String L_WebContentWarningLevelValue; + [Write, Description("Disable UI extending from documents and templates (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_NoExtensibilityCustomizationFromDocumentPolicy; + [Write, Description("Disallow in Word (User) - Depends on L_NoExtensibilityCustomizationFromDocumentPolicy (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_NoExtensibilityCustomizationFromDocumentPolicyWord; + [Write, Description("Disallow in Excel (User) - Depends on L_NoExtensibilityCustomizationFromDocumentPolicy (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_NoExtensibilityCustomizationFromDocumentPolicyExcel; + [Write, Description("Disallow in Visio (User) - Depends on L_NoExtensibilityCustomizationFromDocumentPolicy (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_NoExtensibilityCustomizationFromDocumentPolicyVisio; + [Write, Description("Disallow in PowerPoint (User) - Depends on L_NoExtensibilityCustomizationFromDocumentPolicy (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_NoExtensibilityCustomizationFromDocumentPolicyPowerPoint; + [Write, Description("Disallow in Publisher (User) - Depends on L_NoExtensibilityCustomizationFromDocumentPolicy (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_NoExtensibilityCustomizationFromDocumentPolicyPublisher; + [Write, Description("Disallow in Outlook (User) - Depends on L_NoExtensibilityCustomizationFromDocumentPolicy (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_NoExtensibilityCustomizationFromDocumentPolicyOutlook; + [Write, Description("Disallow in Project (User) - Depends on L_NoExtensibilityCustomizationFromDocumentPolicy (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_NoExtensibilityCustomizationFromDocumentPolicyProject; + [Write, Description("Disallow in Access (User) - Depends on L_NoExtensibilityCustomizationFromDocumentPolicy (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_NoExtensibilityCustomizationFromDocumentPolicyAccess; + [Write, Description("Disallow in InfoPath (User) - Depends on L_NoExtensibilityCustomizationFromDocumentPolicy (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_NoExtensibilityCustomizationFromDocumentPolicyInfoPath; + [Write, Description("ActiveX Control Initialization (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_ActiveXControlInitialization; + [Write, Description("ActiveX Control Initialization: (User) - Depends on L_ActiveXControlInitialization (1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6)"), ValueMap{"1", "2", "3", "4", "5", "6"}, Values{"1", "2", "3", "4", "5", "6"}] String L_ActiveXControlInitializationcolon; + [Write, Description("Allow Basic Authentication prompts from network proxies (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_BasicAuthProxyBehavior; + [Write, Description("Allow VBA to load typelib references by path from untrusted intranet locations (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_AllowVbaIntranetRefs; + [Write, Description("Automation Security (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_AutomationSecurity; + [Write, Description("Set the Automation Security level (User) - Depends on L_AutomationSecurity (3: Disable macros by default, 2: Use application macro security level, 1: Macros enabled (default))"), ValueMap{"3", "2", "1"}, Values{"3", "2", "1"}] String L_SettheAutomationSecuritylevel; + [Write, Description("Control how Office handles form-based sign-in prompts (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_AuthenticationFBABehavior; + [Write, Description("Specify hosts allowed to show form-based sign-in prompts to users: (User) - Depends on L_AuthenticationFBABehavior")] String L_AuthenticationFBAEnabledHostsID; + [Write, Description("Behavior: (User) - Depends on L_AuthenticationFBABehavior (1: Block all prompts, 2: Ask the user what to do for each new host, 3: Show prompts only from allowed hosts)"), ValueMap{"1", "2", "3"}, Values{"1", "2", "3"}] String L_authenticationFBABehaviorEnum; + [Write, Description("Disable additional security checks on VBA library references that may refer to unsafe locations on the local machine (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_DisableStrictVbaRefsSecurityPolicy; + [Write, Description("Disable all Trust Bar notifications for security issues (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_DisableallTrustBarnotificationsfor; + [Write, Description("Encryption mode for Information Rights Management (IRM) (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Encryptiontypeforirm; + [Write, Description("IRM Encryption Mode: (User) - Depends on L_Encryptiontypeforirm (1: Cipher Block Chaining (CBC), 2: Electronic Codebook (ECB))"), ValueMap{"1", "2"}, Values{"1", "2"}] String L_Encryptiontypeforirmcolon; + [Write, Description("Encryption type for password protected Office 97-2003 files (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Encryptiontypeforpasswordprotectedoffice972003; + [Write, Description("Encryption type: (User) - Depends on L_Encryptiontypeforpasswordprotectedoffice972003")] String L_encryptiontypecolon318; + [Write, Description("Encryption type for password protected Office Open XML files (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Encryptiontypeforpasswordprotectedofficeopen; + [Write, Description("Encryption type: (User) - Depends on L_Encryptiontypeforpasswordprotectedofficeopen")] String L_Encryptiontypecolon; + [Write, Description("Load Controls in Forms3 (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_LoadControlsinForms3; + [Write, Description("Load Controls in Forms3: (User) - Depends on L_LoadControlsinForms3 (1: 1, 2: 2, 3: 3, 4: 4)"), ValueMap{"1", "2", "3", "4"}, Values{"1", "2", "3", "4"}] String L_LoadControlsinForms3colon; + [Write, Description("Macro Runtime Scan Scope (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_MacroRuntimeScanScope; + [Write, Description(" - Depends on L_MacroRuntimeScanScope (0: Disable for all documents, 1: Enable for low trust documents, 2: Enable for all documents)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String L_MacroRuntimeScanScopeEnum; + [Write, Description("Protect document metadata for rights managed Office Open XML Files (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Protectdocumentmetadataforrightsmanaged; + [Write, Description("Allow mix of policy and user locations (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Allowmixofpolicyanduserlocations; + [Write, Description("Disable the Office client from polling the SharePoint Server for published links (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_DisabletheOfficeclientfrompolling; + [Write, Description("Disable Smart Document's use of manifests (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_DisableSmartDocumentsuseofmanifests; + [Write, Description("Outlook Security Mode (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_OutlookSecurityMode; + [Write, Description("Configure Outlook object model prompt when reading address information (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_OOMAddressAccess; + [Write, Description("Guard behavior: (User) (1: Prompt User, 2: Automatically Approve, 0: Automatically Deny, 3: Prompt user based on computer security)"), ValueMap{"1", "2", "0", "3"}, Values{"1", "2", "0", "3"}] String L_OOMAddressAccess_Setting; + [Write, Description("Configure Outlook object model prompt when responding to meeting and task requests (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_OOMMeetingTaskRequest; + [Write, Description("Guard behavior: (User) (1: Prompt User, 2: Automatically Approve, 0: Automatically Deny, 3: Prompt user based on computer security)"), ValueMap{"1", "2", "0", "3"}, Values{"1", "2", "0", "3"}] String L_OOMMeetingTaskRequest_Setting; + [Write, Description("Configure Outlook object model prompt when sending mail (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_OOMSend; + [Write, Description("Guard behavior: (User) (1: Prompt User, 2: Automatically Approve, 0: Automatically Deny, 3: Prompt user based on computer security)"), ValueMap{"1", "2", "0", "3"}, Values{"1", "2", "0", "3"}] String L_OOMSend_Setting; + [Write, Description("Prevent users from customizing attachment security settings (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Preventusersfromcustomizingattachmentsecuritysettings; + [Write, Description("Retrieving CRLs (Certificate Revocation Lists) (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_RetrievingCRLsCertificateRevocationLists; + [Write, Description(" (0: Use system Default, 1: When online always retreive the CRL, 2: Never retreive the CRL)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String L_empty31; + [Write, Description("Configure Outlook object model prompt When accessing the Formula property of a UserProperty object (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_OOMFormula; + [Write, Description("Guard behavior: (User) (1: Prompt User, 2: Automatically Approve, 0: Automatically Deny, 3: Prompt user based on computer security)"), ValueMap{"1", "2", "0", "3"}, Values{"1", "2", "0", "3"}] String L_OOMFormula_Setting; + [Write, Description("Authentication with Exchange Server (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_AuthenticationwithExchangeServer; + [Write, Description("Select the authentication with Exchange server. (User) (9: Kerberos/NTLM Password Authentication, 16: Kerberos Password Authentication, 10: NTLM Password Authentication, 2147545088: Insert a smart card)"), ValueMap{"9", "16", "10", "2147545088"}, Values{"9", "16", "10", "2147545088"}] String L_SelecttheauthenticationwithExchangeserver; + [Write, Description("Enable RPC encryption (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_EnableRPCEncryption; + [Write, Description("Allow hyperlinks in suspected phishing e-mail messages (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Enablelinksinemailmessages; + [Write, Description("Configure Outlook object model prompt when accessing an address book (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_OOMAddressBook; + [Write, Description("Guard behavior: (User) (1: Prompt User, 2: Automatically Approve, 0: Automatically Deny, 3: Prompt user based on computer security)"), ValueMap{"1", "2", "0", "3"}, Values{"1", "2", "0", "3"}] String L_OOMAddressBook_Setting; + [Write, Description("Outlook Security Policy: (User) - Depends on L_OutlookSecurityMode (0: Outlook Default Security, 1: Use Security Form from 'Outlook Security Settings' Public Folder, 2: Use Security Form from 'Outlook 10 Security Settings' Public Folder, 3: Use Outlook Security Group Policy)"), ValueMap{"0", "1", "2", "3"}, Values{"0", "1", "2", "3"}] String L_OutlookSecurityPolicy; + [Write, Description("Allow users to demote attachments to Level 2 (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_AllowUsersToLowerAttachments; + [Write, Description("Allow Active X One Off Forms (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_AllowActiveXOneOffForms; + [Write, Description("Sets which ActiveX controls to allow. (0: Load only Outlook Controls, 1: Allows only Safe Controls, 2: Allows all ActiveX Controls)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String L_empty29; + [Write, Description("Allow scripts in one-off Outlook forms (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_EnableScriptsInOneOffForms; + [Write, Description("Remove file extensions blocked as Level 2 (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Level2RemoveFilePolicy; + [Write, Description("Removed Extensions: (User)")] String L_removedextensions25; + [Write, Description("Use Unicode format when dragging e-mail message to file system (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_MSGUnicodeformatwhendraggingtofilesystem; + [Write, Description("Set Outlook object model custom actions execution prompt (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_OnExecuteCustomActionOOM; + [Write, Description("When executing a custom action: (User) (1: Prompt User, 2: Automatically Approve, 0: Automatically Deny, 3: Prompt user based on computer security)"), ValueMap{"1", "2", "0", "3"}, Values{"1", "2", "0", "3"}] String L_OnExecuteCustomActionOOM_Setting; + [Write, Description("Do not allow Outlook object model scripts to run for public folders (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_DisableOutlookobjectmodelscriptsforpublicfolders; + [Write, Description("Include Internet in Safe Zones for Automatic Picture Download (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_BlockInternet; + [Write, Description("Security setting for macros (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_SecurityLevelOutlook; + [Write, Description("Security Level (User) (2: Always warn, 4: Never warn, disable all, 3: Warn for signed, disable unsigned, 1: No security check)"), ValueMap{"2", "4", "3", "1"}, Values{"2", "4", "3", "1"}] String L_SecurityLevel; + [Write, Description("Remove file extensions blocked as Level 1 (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Level1RemoveFilePolicy; + [Write, Description("Removed Extensions: (User)")] String L_RemovedExtensions; + [Write, Description("Signature Warning (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_SignatureWarning; + [Write, Description("Signature Warning (User) (0: Let user decide if they want to be warned, 1: Always warn about invalid signatures, 2: Never warn about invalid signatures)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String L_signaturewarning30; + [Write, Description("Display Level 1 attachments (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Level1Attachments; + [Write, Description("Minimum encryption settings (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Minimumencryptionsettings; + [Write, Description("Minimum key size (in bits): (User)")] SInt32 L_Minimumkeysizeinbits; + [Write, Description("Do not allow Outlook object model scripts to run for shared folders (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_DisableOutlookobjectmodelscripts; + [Write, Description("Configure Outlook object model prompt when executing Save As (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_OOMSaveAs; + [Write, Description("Guard behavior: (User) (1: Prompt User, 2: Automatically Approve, 0: Automatically Deny, 3: Prompt user based on computer security)"), ValueMap{"1", "2", "0", "3"}, Values{"1", "2", "0", "3"}] String L_OOMSaveAs_Setting; + [Write, Description("Junk E-mail protection level (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_JunkEmailprotectionlevel; + [Write, Description("Select level: (User) (4294967295: No Protection, 6: Low (Default), 3: High, 2147483648: Trusted Lists Only)"), ValueMap{"4294967295", "6", "3", "2147483648"}, Values{"4294967295", "6", "3", "2147483648"}] String L_Selectlevel; + [Write, Description("Run Programs (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_RunPrograms; + [Write, Description(" - Depends on L_RunPrograms (0: disable (don't run any programs), 1: enable (prompt user before running), 2: enable all (run without prompting))"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String L_RunPrograms_L_Empty; + [Write, Description("Scan encrypted macros in PowerPoint Open XML presentations (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Determinewhethertoforceencryptedppt; + [Write, Description(" - Depends on L_Determinewhethertoforceencryptedppt (0: Scan encrypted macros (default), 1: Scan if anti-virus software available, 2: Load macros without scanning)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String L_DeterminewhethertoforceencryptedpptDropID; + [Write, Description("Block macros from running in Office files from the Internet (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftPowerPoint_Security_TrustCenter_L_BlockMacroExecutionFromInternet; + [Write, Description("Disable Trust Bar Notification for unsigned application add-ins and block them (User) (Deprecated) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftPowerPoint_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned; + [Write, Description("PowerPoint 97-2003 presentations, shows, templates and add-in files (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_PowerPoint972003PresentationsShowsTemplatesandAddInFiles; + [Write, Description("File block setting: (User) - Depends on L_PowerPoint972003PresentationsShowsTemplatesandAddInFiles (0: Do not block, 1: Save blocked, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View)"), ValueMap{"0", "1", "2", "3", "4", "5"}, Values{"0", "1", "2", "3", "4", "5"}] String L_PowerPoint972003PresentationsShowsTemplatesandAddInFilesDropID; + [Write, Description("Set default file block behavior (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftPowerPoint_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehavior; + [Write, Description(" - Depends on MicrosoftPowerPoint_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehavior (0: Blocked files are not opened, 1: Blocked files open in Protected View and can not be edited, 2: Blocked files open in Protected View and can be edited)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String MicrosoftPowerPoint_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehaviorDropID; + [Write, Description("Do not open files from the Internet zone in Protected View (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_DoNotOpenFilesFromTheInternetZoneInProtectedView; + [Write, Description("Do not open files in unsafe locations in Protected View (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_DoNotOpenFilesInUnsafeLocationsInProtectedView; + [Write, Description("Set document behavior if file validation fails (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails; + [Write, Description("Checked: Allow edit. Unchecked: Do not allow edit. (User) - Depends on MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsStr3; + [Write, Description(" - Depends on MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails (0: Block files, 1: Open in Protected View)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsDropID; + [Write, Description("Turn off Protected View for attachments opened from Outlook (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_TurnOffProtectedViewForAttachmentsOpenedFromOutlook; + [Write, Description("Require that application add-ins are signed by Trusted Publisher (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftPowerPoint_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned; + [Write, Description("Disable Trust Bar Notification for unsigned application add-ins and block them (User) - Depends on MicrosoftPowerPoint_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftPowerPoint_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2; + [Write, Description("Allow Trusted Locations on the network (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftPowerPoint_Security_TrustCenterTrustedLocations_L_AllowTrustedLocationsOnTheNetwork; + [Write, Description("VBA Macro Notification Settings (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftPowerPoint_Security_TrustCenter_L_VBAWarningsPolicy; + [Write, Description(" - Depends on MicrosoftPowerPoint_Security_TrustCenter_L_VBAWarningsPolicy (2: Disable all with notification, 3: Disable all except digitally signed macros, 4: Disable all without notification, 1: Enable all macros (not recommended))"), ValueMap{"2", "3", "4", "1"}, Values{"2", "3", "4", "1"}] String L_empty3; + [Write, Description("Turn off file validation (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftPowerPoint_Security_L_TurnOffFileValidation; + [Write, Description("Allow Trusted Locations on the network (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftProject_Security_TrustCenter_L_AllowTrustedLocationsOnTheNetwork; + [Write, Description("Disable Trust Bar Notification for unsigned application add-ins and block them (User) (Deprecated) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftProject_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned; + [Write, Description("Require that application add-ins are signed by Trusted Publisher (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftProject_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned; + [Write, Description("Disable Trust Bar Notification for unsigned application add-ins and block them (User) - Depends on MicrosoftProject_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftProject_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2; + [Write, Description("VBA Macro Notification Settings (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftProject_Security_TrustCenter_L_VBAWarningsPolicy; + [Write, Description(" - Depends on MicrosoftProject_Security_TrustCenter_L_VBAWarningsPolicy (2: Disable all with notification, 3: Disable all except digitally signed macros, 4: Disable all without notification, 1: Enable all macros (not recommended))"), ValueMap{"2", "3", "4", "1"}, Values{"2", "3", "4", "1"}] String MicrosoftProject_Security_TrustCenter_L_VBAWarningsPolicy_L_Empty; + [Write, Description("Publisher Automation Security Level (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_PublisherAutomationSecurityLevel; + [Write, Description(" - Depends on L_PublisherAutomationSecurityLevel (1: Low (enabled), 2: By UI (prompted), 3: High (disabled))"), ValueMap{"1", "2", "3"}, Values{"1", "2", "3"}] String L_PublisherAutomationSecurityLevel_L_Empty; + [Write, Description("Block macros from running in Office files from the internet (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftPublisherV3_Security_TrustCenter_L_BlockMacroExecutionFromInternet; + [Write, Description("Disable Trust Bar Notification for unsigned application add-ins (User) (Deprecated) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftPublisherV2_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned; + [Write, Description("Require that application add-ins are signed by Trusted Publisher (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftPublisherV2_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned; + [Write, Description("Disable Trust Bar Notification for unsigned application add-ins (User) - Depends on MicrosoftPublisherV2_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftPublisherV2_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2; + [Write, Description("VBA Macro Notification Settings (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftPublisherV2_Security_TrustCenter_L_VBAWarningsPolicy; + [Write, Description(" - Depends on MicrosoftPublisherV2_Security_TrustCenter_L_VBAWarningsPolicy (2: Disable all with notification, 3: Disable all except digitally signed macros, 4: Disable all without notification, 1: Enable all macros (not recommended))"), ValueMap{"2", "3", "4", "1"}, Values{"2", "3", "4", "1"}] String L_empty0; + [Write, Description("Allow Trusted Locations on the network (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftVisio_Security_TrustCenter_L_AllowTrustedLocationsOnTheNetwork; + [Write, Description("Block macros from running in Office files from the Internet (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftVisio_Security_TrustCenter_L_BlockMacroExecutionFromInternet; + [Write, Description("Disable Trust Bar Notification for unsigned application add-ins and block them (User) (Deprecated) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftVisio_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned; + [Write, Description("Visio 2000-2002 Binary Drawings, Templates and Stencils (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Visio2000Files; + [Write, Description("File block setting: (User) - Depends on L_Visio2000Files (0: Do not block, 2: Open/Save blocked)"), ValueMap{"0", "2"}, Values{"0", "2"}] String L_Visio2000FilesDropID; + [Write, Description("Visio 2003-2010 Binary Drawings, Templates and Stencils (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Visio2003Files; + [Write, Description("File block setting: (User) - Depends on L_Visio2003Files (0: Do not block, 1: Save blocked, 2: Open/Save blocked)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String L_Visio2003FilesDropID; + [Write, Description("Visio 5.0 or earlier Binary Drawings, Templates and Stencils (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Visio50AndEarlierFiles; + [Write, Description("File block setting: (User) - Depends on L_Visio50AndEarlierFiles (0: Do not block, 2: Open/Save blocked)"), ValueMap{"0", "2"}, Values{"0", "2"}] String L_Visio50AndEarlierFilesDropID; + [Write, Description("Require that application add-ins are signed by Trusted Publisher (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftVisio_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned; + [Write, Description("Disable Trust Bar Notification for unsigned application add-ins and block them (User) - Depends on MicrosoftVisio_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftVisio_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2; + [Write, Description("VBA Macro Notification Settings (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftVisio_Security_TrustCenter_L_VBAWarningsPolicy; + [Write, Description(" - Depends on MicrosoftVisio_Security_TrustCenter_L_VBAWarningsPolicy (2: Disable all with notification, 3: Disable all except digitally signed macros, 4: Disable all without notification, 1: Enable all macros (not recommended))"), ValueMap{"2", "3", "4", "1"}, Values{"2", "3", "4", "1"}] String MicrosoftVisio_Security_TrustCenter_L_VBAWarningsPolicy_L_Empty; + [Write, Description("Block macros from running in Office files from the Internet (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftWord_Security_TrustCenter_L_BlockMacroExecutionFromInternet; + [Write, Description("Disable Trust Bar Notification for unsigned application add-ins and block them (User) (Deprecated) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftWord_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned; + [Write, Description("Dynamic Data Exchange (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_AllowDDE; + [Write, Description("Dynamic Data Exchange setting (User) - Depends on L_AllowDDE (1: Limited Dynamic Data Exchange, 2: Allow Dynamic Data Exchange)"), ValueMap{"1", "2"}, Values{"1", "2"}] String L_AllowDDEDropID; + [Write, Description("Set default file block behavior (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftWord_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehavior; + [Write, Description(" - Depends on MicrosoftWord_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehavior (0: Blocked files are not opened, 1: Blocked files open in Protected View and can not be edited, 2: Blocked files open in Protected View and can be edited)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String MicrosoftWord_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehaviorDropID; + [Write, Description("Word 2 and earlier binary documents and templates (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Word2AndEarlierBinaryDocumentsAndTemplates; + [Write, Description("File block setting: (User) - Depends on L_Word2AndEarlierBinaryDocumentsAndTemplates (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View)"), ValueMap{"0", "2", "3", "4", "5"}, Values{"0", "2", "3", "4", "5"}] String L_Word2AndEarlierBinaryDocumentsAndTemplatesDropID; + [Write, Description("Word 2000 binary documents and templates (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Word2000BinaryDocumentsAndTemplates; + [Write, Description("File block setting: (User) - Depends on L_Word2000BinaryDocumentsAndTemplates (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View)"), ValueMap{"0", "2", "3", "4", "5"}, Values{"0", "2", "3", "4", "5"}] String L_Word2000BinaryDocumentsAndTemplatesDropID; + [Write, Description("Word 2003 binary documents and templates (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Word2003BinaryDocumentsAndTemplates; + [Write, Description("File block setting: (User) - Depends on L_Word2003BinaryDocumentsAndTemplates (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View)"), ValueMap{"0", "2", "3", "4", "5"}, Values{"0", "2", "3", "4", "5"}] String L_Word2003BinaryDocumentsAndTemplatesDropID; + [Write, Description("Word 2007 and later binary documents and templates (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Word2007AndLaterBinaryDocumentsAndTemplates; + [Write, Description("File block setting: (User) - Depends on L_Word2007AndLaterBinaryDocumentsAndTemplates (0: Do not block, 1: Save blocked, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View)"), ValueMap{"0", "1", "2", "3", "4", "5"}, Values{"0", "1", "2", "3", "4", "5"}] String L_Word2007AndLaterBinaryDocumentsAndTemplatesDropID; + [Write, Description("Word 6.0 binary documents and templates (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Word6Pt0BinaryDocumentsAndTemplates; + [Write, Description("File block setting: (User) - Depends on L_Word6Pt0BinaryDocumentsAndTemplates (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View)"), ValueMap{"0", "2", "3", "4", "5"}, Values{"0", "2", "3", "4", "5"}] String L_Word6Pt0BinaryDocumentsAndTemplatesDropID; + [Write, Description("Word 95 binary documents and templates (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Word95BinaryDocumentsAndTemplates; + [Write, Description("File block setting: (User) - Depends on L_Word95BinaryDocumentsAndTemplates (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View)"), ValueMap{"0", "2", "3", "4", "5"}, Values{"0", "2", "3", "4", "5"}] String L_Word95BinaryDocumentsAndTemplatesDropID; + [Write, Description("Word 97 binary documents and templates (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_Word97BinaryDocumentsAndTemplates; + [Write, Description("File block setting: (User) - Depends on L_Word97BinaryDocumentsAndTemplates (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View)"), ValueMap{"0", "2", "3", "4", "5"}, Values{"0", "2", "3", "4", "5"}] String L_Word97BinaryDocumentsAndTemplatesDropID; + [Write, Description("Word XP binary documents and templates (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_WordXPBinaryDocumentsAndTemplates; + [Write, Description("File block setting: (User) - Depends on L_WordXPBinaryDocumentsAndTemplates (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View)"), ValueMap{"0", "2", "3", "4", "5"}, Values{"0", "2", "3", "4", "5"}] String L_WordXPBinaryDocumentsAndTemplatesDropID; + [Write, Description("Do not open files from the Internet zone in Protected View (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftWord_Security_TrustCenterProtectedView_L_DoNotOpenFilesFromTheInternetZoneInProtectedView; + [Write, Description("Do not open files in unsafe locations in Protected View (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftWord_Security_TrustCenterProtectedView_L_DoNotOpenFilesInUnsafeLocationsInProtectedView; + [Write, Description("Set document behavior if file validation fails (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftWord_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails; + [Write, Description(" - Depends on MicrosoftWord_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails (0: Block files, 1: Open in Protected View)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftWord_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsDropID; + [Write, Description("Checked: Allow edit. Unchecked: Do not allow edit. (User) - Depends on MicrosoftWord_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails (0: False, 1: True)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftWord_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsStr3; + [Write, Description("Turn off Protected View for attachments opened from Outlook (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftWord_Security_TrustCenterProtectedView_L_TurnOffProtectedViewForAttachmentsOpenedFromOutlook; + [Write, Description("Require that application add-ins are signed by Trusted Publisher (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftWord_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned; + [Write, Description("Disable Trust Bar Notification for unsigned application add-ins and block them (User) - Depends on MicrosoftWord_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftWord_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2; + [Write, Description("Scan encrypted macros in Word Open XML documents (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String L_DeterminewhethertoforceencryptedWord; + [Write, Description(" - Depends on L_DeterminewhethertoforceencryptedWord (0: Scan encrypted macros (default), 1: Scan if anti-virus software available, 2: Load macros without scanning)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String L_DeterminewhethertoforceencryptedWordDropID; + [Write, Description("VBA Macro Notification Settings (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftWord_Security_TrustCenter_L_VBAWarningsPolicy; + [Write, Description(" - Depends on MicrosoftWord_Security_TrustCenter_L_VBAWarningsPolicy (2: Disable all with notification, 3: Disable all except digitally signed macros, 4: Disable all without notification, 1: Enable all macros (not recommended))"), ValueMap{"2", "3", "4", "1"}, Values{"2", "3", "4", "1"}] String L_empty19; + [Write, Description("Turn off file validation (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftWord_Security_L_TurnOffFileValidation; + [Write, Description("Allow Trusted Locations on the network (User) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftWord_Security_TrustCenterTrustedLocations_L_AllowTrustedLocationsOnTheNetwork; +}; +[ClassVersion("1.0.0.0"), FriendlyName("IntuneSecurityBaselineMicrosoft365AppsForEnterprise")] +class MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise : OMI_BaseResource +{ + [Write, Description("Policy description")] String Description; + [Key, Description("Policy name")] String DisplayName; + [Write, Description("List of Scope Tags for this Entity instance.")] String RoleScopeTagIds[]; + [Write, Description("The unique identifier for an entity. Read-only.")] String Id; + [Write, Description("The policy settings for the device scope"), EmbeddedInstance("MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneSecurityBaselineMicrosoft365AppsForEnterprise")] String DeviceSettings; + [Write, Description("The policy settings for the user scope"), EmbeddedInstance("MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneSecurityBaselineMicrosoft365AppsForEnterprise")] String UserSettings; + [Write, Description("Represents the assignment to the Intune policy."), EmbeddedInstance("MSFT_DeviceManagementConfigurationPolicyAssignments")] String Assignments[]; + [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; + [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Secret of the Azure Active Directory tenant used for authentication."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise/readme.md new file mode 100644 index 0000000000..7e7218c244 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise/readme.md @@ -0,0 +1,6 @@ + +# IntuneSecurityBaselineMicrosoft365AppsForEnterprise + +## Description + +Intune Security Baseline Microsoft365 Apps For Enterprise diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise/settings.json new file mode 100644 index 0000000000..4bda1f09ca --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName":"IntuneSecurityBaselineMicrosoft365AppsForEnterprise", + "description":"This resource configures an Intune Security Baseline Microsoft365 Apps For Enterprise.", + "permissions":{ + "graph":{ + "delegated":{ + "read":[ + { + "name":"DeviceManagementConfiguration.Read.All" + } + ], + "update":[ + { + "name":"DeviceManagementConfiguration.ReadWrite.All" + } + ] + }, + "application":{ + "read":[ + { + "name":"DeviceManagementConfiguration.Read.All" + } + ], + "update":[ + { + "name":"DeviceManagementConfiguration.ReadWrite.All" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneSecurityBaselineMicrosoft365AppsForEnterprise/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneSecurityBaselineMicrosoft365AppsForEnterprise/1-Create.ps1 new file mode 100644 index 0000000000..4999c28f32 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneSecurityBaselineMicrosoft365AppsForEnterprise/1-Create.ps1 @@ -0,0 +1,58 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneSecurityBaselineMicrosoft365AppsForEnterprise 'mySecurityBaselineMicrosoft365AppsForEnterprisePolicy' + { + DisplayName = 'test' + DeviceSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneSecurityBaselineMicrosoft365AppsForEnterprise + { + L_ProtectionFromZoneElevation = '1' + L_grooveexe98 = '1' + L_excelexe99 = '1' + L_mspubexe100 = '1' + L_powerpntexe101 = '1' + L_pptviewexe102 = '1' + L_visioexe103 = '1' + L_winprojexe104 = '1' + L_winwordexe105 = '1' + L_outlookexe106 = '1' + L_spdesignexe107 = '1' + L_exprwdexe108 = '1' + L_msaccessexe109 = '1' + L_onenoteexe110 = '1' + L_mse7exe111 = '1' + } + UserSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneSecurityBaselineMicrosoft365AppsForEnterprise + { + MicrosoftPublisherV3_Security_TrustCenter_L_BlockMacroExecutionFromInternet = '1' + MicrosoftVisio_Security_TrustCenter_L_VBAWarningsPolicy = '1' + MicrosoftVisio_Security_TrustCenter_L_VBAWarningsPolicy_L_Empty = '3' + } + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneSecurityBaselineMicrosoft365AppsForEnterprise/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneSecurityBaselineMicrosoft365AppsForEnterprise/2-Update.ps1 new file mode 100644 index 0000000000..9462f97414 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneSecurityBaselineMicrosoft365AppsForEnterprise/2-Update.ps1 @@ -0,0 +1,58 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneSecurityBaselineMicrosoft365AppsForEnterprise 'mySecurityBaselineMicrosoft365AppsForEnterprisePolicy' + { + DisplayName = 'test' + DeviceSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneSecurityBaselineMicrosoft365AppsForEnterprise + { + L_ProtectionFromZoneElevation = '1' + L_grooveexe98 = '1' + L_excelexe99 = '1' + L_mspubexe100 = '1' + L_powerpntexe101 = '1' + L_pptviewexe102 = '1' + L_visioexe103 = '1' + L_winprojexe104 = '1' + L_winwordexe105 = '1' + L_outlookexe106 = '1' + L_spdesignexe107 = '1' + L_exprwdexe108 = '1' + L_msaccessexe109 = '1' + L_onenoteexe110 = '1' + L_mse7exe111 = '1' + } + UserSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneSecurityBaselineMicrosoft365AppsForEnterprise + { + MicrosoftPublisherV3_Security_TrustCenter_L_BlockMacroExecutionFromInternet = '1' + MicrosoftVisio_Security_TrustCenter_L_VBAWarningsPolicy = '1' + MicrosoftVisio_Security_TrustCenter_L_VBAWarningsPolicy_L_Empty = '2' # Updated property + } + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneSecurityBaselineMicrosoft365AppsForEnterprise/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneSecurityBaselineMicrosoft365AppsForEnterprise/3-Remove.ps1 new file mode 100644 index 0000000000..b9a8c3c849 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneSecurityBaselineMicrosoft365AppsForEnterprise/3-Remove.ps1 @@ -0,0 +1,34 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneSecurityBaselineMicrosoft365AppsForEnterprise 'mySecurityBaselineMicrosoft365AppsForEnterprisePolicy' + { + DisplayName = 'test' + Ensure = 'Absent' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} diff --git a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 index e534d1df33..7a3beda733 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 @@ -2146,7 +2146,24 @@ function Get-IntuneSettingCatalogPolicySettingDSCValue # If no parent definition is found, it might have been combined with the OffsetUri if ($null -eq $parentDefinition) { - $definition = Get-SettingDefinitionFromNameWithParentFromOffsetUri -OffsetUriName $key -SettingDefinitions $SettingTemplates.SettingDefinitions + $newKey = $key + switch -wildcard ($newKey) + { + '*TrustCenterTrustedLocations_*' { $newKey = $newKey.Replace('TrustCenterTrustedLocations', 'TrustCenter~L_TrustedLocations') } + '*TrustCenterFileBlockSettings_*' { $newKey = $newKey.Replace('TrustCenterFileBlockSettings', 'TrustCenter~L_FileBlockSettings') } + '*TrustCenterProtectedView_*' { $newKey = $newKey.Replace('TrustCenterProtectedView', 'TrustCenter~L_ProtectedView') } + '*_TrustCenter*' { $newKey = $newKey.Replace('_TrustCenter', '~L_TrustCenter') } + '*_Security_*' { $newKey = $newKey.Replace('Security', '~L_Security') } + 'MicrosoftPublisherV3_*' { $newKey = $newKey.Replace('MicrosoftPublisherV3_', 'pub16v3~Policy~L_MicrosoftOfficePublisher') } + 'MicrosoftPublisherV2_*' { $newKey = $newKey.Replace('MicrosoftPublisherV2_', 'pub16v2~Policy~L_MicrosoftOfficePublisher') } + 'MicrosoftVisio_*' { $newKey = $newKey.Replace('MicrosoftVisio_', 'visio16v2~Policy~L_MicrosoftVisio~L_VisioOptions') } + 'MicrosoftProject_*' { $newKey = $newKey.Replace('MicrosoftProject_', 'proj16v2~Policy~L_Proj~L_ProjectOptions') } + 'MicrosoftPowerPoint_*' { $newKey = $newKey.Replace('MicrosoftPowerPoint_', 'ppt16v2~Policy~L_MicrosoftOfficePowerPoint~L_PowerPointOptions') } + 'MicrosoftWord_*' { $newKey = $newKey.Replace('MicrosoftWord_', 'word16v2~Policy~L_MicrosoftOfficeWord~L_WordOptions') } + 'MicrosoftExcel_*' { $newKey = $newKey.Replace('MicrosoftExcel_', 'excel16v2~Policy~L_MicrosoftOfficeExcel~L_ExcelOptions') } + 'MicrosoftAccess_*' { $newKey = $newKey.Replace('MicrosoftAccess_', 'access16v2~Policy~L_MicrosoftOfficeaccess~L_ApplicationSettings') } + } + $definition = Get-SettingDefinitionFromNameWithParentFromOffsetUri -OffsetUriName $newKey -SettingDefinitions $SettingTemplates.SettingDefinitions if ($null -ne $definition) { $offsetUriFound = $true @@ -2279,18 +2296,31 @@ function Get-SettingDefinitionFromNameWithParentFromOffsetUri $settingName = $OffsetUriName $offsetUriPrefix = "" - foreach ($part in $offsetUriParts) + for ($i = 0; $i -lt $offsetUriParts.Count; $i++) { - if ($settingName -like "*$($part)_*") + $part = $offsetUriParts[$i] + if ($settingName -like "$($part)_*") { $settingName = $settingName.Replace("$($part)_", "") # Add wildcards to match removed parts with invalid characters $offsetUriPrefix += "*$($part)*" + $i = 0 } } - $filteredDefinitions = $SettingDefinitions | Where-Object -FilterScript { - $_.Name -eq $settingName -and $_.OffsetUri -like "*$offsetUriPrefix*" + if ($settingName -eq "v2") + { + $settingName = $offsetUriPrefix.Split("*")[-2] + "_v2" # Add the last element of the offset Uri parts before the v2 + $filteredDefinitions = $SettingDefinitions | Where-Object -FilterScript { + ($_.Id -like "*$settingName" -and $_.Name -eq $settingName.Replace('_v2', '') -and $_.OffsetUri -like "*$offsetUriPrefix*") -or + ($_.Name -eq $settingName -and $_.OffsetUri -like "*$offsetUriPrefix*") + } + } + else + { + $filteredDefinitions = $SettingDefinitions | Where-Object -FilterScript { + $_.Name -eq $settingName -and $_.OffsetUri -like "*$offsetUriPrefix*" + } } if ($filteredDefinitions.Count -eq 1) @@ -2303,6 +2333,7 @@ function Get-SettingDefinitionFromNameWithParentFromOffsetUri foreach ($definition in $filteredDefinitions) { $skip = 0 + $breakCounter = 0 $newSettingName = $settingName do { $previousSettingName = $newSettingName @@ -2313,12 +2344,23 @@ function Get-SettingDefinitionFromNameWithParentFromOffsetUri $newName = Get-SettingDefinitionNameWithParentFromOffsetUri -OffsetUri $_.OffsetUri -SettingName $previousSettingName -Skip $skip if ($newName -eq $newSettingName) { - $combinationMatchesWithOffsetUri += $_ + # Exclude v2 versions from the comparison + if ($definition.Id -like "*_v2" -and $_.Id -ne $definition.Id.Replace('_v2', '') -or + $definition.Id -notlike "*_v2" -and $_.Id -ne $definition.Id + "_v2") + { + $combinationMatchesWithOffsetUri += $_ + } } } $settingsWithSameName = $combinationMatchesWithOffsetUri + $breakCounter++ $skip++ - } while ($combinationMatchesWithOffsetUri.Count -gt 1) + } while ($combinationMatchesWithOffsetUri.Count -gt 1 -and $breakCounter -lt 8) + + if ($breakCounter -eq 8) + { + throw "Could not find a unique setting definition for $settingName with parent from OffsetUri $OffsetUriName" + } if ($newSettingName -eq $OffsetUriName) { @@ -2524,7 +2566,12 @@ function Export-IntuneSettingCatalogPolicySettings $newName = Get-SettingDefinitionNameWithParentFromOffsetUri -OffsetUri $_.OffsetUri -SettingName $previousSettingName -Skip $skip if ($newName -eq $newSettingName) { - $combinationMatchesWithOffsetUri += $_ + # Exclude v2 versions from the comparison + if ($settingDefinition.Id -like "*_v2" -and $_.Id -ne $settingDefinition.Id.Replace('_v2', '') -or + $settingDefinition.Id -notlike "*_v2" -and $_.Id -ne $settingDefinition.Id + "_v2") + { + $combinationMatchesWithOffsetUri += $_ + } } } $settingsWithSameName = $combinationMatchesWithOffsetUri @@ -2534,6 +2581,10 @@ function Export-IntuneSettingCatalogPolicySettings if ($breakCounter -lt 8) { + if ($settingDefinition.Id -like "*_v2" -and $newSettingName -notlike "*_v2") + { + $newSettingName += "_v2" + } $settingName = $newSettingName } else @@ -2556,21 +2607,22 @@ function Export-IntuneSettingCatalogPolicySettings $settingName = Get-SettingDefinitionNameWithParentFromOffsetUri -OffsetUri $settingDefinition.OffsetUri -SettingName $settingName } - # Simplify names from the OffsetUri. This is done to make the names more readable, especially in case of long and complex OffsetUris. + # Simplify names from the OffsetUri. This is done to make the names more readable, especially in case of long and complex OffsetUris. switch -wildcard ($settingName) { - { 'access16v2~Policy~L_MicrosoftOfficeaccess~L_ApplicationSettings~L_Security*' } { $settingName = $settingName.Replace('access16v2~Policy~L_MicrosoftOfficeaccess~L_ApplicationSettings', 'MicrosoftAccess_') } - { 'excel16v2~Policy~L_MicrosoftOfficeExcel~L_ExcelOptions~*' } { $settingName = $settingName.Replace('excel16v2~Policy~L_MicrosoftOfficeExcel~L_ExcelOptions', 'MicrosoftExcel_') } - { 'word16v2~Policy~L_MicrosoftOfficeWord~L_WordOptions~*' } { $settingName = $settingName.Replace('word16v2~Policy~L_MicrosoftOfficeWord~L_WordOptions', 'MicrosoftWord_') } - { 'ppt16v2~Policy~L_MicrosoftOfficePowerPoint~L_PowerPointOptions~*' } { $settingName = $settingName.Replace('ppt16v2~Policy~L_MicrosoftOfficePowerPoint~L_PowerPointOptions', 'MicrosoftPowerPoint_') } - { 'proj16v2~Policy~L_Proj~L_ProjectOptions~*' } { $settingName = $settingName.Replace('proj16v2~Policy~L_Proj~L_ProjectOptions', 'MicrosoftProject_') } - { 'visio16v2~Policy~L_MicrosoftVisio~L_VisioOptions~*' } { $settingName = $settingName.Replace('visio16v2~Policy~L_MicrosoftVisio~L_VisioOptions', 'MicrosoftVisio_') } - { 'pub16v*~Policy~L_MicrosoftOfficePublisher~' } { $settingName = [Regex]::replace($settingName, 'pub16v(.*)~Policy~L_MicrosoftOfficePublisher', 'MicrosoftPublisher_') } - { '*~L_Security~*' } { $settingName = $settingName.Replace('~L_Security', 'Security') } - { '*~L_TrustCenter_'} { $settingName = $settingName.Replace('~L_TrustCenter', '_TrustCenter') } - { '*~L_ProtectedView_' } { $settingName = $settingName.Replace('~L_ProtectedView', 'ProtectedView') } - { '*~L_FileBlockSettings_' } { $settingName = $settingName.Replace('~L_FileBlockSettings', 'FileBlockSettings') } - { '*~L_TrustedLocations' } { $settingName = $settingName.Replace('~L_TrustedLocations', 'TrustedLocations') } + 'access16v2~Policy~L_MicrosoftOfficeaccess~L_ApplicationSettings~*' { $settingName = $settingName.Replace('access16v2~Policy~L_MicrosoftOfficeaccess~L_ApplicationSettings', 'MicrosoftAccess_') } + 'excel16v2~Policy~L_MicrosoftOfficeExcel~L_ExcelOptions~*' { $settingName = $settingName.Replace('excel16v2~Policy~L_MicrosoftOfficeExcel~L_ExcelOptions', 'MicrosoftExcel_') } + 'word16v2~Policy~L_MicrosoftOfficeWord~L_WordOptions~*' { $settingName = $settingName.Replace('word16v2~Policy~L_MicrosoftOfficeWord~L_WordOptions', 'MicrosoftWord_') } + 'ppt16v2~Policy~L_MicrosoftOfficePowerPoint~L_PowerPointOptions~*' { $settingName = $settingName.Replace('ppt16v2~Policy~L_MicrosoftOfficePowerPoint~L_PowerPointOptions', 'MicrosoftPowerPoint_') } + 'proj16v2~Policy~L_Proj~L_ProjectOptions~*' { $settingName = $settingName.Replace('proj16v2~Policy~L_Proj~L_ProjectOptions', 'MicrosoftProject_') } + 'visio16v2~Policy~L_MicrosoftVisio~L_VisioOptions~*' { $settingName = $settingName.Replace('visio16v2~Policy~L_MicrosoftVisio~L_VisioOptions', 'MicrosoftVisio_') } + 'pub16v2~Policy~L_MicrosoftOfficePublisher~*' { $settingName = $settingName.Replace('pub16v2~Policy~L_MicrosoftOfficePublisher', 'MicrosoftPublisherV2_') } + 'pub16v3~Policy~L_MicrosoftOfficePublisher~*' { $settingName = $settingName.Replace('pub16v3~Policy~L_MicrosoftOfficePublisher', 'MicrosoftPublisherV3_') } + '*~L_Security~*' { $settingName = $settingName.Replace('~L_Security', 'Security') } + '*~L_TrustCenter*' { $settingName = $settingName.Replace('~L_TrustCenter', '_TrustCenter') } + '*~L_ProtectedView_*' { $settingName = $settingName.Replace('~L_ProtectedView', 'ProtectedView') } + '*~L_FileBlockSettings_*' { $settingName = $settingName.Replace('~L_FileBlockSettings', 'FileBlockSettings') } + '*~L_TrustedLocations*' { $settingName = $settingName.Replace('~L_TrustedLocations', 'TrustedLocations') } } } @@ -2729,7 +2781,7 @@ function Update-IntuneDeviceConfigurationPolicy 'settings' = $Settings } $body = $policy | ConvertTo-Json -Depth 20 - #write-verbose -Message $body + #Write-Verbose -Message $body Invoke-MgGraphRequest -Method PUT -Uri $Uri -Body $body -ErrorAction Stop } catch diff --git a/ResourceGenerator/M365DSCResourceGenerator.psm1 b/ResourceGenerator/M365DSCResourceGenerator.psm1 index 8073abe8d2..68b1aae17d 100644 --- a/ResourceGenerator/M365DSCResourceGenerator.psm1 +++ b/ResourceGenerator/M365DSCResourceGenerator.psm1 @@ -278,6 +278,10 @@ function New-M365DSCResource $deviceDefinitionSettings = @() foreach ($deviceTemplateSetting in $deviceTemplateSettings) { + foreach ($deviceChildSetting in $deviceTemplateSetting.ChildSettings) + { + $deviceChildSetting.DisplayName += " - Depends on $($deviceTemplateSetting.Name)" + } $deviceDefinitionSettings += New-ParameterDefinitionFromSettingsCatalogTemplateSetting ` -TemplateSetting $deviceTemplateSetting } @@ -285,6 +289,10 @@ function New-M365DSCResource $userDefinitionSettings = @() foreach ($userTemplateSetting in $userTemplateSettings) { + foreach ($userChildSetting in $userTemplateSetting.ChildSettings) + { + $userChildSetting.DisplayName += " - Depends on $($userTemplateSetting.Name)" + } $userDefinitionSettings += New-ParameterDefinitionFromSettingsCatalogTemplateSetting ` -TemplateSetting $userTemplateSetting } @@ -308,14 +316,14 @@ function New-M365DSCResource MOFInstance = @( @" [ClassVersion("1.0.0.0")] -class MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings +class MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_$($ResourceName) { $($deviceDefinitionSettings.MOF -join "`r`n") }; "@, @" [ClassVersion("1.0.0.0")] -class MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings +class MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_$($ResourceName) { $($userDefinitionSettings.MOF -join "`r`n") }; @@ -336,13 +344,13 @@ $($userDefinitionSettings.MOF -join "`r`n") { $parameter -match '\$.*$' $parameterName = $Matches[0].Replace('$', '') - $parameterType = 'IntuneSettingsCatalog' + $parameterName + $parameterType = 'IntuneSettingsCatalog' + $parameterName + $(if ($parameterName -in @('DeviceSettings', 'UserSettings')) { "_$ResourceName" }) $cimInstance = $definitionSettings.MOFInstance | Where-Object -FilterScript { $_ -like "*$parameterType`n*" -or $_ -like "*$parameterType`r`n*" } $rowFilter = '\[.*;' $cimRows = [regex]::Matches($cimInstance, $rowFilter) | Foreach-Object { $_.Value } - $cimPropertyNamequery = '[a-zA-Z_]+[\[\]]*;' + $cimPropertyNamequery = '[a-zA-Z0-9_]+[\[\]]*;' $cimProperties = @() foreach ($row in $cimRows) { @@ -364,7 +372,7 @@ $($userDefinitionSettings.MOF -join "`r`n") Name = $parameterName IsComplexType = $true IsMandatory = $false - IsArray = $true + IsArray = $parameter -match '\[.*\[\]\]' Type = $parameterType Properties = $cimProperties } @@ -539,6 +547,7 @@ $($userDefinitionSettings.MOF -join "`r`n") [array]`$settings = Get-$($CmdLetNoun)Setting `` -DeviceManagementConfigurationPolicyId `$Id `` -ExpandProperty 'settingDefinitions' `` + -All `` -ErrorAction Stop `$policySettings = @{} @@ -662,7 +671,7 @@ $($userDefinitionSettings.MOF -join "`r`n") $defaultCreateParameters = @" `$settings = Get-IntuneSettingCatalogPolicySetting `` -DSCParams ([System.Collections.Hashtable]`$BoundParameters) `` - -TemplateId `$templateReferenceId$(if ($containsDeviceAndUserSettings) { " ```r`n -ContainsDeviceAndUserSettings" })`r`n + -TemplateId `$templateReferenceId$(if ($containsDeviceAndUserSettings) { " ```r`n -ContainsDeviceAndUserSettings" }) `$createParameters = @{ Name = `$DisplayName @@ -785,7 +794,7 @@ $($userDefinitionSettings.MOF -join "`r`n") $defaultUpdateParameters = @" `$settings = Get-IntuneSettingCatalogPolicySetting `` -DSCParams ([System.Collections.Hashtable]`$BoundParameters) `` - -TemplateId `$templateReferenceId$(if ($containsDeviceAndUserSettings) { " ```r`n -ContainsDeviceAndUserSettings" })`r`n + -TemplateId `$templateReferenceId$(if ($containsDeviceAndUserSettings) { " ```r`n -ContainsDeviceAndUserSettings" }) Update-IntuneDeviceConfigurationPolicy `` -DeviceConfigurationPolicyId `$currentInstance.Id `` @@ -3894,7 +3903,12 @@ function New-SettingsCatalogSettingDefinitionSettingsFromTemplate { $newName = Get-SettingDefinitionNameWithParentFromOffsetUri -OffsetUri $_.OffsetUri -SettingName $previousSettingName -Skip $skip if ($newName -eq $newSettingName) { - $combinationMatchesWithOffsetUri += $_ + # Exclude v2 versions from the comparison + if ($settingDefinition.Id -like "*_v2" -and $_.Id -ne $settingDefinition.Id.Replace('_v2', '') -or + $settingDefinition.Id -notlike "*_v2" -and $_.Id -ne $settingDefinition.Id + "_v2") + { + $combinationMatchesWithOffsetUri += $_ + } } } $settingsWithSameName = $combinationMatchesWithOffsetUri @@ -3904,6 +3918,10 @@ function New-SettingsCatalogSettingDefinitionSettingsFromTemplate { if ($breakCounter -lt 8) { + if ($settingDefinition.Id -like "*_v2" -and $newSettingName -notlike "*_v2") + { + $newSettingName += "_v2" + } $settingName = $newSettingName } else @@ -3926,21 +3944,22 @@ function New-SettingsCatalogSettingDefinitionSettingsFromTemplate { $settingName = Get-SettingDefinitionNameWithParentFromOffsetUri -OffsetUri $SettingDefinition.OffsetUri -SettingName $settingName } - # Simplify names from the OffsetUri. This is done to make the names more readable, especially in case of long and complex OffsetUris. + # Simplify names from the OffsetUri. This is done to make the names more readable, especially in case of long and complex OffsetUris. switch -wildcard ($settingName) { - { 'access16v2~Policy~L_MicrosoftOfficeaccess~L_ApplicationSettings~L_Security*' } { $settingName = $settingName.Replace('access16v2~Policy~L_MicrosoftOfficeaccess~L_ApplicationSettings', 'MicrosoftAccess_') } - { 'excel16v2~Policy~L_MicrosoftOfficeExcel~L_ExcelOptions~*' } { $settingName = $settingName.Replace('excel16v2~Policy~L_MicrosoftOfficeExcel~L_ExcelOptions', 'MicrosoftExcel_') } - { 'word16v2~Policy~L_MicrosoftOfficeWord~L_WordOptions~*' } { $settingName = $settingName.Replace('word16v2~Policy~L_MicrosoftOfficeWord~L_WordOptions', 'MicrosoftWord_') } - { 'ppt16v2~Policy~L_MicrosoftOfficePowerPoint~L_PowerPointOptions~*' } { $settingName = $settingName.Replace('ppt16v2~Policy~L_MicrosoftOfficePowerPoint~L_PowerPointOptions', 'MicrosoftPowerPoint_') } - { 'proj16v2~Policy~L_Proj~L_ProjectOptions~*' } { $settingName = $settingName.Replace('proj16v2~Policy~L_Proj~L_ProjectOptions', 'MicrosoftProject_') } - { 'visio16v2~Policy~L_MicrosoftVisio~L_VisioOptions~*' } { $settingName = $settingName.Replace('visio16v2~Policy~L_MicrosoftVisio~L_VisioOptions', 'MicrosoftVisio_') } - { 'pub16v*~Policy~L_MicrosoftOfficePublisher~' } { $settingName = [Regex]::replace($settingName, 'pub16v(.*)~Policy~L_MicrosoftOfficePublisher', 'MicrosoftPublisher_') } - { '*~L_Security~*' } { $settingName = $settingName.Replace('~L_Security', 'Security') } - { '*~L_TrustCenter_'} { $settingName = $settingName.Replace('~L_TrustCenter', '_TrustCenter') } - { '*~L_ProtectedView_' } { $settingName = $settingName.Replace('~L_ProtectedView', 'ProtectedView') } - { '*~L_FileBlockSettings_' } { $settingName = $settingName.Replace('~L_FileBlockSettings', 'FileBlockSettings') } - { '*~L_TrustedLocations' } { $settingName = $settingName.Replace('~L_TrustedLocations', 'TrustedLocations') } + 'access16v2~Policy~L_MicrosoftOfficeaccess~L_ApplicationSettings~*' { $settingName = $settingName.Replace('access16v2~Policy~L_MicrosoftOfficeaccess~L_ApplicationSettings', 'MicrosoftAccess_') } + 'excel16v2~Policy~L_MicrosoftOfficeExcel~L_ExcelOptions~*' { $settingName = $settingName.Replace('excel16v2~Policy~L_MicrosoftOfficeExcel~L_ExcelOptions', 'MicrosoftExcel_') } + 'word16v2~Policy~L_MicrosoftOfficeWord~L_WordOptions~*' { $settingName = $settingName.Replace('word16v2~Policy~L_MicrosoftOfficeWord~L_WordOptions', 'MicrosoftWord_') } + 'ppt16v2~Policy~L_MicrosoftOfficePowerPoint~L_PowerPointOptions~*' { $settingName = $settingName.Replace('ppt16v2~Policy~L_MicrosoftOfficePowerPoint~L_PowerPointOptions', 'MicrosoftPowerPoint_') } + 'proj16v2~Policy~L_Proj~L_ProjectOptions~*' { $settingName = $settingName.Replace('proj16v2~Policy~L_Proj~L_ProjectOptions', 'MicrosoftProject_') } + 'visio16v2~Policy~L_MicrosoftVisio~L_VisioOptions~*' { $settingName = $settingName.Replace('visio16v2~Policy~L_MicrosoftVisio~L_VisioOptions', 'MicrosoftVisio_') } + 'pub16v2~Policy~L_MicrosoftOfficePublisher~*' { $settingName = $settingName.Replace('pub16v2~Policy~L_MicrosoftOfficePublisher', 'MicrosoftPublisherV2_') } + 'pub16v3~Policy~L_MicrosoftOfficePublisher~*' { $settingName = $settingName.Replace('pub16v3~Policy~L_MicrosoftOfficePublisher', 'MicrosoftPublisherV3_') } + '*~L_Security~*' { $settingName = $settingName.Replace('~L_Security', 'Security') } + '*~L_TrustCenter*' { $settingName = $settingName.Replace('~L_TrustCenter', '_TrustCenter') } + '*~L_ProtectedView_*' { $settingName = $settingName.Replace('~L_ProtectedView', 'ProtectedView') } + '*~L_FileBlockSettings_*' { $settingName = $settingName.Replace('~L_FileBlockSettings', 'FileBlockSettings') } + '*~L_TrustedLocations*' { $settingName = $settingName.Replace('~L_TrustedLocations', 'TrustedLocations') } } } @@ -4109,7 +4128,7 @@ class $ "@ - $mofDefinition = $mofParameterTemplate.Replace("", $TemplateSetting.DisplayName) + $mofDefinition = $mofParameterTemplate.Replace("", $TemplateSetting.DisplayName.Replace("`r`n", "")) $optionsString = "" $valueMapString = "" if ($TemplateSetting.Options) { diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneSecurityBaselineMicrosoft365AppsForEnterprise.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneSecurityBaselineMicrosoft365AppsForEnterprise.Tests.ps1 new file mode 100644 index 0000000000..a232790964 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneSecurityBaselineMicrosoft365AppsForEnterprise.Tests.ps1 @@ -0,0 +1,500 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource "IntuneSecurityBaselineMicrosoft365AppsForEnterprise" -GenericStubModule $GenericStubPath +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName Get-PSSession -MockWith { + } + + Mock -CommandName Remove-PSSession -MockWith { + } + + Mock -CommandName Update-MgBetaDeviceManagementConfigurationPolicy -MockWith { + } + + Mock -CommandName New-MgBetaDeviceManagementConfigurationPolicy -MockWith { + return @{ + Id = '12345-12345-12345-12345-12345' + } + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicy -MockWith { + return @{ + Id = '12345-12345-12345-12345-12345' + Description = 'My Test' + Name = 'My Test' + RoleScopeTagIds = @("FakeStringValue") + TemplateReference = @{ + TemplateId = '90316f12-246d-44c6-a767-f87692e86083_2' + } + } + } + + Mock -CommandName Remove-MgBetaDeviceManagementConfigurationPolicy -MockWith { + } + + Mock -CommandName Update-IntuneDeviceConfigurationPolicy -MockWith { + } + + Mock -CommandName Get-IntuneSettingCatalogPolicySetting -MockWith { + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicySetting -MockWith { + return @( + @{ + Id = '0' + SettingDefinitions = @( + @{ + Id = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation' + Name = 'L_ProtectionFromZoneElevation' + OffsetUri = '/Config/office16v2~Policy~L_MicrosoftOfficemachine~L_SecuritySettingsMachine~L_IESecurity/L_ProtectionFromZoneElevation' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + } + }, + @{ + Id = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation_l_excelexe99' + Name = 'L_excelexe99' + OffsetUri = '/Config/office16v2~Policy~L_MicrosoftOfficemachine~L_SecuritySettingsMachine~L_IESecurity/L_ProtectionFromZoneElevation' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + options = @( + @{ + name = 'False' + itemId = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation_l_excelexe99_0' + dependentOn = @( + @{ + dependentOn = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation_1' + parentSettingId = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation' + } + ) + }, + @{ + name = 'True' + itemId = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation_l_excelexe99_1' + dependentOn = @( + @{ + dependentOn = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation_1' + parentSettingId = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation' + } + ) + } + ) + } + }, + @{ + Id = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation_l_grooveexe98' + Name = 'L_grooveexe98' + OffsetUri = '/Config/office16v2~Policy~L_MicrosoftOfficemachine~L_SecuritySettingsMachine~L_IESecurity/L_ProtectionFromZoneElevation' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + options = @( + @{ + name = 'False' + itemId = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation_l_grooveexe98_0' + dependentOn = @( + @{ + dependentOn = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation_1' + parentSettingId = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation' + } + ) + }, + @{ + name = 'True' + itemId = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation_l_grooveexe98_1' + dependentOn = @( + @{ + dependentOn = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation_1' + parentSettingId = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation' + } + ) + } + ) + } + }, + @{ + Id = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation_l_mspubexe100' + Name = 'L_mspubexe100' + OffsetUri = '/Config/office16v2~Policy~L_MicrosoftOfficemachine~L_SecuritySettingsMachine~L_IESecurity/L_ProtectionFromZoneElevation' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + options = @( + @{ + name = 'False' + itemId = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation_l_mspubexe100_0' + dependentOn = @( + @{ + dependentOn = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation_1' + parentSettingId = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation' + } + ) + }, + @{ + name = 'True' + itemId = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation_l_mspubexe100_1' + dependentOn = @( + @{ + dependentOn = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation_1' + parentSettingId = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation' + } + ) + } + ) + } + } + ) + SettingInstance = @{ + SettingDefinitionId = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = '7f23a242-9f64-47a5-8a57-a4675ca74c2b' + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + choiceSettingValue = @{ + value = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation_1' + children = @( + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + settingDefinitionId = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation_l_grooveexe98' + choiceSettingValue = @{ + children = @() + value = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation_l_grooveexe98_1' + } + }, + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + settingDefinitionId = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation_l_excelexe99' + choiceSettingValue = @{ + children = @() + value = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation_l_excelexe99_1' + } + }, + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + settingDefinitionId = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation_l_mspubexe100' + choiceSettingValue = @{ + children = @() + value = 'device_vendor_msft_policy_config_office16v2~policy~l_microsoftofficemachine~l_securitysettingsmachine~l_iesecurity_l_protectionfromzoneelevation_l_mspubexe100_1' + } + } + ) + } + } + } + }, + @{ + Id = '1' + SettingDefinitions = @( + @{ + Id = 'user_vendor_msft_policy_config_word16v2~policy~l_microsoftofficeword~l_wordoptions~l_security~l_trustcenter~l_fileblocksettings_l_word2003binarydocumentsandtemplates' + Name = 'L_Word2003BinaryDocumentsAndTemplates' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + options = @( + @{ + name = 'Enabled' + itemId = 'user_vendor_msft_policy_config_word16v2~policy~l_microsoftofficeword~l_wordoptions~l_security~l_trustcenter~l_fileblocksettings_l_word2003binarydocumentsandtemplates_1' + } + ) + } + }, + @{ + Id = 'user_vendor_msft_policy_config_word16v2~policy~l_microsoftofficeword~l_wordoptions~l_security~l_trustcenter~l_fileblocksettings_l_word2003binarydocumentsandtemplates_l_word2003binarydocumentsandtemplatesdropid' + Name = 'L_Word2003BinaryDocumentsAndTemplatesDropID' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + options = @( + @{ + name = 'Open/Save blocked, use open policy' + itemId = 'user_vendor_msft_policy_config_word16v2~policy~l_microsoftofficeword~l_wordoptions~l_security~l_trustcenter~l_fileblocksettings_l_word2003binarydocumentsandtemplates_l_word2003binarydocumentsandtemplatesdropid_2' + dependentOn = @( + @{ + dependentOn = 'user_vendor_msft_policy_config_word16v2~policy~l_microsoftofficeword~l_wordoptions~l_security~l_trustcenter~l_fileblocksettings_l_word2003binarydocumentsandtemplates_1' + parentSettingId = 'user_vendor_msft_policy_config_word16v2~policy~l_microsoftofficeword~l_wordoptions~l_security~l_trustcenter~l_fileblocksettings_l_word2003binarydocumentsandtemplates' + } + ) + } + ) + } + } + ) + SettingInstance = @{ + SettingDefinitionId = 'user_vendor_msft_policy_config_word16v2~policy~l_microsoftofficeword~l_wordoptions~l_security~l_trustcenter~l_fileblocksettings_l_word2003binarydocumentsandtemplates' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = '23436aa2-f056-40bd-aca3-9bc84b2aeff0' + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + choiceSettingValue = @{ + value = 'user_vendor_msft_policy_config_word16v2~policy~l_microsoftofficeword~l_wordoptions~l_security~l_trustcenter~l_fileblocksettings_l_word2003binarydocumentsandtemplates_1' + children = @( + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + settingDefinitionId = 'user_vendor_msft_policy_config_word16v2~policy~l_microsoftofficeword~l_wordoptions~l_security~l_trustcenter~l_fileblocksettings_l_word2003binarydocumentsandtemplates_l_word2003binarydocumentsandtemplatesdropid' + choiceSettingValue = @{ + children = @() + value = 'user_vendor_msft_policy_config_word16v2~policy~l_microsoftofficeword~l_wordoptions~l_security~l_trustcenter~l_fileblocksettings_l_word2003binarydocumentsandtemplates_l_word2003binarydocumentsandtemplatesdropid_2' + } + } + ) + } + } + } + } + ) + } + + Mock -CommandName Update-DeviceConfigurationPolicyAssignment -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicyAssignment -MockWith { + return @(@{ + Id = '12345-12345-12345-12345-12345' + Source = 'direct' + SourceId = '12345-12345-12345-12345-12345' + Target = @{ + DeviceAndAppManagementAssignmentFilterId = '12345-12345-12345-12345-12345' + DeviceAndAppManagementAssignmentFilterType = 'none' + AdditionalProperties = @( + @{ + '@odata.type' = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + } + ) + } + }) + } + + } + # Test contexts + Context -Name "The IntuneSecurityBaselineMicrosoft365AppsForEnterprise should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + deviceAndAppManagementAssignmentFilterType = 'none' + } -ClientOnly) + ) + Description = "My Test" + DeviceSettings = [CimInstance]( + New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings -Property @{ + L_ProtectionFromZoneElevation = '1' + L_grooveexe98 = '1' + L_excelexe99 = '1' + L_mspubexe100 = '1' + } -ClientOnly + ) + Id = "12345-12345-12345-12345-12345" + DisplayName = "My Test" + RoleScopeTagIds = @("FakeStringValue") + UserSettings = [CimInstance]( + New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings -Property @{ + L_Word2003BinaryDocumentsAndTemplates = '1' + L_Word2003BinaryDocumentsAndTemplatesDropID = '2' + } -ClientOnly + ) + Ensure = "Present" + Credential = $Credential + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicy -MockWith { + return $null + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + It 'Should Create the group from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-MgBetaDeviceManagementConfigurationPolicy -Exactly 1 + } + } + + Context -Name "The IntuneSecurityBaselineMicrosoft365AppsForEnterprise exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + deviceAndAppManagementAssignmentFilterType = 'none' + } -ClientOnly) + ) + Description = "My Test" + DeviceSettings = [CimInstance]( + New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings -Property @{ + L_ProtectionFromZoneElevation = '1' + L_grooveexe98 = '1' + L_excelexe99 = '1' + L_mspubexe100 = '1' + } -ClientOnly + ) + Id = "12345-12345-12345-12345-12345" + DisplayName = "My Test" + RoleScopeTagIds = @("FakeStringValue") + UserSettings = [CimInstance]( + New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings -Property @{ + L_Word2003BinaryDocumentsAndTemplates = '1' + L_Word2003BinaryDocumentsAndTemplatesDropID = '2' + } -ClientOnly + ) + Ensure = "Absent" + Credential = $Credential + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should Remove the group from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-MgBetaDeviceManagementConfigurationPolicy -Exactly 1 + } + } + Context -Name "The IntuneSecurityBaselineMicrosoft365AppsForEnterprise Exists and Values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + deviceAndAppManagementAssignmentFilterType = 'none' + } -ClientOnly) + ) + Description = "My Test" + DeviceSettings = [CimInstance]( + New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings -Property @{ + L_ProtectionFromZoneElevation = '1' + L_grooveexe98 = '1' + L_excelexe99 = '1' + L_mspubexe100 = '1' + } -ClientOnly + ) + Id = "12345-12345-12345-12345-12345" + DisplayName = "My Test" + RoleScopeTagIds = @("FakeStringValue") + UserSettings = [CimInstance]( + New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings -Property @{ + L_Word2003BinaryDocumentsAndTemplates = '1' + L_Word2003BinaryDocumentsAndTemplatesDropID = '2' + } -ClientOnly + ) + Ensure = "Present" + Credential = $Credential + } + } + + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The IntuneSecurityBaselineMicrosoft365AppsForEnterprise exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + deviceAndAppManagementAssignmentFilterType = 'none' + } -ClientOnly) + ) + Description = "My Test" + DeviceSettings = [CimInstance]( + New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings -Property @{ + L_ProtectionFromZoneElevation = '1' + L_grooveexe98 = '1' + L_excelexe99 = '1' + L_mspubexe100 = '0' # Drift + } -ClientOnly + ) + Id = "12345-12345-12345-12345-12345" + DisplayName = "My Test" + RoleScopeTagIds = @("FakeStringValue") + UserSettings = [CimInstance]( + New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings -Property @{ + L_Word2003BinaryDocumentsAndTemplates = '1' + L_Word2003BinaryDocumentsAndTemplatesDropID = '2' + } -ClientOnly + ) + Ensure = "Present" + Credential = $Credential + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Update-IntuneDeviceConfigurationPolicy -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope From 5d7776034f6a0cf4f234dcb66c3d6d640e196d9a Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Tue, 15 Oct 2024 13:23:03 +0200 Subject: [PATCH 222/252] Switch types of device and user scoped settings --- CHANGELOG.md | 2 ++ ...T_IntuneAccountProtectionPolicyWindows10.psm1 | 4 ++-- ...neAccountProtectionPolicyWindows10.schema.mof | 8 ++++---- .../1-Create.ps1 | 4 ++-- .../2-Update.ps1 | 4 ++-- ...uneAccountProtectionPolicyWindows10.Tests.ps1 | 16 ++++++++-------- 6 files changed, 20 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index df501deccd..5847eedf35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,8 @@ * Migrate to new Settings Catalog cmdlets. * IntuneMobileAppsMacOSLobApp * Initial release +* IntuneSecurityBaselineMicrosoft365AppsForEnterprise + * Initial release * M365DSCDRGUtil * Fixes an issue for the handling of skipped one-property elements in the Settings Catalog. FIXES [#5086](https://github.com/microsoft/Microsoft365DSC/issues/5086) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicyWindows10/MSFT_IntuneAccountProtectionPolicyWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicyWindows10/MSFT_IntuneAccountProtectionPolicyWindows10.psm1 index 5188f9fe59..8f3496d87e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicyWindows10/MSFT_IntuneAccountProtectionPolicyWindows10.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicyWindows10/MSFT_IntuneAccountProtectionPolicyWindows10.psm1 @@ -682,7 +682,7 @@ function Export-TargetResource { $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` -ComplexObject $Results.DeviceSettings ` - -CIMInstanceName 'MicrosoftGraphIntuneSettingsCatalogDeviceSettings' + -CIMInstanceName 'MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneAccountProtectionPolicyWindows10' if (-not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) { $Results.DeviceSettings = $complexTypeStringResult @@ -696,7 +696,7 @@ function Export-TargetResource { $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` -ComplexObject $Results.UserSettings ` - -CIMInstanceName 'MicrosoftGraphIntuneSettingsCatalogUserSettings' + -CIMInstanceName 'MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneAccountProtectionPolicyWindows10' if (-not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) { $Results.UserSettings = $complexTypeStringResult diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicyWindows10/MSFT_IntuneAccountProtectionPolicyWindows10.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicyWindows10/MSFT_IntuneAccountProtectionPolicyWindows10.schema.mof index 269777f6a7..47f1cc08cd 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicyWindows10/MSFT_IntuneAccountProtectionPolicyWindows10.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAccountProtectionPolicyWindows10/MSFT_IntuneAccountProtectionPolicyWindows10.schema.mof @@ -10,7 +10,7 @@ class MSFT_DeviceManagementConfigurationPolicyAssignments }; [ClassVersion("1.0.0.0")] -class MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings +class MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneAccountProtectionPolicyWindows10 { [Write, Description("Credential Guard (0: (Disabled) Turns off Credential Guard remotely if configured previously without UEFI Lock., 1: (Enabled with UEFI lock) Turns on Credential Guard with UEFI lock., 2: (Enabled without lock) Turns on Credential Guard without UEFI lock.)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String LsaCfgFlags; [Write, Description("Facial Features Use Enhanced Anti Spoofing (false: Disabled, true: Enabled)"), ValueMap{"false", "true"}, Values{"false", "true"}] String FacialFeaturesUseEnhancedAntiSpoofing; @@ -28,7 +28,7 @@ class MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings }; [ClassVersion("1.0.0.0")] -class MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings +class MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneAccountProtectionPolicyWindows10 { [Write, Description("Enable Pin Recovery (User) (false: Disabled, true: Enabled)"), ValueMap{"false", "true"}, Values{"false", "true"}] String EnablePinRecovery; [Write, Description("Expiration (User)")] SInt32 Expiration; @@ -49,8 +49,8 @@ class MSFT_IntuneAccountProtectionPolicyWindows10 : OMI_BaseResource [Key, Description("Policy name")] String DisplayName; [Write, Description("List of Scope Tags for this Entity instance.")] String RoleScopeTagIds[]; [Write, Description("The unique identifier for an entity. Read-only.")] String Id; - [Write, Description("The policy settings for the device scope."), EmbeddedInstance("MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings")] String DeviceSettings; - [Write, Description("The policy settings for the user scope"), EmbeddedInstance("MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings")] String UserSettings; + [Write, Description("The policy settings for the device scope."), EmbeddedInstance("MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneAccountProtectionPolicyWindows10")] String DeviceSettings; + [Write, Description("The policy settings for the user scope"), EmbeddedInstance("MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneAccountProtectionPolicyWindows10")] String UserSettings; [Write, Description("Represents the assignment to the Intune policy."), EmbeddedInstance("MSFT_DeviceManagementConfigurationPolicyAssignments")] String Assignments[]; [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAccountProtectionPolicyWindows10/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAccountProtectionPolicyWindows10/1-Create.ps1 index 13e7d999e7..d5b7854a82 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneAccountProtectionPolicyWindows10/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAccountProtectionPolicyWindows10/1-Create.ps1 @@ -25,12 +25,12 @@ Configuration Example IntuneAccountProtectionPolicyWindows10 'myAccountProtectionPolicy' { DisplayName = 'test' - DeviceSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings + DeviceSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneAccountProtectionPolicyWindows10 { History = 10 EnablePinRecovery = 'true' } - UserSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings + UserSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneAccountProtectionPolicyWindows10 { History = 20 EnablePinRecovery = 'true' diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAccountProtectionPolicyWindows10/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAccountProtectionPolicyWindows10/2-Update.ps1 index 3752c70dd6..4ea17bbc2c 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneAccountProtectionPolicyWindows10/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAccountProtectionPolicyWindows10/2-Update.ps1 @@ -25,12 +25,12 @@ Configuration Example IntuneAccountProtectionPolicyWindows10 'myAccountProtectionPolicy' { DisplayName = 'test' - DeviceSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings + DeviceSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneAccountProtectionPolicyWindows10 { History = 10 EnablePinRecovery = 'true' } - UserSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings + UserSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneAccountProtectionPolicyWindows10 { History = 30 # Updated property EnablePinRecovery = 'true' diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAccountProtectionPolicyWindows10.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAccountProtectionPolicyWindows10.Tests.ps1 index b83b974567..d3d8323968 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAccountProtectionPolicyWindows10.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAccountProtectionPolicyWindows10.Tests.ps1 @@ -219,7 +219,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ) Description = "My Test" DeviceSettings = [CimInstance]( - New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings -Property @{ + New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneAccountProtectionPolicyWindows10 -Property @{ History = 10 } -ClientOnly ) @@ -227,7 +227,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { DisplayName = "My Test" RoleScopeTagIds = @("FakeStringValue") UserSettings = [CimInstance]( - New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings -Property @{ + New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneAccountProtectionPolicyWindows10 -Property @{ History = 20 } -ClientOnly ) @@ -263,7 +263,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ) Description = "My Test" DeviceSettings = [CimInstance]( - New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings -Property @{ + New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneAccountProtectionPolicyWindows10 -Property @{ History = 10 } -ClientOnly ) @@ -271,7 +271,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { DisplayName = "My Test" RoleScopeTagIds = @("FakeStringValue") UserSettings = [CimInstance]( - New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings -Property @{ + New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneAccountProtectionPolicyWindows10 -Property @{ History = 20 } -ClientOnly ) @@ -305,7 +305,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ) Description = "My Test" DeviceSettings = [CimInstance]( - New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings -Property @{ + New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneAccountProtectionPolicyWindows10 -Property @{ History = 10 } -ClientOnly ) @@ -313,7 +313,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { DisplayName = "My Test" RoleScopeTagIds = @("FakeStringValue") UserSettings = [CimInstance]( - New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings -Property @{ + New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneAccountProtectionPolicyWindows10 -Property @{ History = 20 } -ClientOnly ) @@ -339,7 +339,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ) Description = "My Test" DeviceSettings = [CimInstance]( - New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings -Property @{ + New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneAccountProtectionPolicyWindows10 -Property @{ History = 10 } -ClientOnly ) @@ -347,7 +347,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { DisplayName = "My Test" RoleScopeTagIds = @("FakeStringValue") UserSettings = [CimInstance]( - New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings -Property @{ + New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneAccountProtectionPolicyWindows10 -Property @{ History = 30 # Drift } -ClientOnly ) From ce0c78de0d860a45f755c5de5058476833c3d515 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 15 Oct 2024 12:30:23 +0000 Subject: [PATCH 223/252] Updated Resources and Cmdlet documentation pages --- .../IntuneAccountProtectionPolicyWindows10.md | 16 +- ...tyBaselineMicrosoft365AppsForEnterprise.md | 678 ++++++++++++++++++ 2 files changed, 686 insertions(+), 8 deletions(-) create mode 100644 docs/docs/resources/intune/IntuneSecurityBaselineMicrosoft365AppsForEnterprise.md diff --git a/docs/docs/resources/intune/IntuneAccountProtectionPolicyWindows10.md b/docs/docs/resources/intune/IntuneAccountProtectionPolicyWindows10.md index b48a438afa..8a3356509d 100644 --- a/docs/docs/resources/intune/IntuneAccountProtectionPolicyWindows10.md +++ b/docs/docs/resources/intune/IntuneAccountProtectionPolicyWindows10.md @@ -8,8 +8,8 @@ | **DisplayName** | Key | String | Policy name | | | **RoleScopeTagIds** | Write | StringArray[] | List of Scope Tags for this Entity instance. | | | **Id** | Write | String | The unique identifier for an entity. Read-only. | | -| **DeviceSettings** | Write | MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings | The policy settings for the device scope. | | -| **UserSettings** | Write | MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings | The policy settings for the user scope | | +| **DeviceSettings** | Write | MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneAccountProtectionPolicyWindows10 | The policy settings for the device scope. | | +| **UserSettings** | Write | MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneAccountProtectionPolicyWindows10 | The policy settings for the user scope | | | **Assignments** | Write | MSFT_DeviceManagementConfigurationPolicyAssignments[] | Represents the assignment to the Intune policy. | | | **Ensure** | Write | String | Present ensures the policy exists, absent ensures it is removed. | `Present`, `Absent` | | **Credential** | Write | PSCredential | Credentials of the Admin | | @@ -33,7 +33,7 @@ | **groupDisplayName** | Write | String | The group Display Name that is the target of the assignment. | | | **collectionId** | Write | String | The collection Id that is the target of the assignment.(ConfigMgr) | | -### MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings +### MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneAccountProtectionPolicyWindows10 #### Parameters @@ -53,7 +53,7 @@ | **UseCertificateForOnPremAuth** | Write | String | Use Certificate For On Prem Auth (false: Disabled, true: Enabled) | `false`, `true` | | **UsePassportForWork** | Write | String | Use Windows Hello For Business (Device) (false: Disabled, true: Enabled) | `false`, `true` | -### MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings +### MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneAccountProtectionPolicyWindows10 #### Parameters @@ -131,12 +131,12 @@ Configuration Example IntuneAccountProtectionPolicyWindows10 'myAccountProtectionPolicy' { DisplayName = 'test' - DeviceSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings + DeviceSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneAccountProtectionPolicyWindows10 { History = 10 EnablePinRecovery = 'true' } - UserSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings + UserSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneAccountProtectionPolicyWindows10 { History = 20 EnablePinRecovery = 'true' @@ -178,12 +178,12 @@ Configuration Example IntuneAccountProtectionPolicyWindows10 'myAccountProtectionPolicy' { DisplayName = 'test' - DeviceSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings + DeviceSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneAccountProtectionPolicyWindows10 { History = 10 EnablePinRecovery = 'true' } - UserSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings + UserSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneAccountProtectionPolicyWindows10 { History = 30 # Updated property EnablePinRecovery = 'true' diff --git a/docs/docs/resources/intune/IntuneSecurityBaselineMicrosoft365AppsForEnterprise.md b/docs/docs/resources/intune/IntuneSecurityBaselineMicrosoft365AppsForEnterprise.md new file mode 100644 index 0000000000..78a3f1969a --- /dev/null +++ b/docs/docs/resources/intune/IntuneSecurityBaselineMicrosoft365AppsForEnterprise.md @@ -0,0 +1,678 @@ +# IntuneSecurityBaselineMicrosoft365AppsForEnterprise + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Description** | Write | String | Policy description | | +| **DisplayName** | Key | String | Policy name | | +| **RoleScopeTagIds** | Write | StringArray[] | List of Scope Tags for this Entity instance. | | +| **Id** | Write | String | The unique identifier for an entity. Read-only. | | +| **DeviceSettings** | Write | MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneSecurityBaselineMicrosoft365AppsForEnterprise | The policy settings for the device scope | | +| **UserSettings** | Write | MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneSecurityBaselineMicrosoft365AppsForEnterprise | The policy settings for the user scope | | +| **Assignments** | Write | MSFT_DeviceManagementConfigurationPolicyAssignments[] | Represents the assignment to the Intune policy. | | +| **Ensure** | Write | String | Present ensures the policy exists, absent ensures it is removed. | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials of the Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **ApplicationSecret** | Write | PSCredential | Secret of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + +### MSFT_DeviceManagementConfigurationPolicyAssignments + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **dataType** | Write | String | The type of the target assignment. | `#microsoft.graph.groupAssignmentTarget`, `#microsoft.graph.allLicensedUsersAssignmentTarget`, `#microsoft.graph.allDevicesAssignmentTarget`, `#microsoft.graph.exclusionGroupAssignmentTarget`, `#microsoft.graph.configurationManagerCollectionAssignmentTarget` | +| **deviceAndAppManagementAssignmentFilterType** | Write | String | The type of filter of the target assignment i.e. Exclude or Include. Possible values are:none, include, exclude. | `none`, `include`, `exclude` | +| **deviceAndAppManagementAssignmentFilterId** | Write | String | The Id of the filter for the target assignment. | | +| **groupId** | Write | String | The group Id that is the target of the assignment. | | +| **groupDisplayName** | Write | String | The group Display Name that is the target of the assignment. | | +| **collectionId** | Write | String | The collection Id that is the target of the assignment.(ConfigMgr) | | + +### MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneSecurityBaselineMicrosoft365AppsForEnterprise + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Pol_SecGuide_A001_Block_Flash** | Write | String | Block Flash activation in Office documents (0: Disabled, 1: Enabled) | `0`, `1` | +| **Pol_SecGuide_Block_Flash** | Write | String | Block Flash player in Office (Device) - Depends on Pol_SecGuide_A001_Block_Flash (block all flash activation: Block all activation, block embedded flash activation only: Block embedding/linking, allow other activation, allow all flash activation: Allow all activation) | `block all flash activation`, `block embedded flash activation only`, `allow all flash activation` | +| **Pol_SecGuide_Legacy_JScript** | Write | String | Restrict legacy JScript execution for Office (0: Disabled, 1: Enabled) | `0`, `1` | +| **POL_SG_powerpnt** | Write | SInt32 | PowerPoint: (Device) - Depends on Pol_SecGuide_Legacy_JScript | | +| **POL_SG_onenote** | Write | SInt32 | OneNote: (Device) - Depends on Pol_SecGuide_Legacy_JScript | | +| **POL_SG_mspub** | Write | SInt32 | Publisher: (Device) - Depends on Pol_SecGuide_Legacy_JScript | | +| **POL_SG_msaccess** | Write | SInt32 | Access: (Device) - Depends on Pol_SecGuide_Legacy_JScript | | +| **POL_SG_winproj** | Write | SInt32 | Project: (Device) - Depends on Pol_SecGuide_Legacy_JScript | | +| **POL_SG_visio** | Write | SInt32 | Visio: (Device) - Depends on Pol_SecGuide_Legacy_JScript | | +| **POL_SG_outlook** | Write | SInt32 | Outlook: (Device) - Depends on Pol_SecGuide_Legacy_JScript | | +| **POL_SG_winword** | Write | SInt32 | Word: (Device) - Depends on Pol_SecGuide_Legacy_JScript | | +| **POL_SG_excel** | Write | SInt32 | Excel: (Device) - Depends on Pol_SecGuide_Legacy_JScript | | +| **L_PolicyEnableSIPHighSecurityMode** | Write | String | Configure SIP security mode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_PolicyDisableHttpConnect** | Write | String | Disable HTTP fallback for SIP connection (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_AddonManagement** | Write | String | Add-on Management (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_powerpntexe17** | Write | String | powerpnt.exe (Device) - Depends on L_AddonManagement (0: False, 1: True) | `0`, `1` | +| **L_excelexe15** | Write | String | excel.exe (Device) - Depends on L_AddonManagement (0: False, 1: True) | `0`, `1` | +| **L_visioexe19** | Write | String | visio.exe (Device) - Depends on L_AddonManagement (0: False, 1: True) | `0`, `1` | +| **L_onenoteexe26** | Write | String | onent.exe (Device) - Depends on L_AddonManagement (0: False, 1: True) | `0`, `1` | +| **L_outlookexe22** | Write | String | outlook.exe (Device) - Depends on L_AddonManagement (0: False, 1: True) | `0`, `1` | +| **L_pptviewexe18** | Write | String | pptview.exe (Device) - Depends on L_AddonManagement (0: False, 1: True) | `0`, `1` | +| **L_winwordexe21** | Write | String | winword.exe (Device) - Depends on L_AddonManagement (0: False, 1: True) | `0`, `1` | +| **L_exprwdexe24** | Write | String | exprwd.exe (Device) - Depends on L_AddonManagement (0: False, 1: True) | `0`, `1` | +| **L_spdesignexe23** | Write | String | spDesign.exe (Device) - Depends on L_AddonManagement (0: False, 1: True) | `0`, `1` | +| **L_winprojexe20** | Write | String | winproj.exe (Device) - Depends on L_AddonManagement (0: False, 1: True) | `0`, `1` | +| **L_grooveexe14** | Write | String | groove.exe (Device) - Depends on L_AddonManagement (0: False, 1: True) | `0`, `1` | +| **L_mspubexe16** | Write | String | mspub.exe (Device) - Depends on L_AddonManagement (0: False, 1: True) | `0`, `1` | +| **L_mse7exe27** | Write | String | mse7.exe (Device) - Depends on L_AddonManagement (0: False, 1: True) | `0`, `1` | +| **L_msaccessexe25** | Write | String | msaccess.exe (Device) - Depends on L_AddonManagement (0: False, 1: True) | `0`, `1` | +| **L_ConsistentMimeHandling** | Write | String | Consistent Mime Handling (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_excelexe43** | Write | String | excel.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True) | `0`, `1` | +| **L_spdesignexe51** | Write | String | spDesign.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True) | `0`, `1` | +| **L_onenoteexe54** | Write | String | onent.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True) | `0`, `1` | +| **L_outlookexe50** | Write | String | outlook.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True) | `0`, `1` | +| **L_pptviewexe46** | Write | String | pptview.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True) | `0`, `1` | +| **L_mspubexe44** | Write | String | mspub.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True) | `0`, `1` | +| **L_visioexe47** | Write | String | visio.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True) | `0`, `1` | +| **L_winprojexe48** | Write | String | winproj.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True) | `0`, `1` | +| **L_msaccessexe53** | Write | String | msaccess.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True) | `0`, `1` | +| **L_powerpntexe45** | Write | String | powerpnt.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True) | `0`, `1` | +| **L_grooveexe42** | Write | String | groove.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True) | `0`, `1` | +| **L_mse7exe55** | Write | String | mse7.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True) | `0`, `1` | +| **L_winwordexe49** | Write | String | winword.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True) | `0`, `1` | +| **L_exprwdexe52** | Write | String | exprwd.exe (Device) - Depends on L_ConsistentMimeHandling (0: False, 1: True) | `0`, `1` | +| **L_Disableusernameandpassword** | Write | String | Disable user name and password (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_excelexe127** | Write | String | excel.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True) | `0`, `1` | +| **L_grooveexe126** | Write | String | groove.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True) | `0`, `1` | +| **L_onenoteexe138** | Write | String | onent.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True) | `0`, `1` | +| **L_mse7exe139** | Write | String | mse7.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True) | `0`, `1` | +| **L_mspubexe128** | Write | String | mspub.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True) | `0`, `1` | +| **L_visioexe131** | Write | String | visio.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True) | `0`, `1` | +| **L_exprwdexe136** | Write | String | exprwd.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True) | `0`, `1` | +| **L_msaccessexe137** | Write | String | msaccess.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True) | `0`, `1` | +| **L_spdesignexe135** | Write | String | spDesign.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True) | `0`, `1` | +| **L_winwordexe133** | Write | String | winword.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True) | `0`, `1` | +| **L_powerpntexe129** | Write | String | powerpnt.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True) | `0`, `1` | +| **L_outlookexe134** | Write | String | outlook.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True) | `0`, `1` | +| **L_winprojexe132** | Write | String | winproj.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True) | `0`, `1` | +| **L_pptviewexe130** | Write | String | pptview.exe (Device) - Depends on L_Disableusernameandpassword (0: False, 1: True) | `0`, `1` | +| **L_Informationbar** | Write | String | Information Bar (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_excelexe113** | Write | String | excel.exe (Device) - Depends on L_Informationbar (0: False, 1: True) | `0`, `1` | +| **L_mspubexe114** | Write | String | mspub.exe (Device) - Depends on L_Informationbar (0: False, 1: True) | `0`, `1` | +| **L_msaccessexe123** | Write | String | msaccess.exe (Device) - Depends on L_Informationbar (0: False, 1: True) | `0`, `1` | +| **L_onenoteexe124** | Write | String | onent.exe (Device) - Depends on L_Informationbar (0: False, 1: True) | `0`, `1` | +| **L_outlookexe120** | Write | String | outlook.exe (Device) - Depends on L_Informationbar (0: False, 1: True) | `0`, `1` | +| **L_winprojexe118** | Write | String | winproj.exe (Device) - Depends on L_Informationbar (0: False, 1: True) | `0`, `1` | +| **L_powerpntexe115** | Write | String | powerpnt.exe (Device) - Depends on L_Informationbar (0: False, 1: True) | `0`, `1` | +| **L_spdesignexe121** | Write | String | spDesign.exe (Device) - Depends on L_Informationbar (0: False, 1: True) | `0`, `1` | +| **L_grooveexe112** | Write | String | groove.exe (Device) - Depends on L_Informationbar (0: False, 1: True) | `0`, `1` | +| **L_visioexe117** | Write | String | visio.exe (Device) - Depends on L_Informationbar (0: False, 1: True) | `0`, `1` | +| **L_mse7exe125** | Write | String | mse7.exe (Device) - Depends on L_Informationbar (0: False, 1: True) | `0`, `1` | +| **L_winwordexe119** | Write | String | winword.exe (Device) - Depends on L_Informationbar (0: False, 1: True) | `0`, `1` | +| **L_exprwdexe122** | Write | String | exprwd.exe (Device) - Depends on L_Informationbar (0: False, 1: True) | `0`, `1` | +| **L_pptviewexe116** | Write | String | pptview.exe (Device) - Depends on L_Informationbar (0: False, 1: True) | `0`, `1` | +| **L_LocalMachineZoneLockdownSecurity** | Write | String | Local Machine Zone Lockdown Security (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_mse7exe41** | Write | String | mse7.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True) | `0`, `1` | +| **L_powerpntexe31** | Write | String | powerpnt.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True) | `0`, `1` | +| **L_mspubexe30** | Write | String | mspub.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True) | `0`, `1` | +| **L_outlookexe36** | Write | String | outlook.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True) | `0`, `1` | +| **L_pptviewexe32** | Write | String | pptview.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True) | `0`, `1` | +| **L_excelexe29** | Write | String | excel.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True) | `0`, `1` | +| **L_exprwdexe38** | Write | String | exprwd.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True) | `0`, `1` | +| **L_grooveexe28** | Write | String | groove.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True) | `0`, `1` | +| **L_winwordexe35** | Write | String | winword.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True) | `0`, `1` | +| **L_msaccessexe39** | Write | String | msaccess.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True) | `0`, `1` | +| **L_spdesignexe37** | Write | String | spDesign.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True) | `0`, `1` | +| **L_visioexe33** | Write | String | visio.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True) | `0`, `1` | +| **L_onenoteexe40** | Write | String | onent.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True) | `0`, `1` | +| **L_winprojexe34** | Write | String | winproj.exe (Device) - Depends on L_LocalMachineZoneLockdownSecurity (0: False, 1: True) | `0`, `1` | +| **L_MimeSniffingSafetyFature** | Write | String | Mime Sniffing Safety Feature (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_powerpntexe59** | Write | String | powerpnt.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True) | `0`, `1` | +| **L_exprwdexe66** | Write | String | exprwd.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True) | `0`, `1` | +| **L_grooveexe56** | Write | String | groove.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True) | `0`, `1` | +| **L_visioexe61** | Write | String | visio.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True) | `0`, `1` | +| **L_outlookexe64** | Write | String | outlook.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True) | `0`, `1` | +| **L_mspubexe58** | Write | String | mspub.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True) | `0`, `1` | +| **L_mse7exe69** | Write | String | mse7.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True) | `0`, `1` | +| **L_msaccessexe67** | Write | String | msaccess.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True) | `0`, `1` | +| **L_pptviewexe60** | Write | String | pptview.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True) | `0`, `1` | +| **L_winprojexe62** | Write | String | winproj.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True) | `0`, `1` | +| **L_spdesignexe65** | Write | String | spDesign.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True) | `0`, `1` | +| **L_onenoteexe68** | Write | String | onent.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True) | `0`, `1` | +| **L_winwordexe63** | Write | String | winword.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True) | `0`, `1` | +| **L_excelexe57** | Write | String | excel.exe (Device) - Depends on L_MimeSniffingSafetyFature (0: False, 1: True) | `0`, `1` | +| **L_NavigateURL** | Write | String | Navigate URL (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_spdesignexe177** | Write | String | spDesign.exe (Device) - Depends on L_NavigateURL (0: False, 1: True) | `0`, `1` | +| **L_onenoteexe180** | Write | String | onent.exe (Device) - Depends on L_NavigateURL (0: False, 1: True) | `0`, `1` | +| **L_pptviewexe172** | Write | String | pptview.exe (Device) - Depends on L_NavigateURL (0: False, 1: True) | `0`, `1` | +| **L_outlookexe176** | Write | String | outlook.exe (Device) - Depends on L_NavigateURL (0: False, 1: True) | `0`, `1` | +| **L_winprojexe174** | Write | String | winproj.exe (Device) - Depends on L_NavigateURL (0: False, 1: True) | `0`, `1` | +| **L_msaccessexe179** | Write | String | msaccess.exe (Device) - Depends on L_NavigateURL (0: False, 1: True) | `0`, `1` | +| **L_winwordexe175** | Write | String | winword.exe (Device) - Depends on L_NavigateURL (0: False, 1: True) | `0`, `1` | +| **L_excelexe169** | Write | String | excel.exe (Device) - Depends on L_NavigateURL (0: False, 1: True) | `0`, `1` | +| **L_mspubexe170** | Write | String | mspub.exe (Device) - Depends on L_NavigateURL (0: False, 1: True) | `0`, `1` | +| **L_exprwdexe178** | Write | String | exprwd.exe (Device) - Depends on L_NavigateURL (0: False, 1: True) | `0`, `1` | +| **L_powerpntexe171** | Write | String | powerpnt.exe (Device) - Depends on L_NavigateURL (0: False, 1: True) | `0`, `1` | +| **L_visioexe173** | Write | String | visio.exe (Device) - Depends on L_NavigateURL (0: False, 1: True) | `0`, `1` | +| **L_mse7exe181** | Write | String | mse7.exe (Device) - Depends on L_NavigateURL (0: False, 1: True) | `0`, `1` | +| **L_grooveexe168** | Write | String | groove.exe (Device) - Depends on L_NavigateURL (0: False, 1: True) | `0`, `1` | +| **L_ObjectCachingProtection** | Write | String | Object Caching Protection (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_winwordexe77** | Write | String | winword.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True) | `0`, `1` | +| **L_powerpntexe73** | Write | String | powerpnt.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True) | `0`, `1` | +| **L_spdesignexe79** | Write | String | spDesign.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True) | `0`, `1` | +| **L_mse7exe83** | Write | String | mse7.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True) | `0`, `1` | +| **L_mspubexe72** | Write | String | mspub.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True) | `0`, `1` | +| **L_msaccessexe81** | Write | String | msaccess.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True) | `0`, `1` | +| **L_onenoteexe82** | Write | String | onent.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True) | `0`, `1` | +| **L_outlookexe78** | Write | String | outlook.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True) | `0`, `1` | +| **L_grooveexe70** | Write | String | groove.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True) | `0`, `1` | +| **L_excelexe71** | Write | String | excel.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True) | `0`, `1` | +| **L_visioexe75** | Write | String | visio.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True) | `0`, `1` | +| **L_pptviewexe74** | Write | String | pptview.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True) | `0`, `1` | +| **L_winprojexe76** | Write | String | winproj.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True) | `0`, `1` | +| **L_exprwdexe80** | Write | String | exprwd.exe (Device) - Depends on L_ObjectCachingProtection (0: False, 1: True) | `0`, `1` | +| **L_ProtectionFromZoneElevation** | Write | String | Protection From Zone Elevation (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_mspubexe100** | Write | String | mspub.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True) | `0`, `1` | +| **L_visioexe103** | Write | String | visio.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True) | `0`, `1` | +| **L_powerpntexe101** | Write | String | powerpnt.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True) | `0`, `1` | +| **L_excelexe99** | Write | String | excel.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True) | `0`, `1` | +| **L_mse7exe111** | Write | String | mse7.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True) | `0`, `1` | +| **L_winwordexe105** | Write | String | winword.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True) | `0`, `1` | +| **L_exprwdexe108** | Write | String | exprwd.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True) | `0`, `1` | +| **L_msaccessexe109** | Write | String | msaccess.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True) | `0`, `1` | +| **L_spdesignexe107** | Write | String | spDesign.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True) | `0`, `1` | +| **L_onenoteexe110** | Write | String | onent.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True) | `0`, `1` | +| **L_pptviewexe102** | Write | String | pptview.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True) | `0`, `1` | +| **L_winprojexe104** | Write | String | winproj.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True) | `0`, `1` | +| **L_grooveexe98** | Write | String | groove.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True) | `0`, `1` | +| **L_outlookexe106** | Write | String | outlook.exe (Device) - Depends on L_ProtectionFromZoneElevation (0: False, 1: True) | `0`, `1` | +| **L_RestrictActiveXInstall** | Write | String | Restrict ActiveX Install (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_mse7exe** | Write | String | mse7.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True) | `0`, `1` | +| **L_powerpntexe** | Write | String | powerpnt.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True) | `0`, `1` | +| **L_spDesignexe** | Write | String | spDesign.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True) | `0`, `1` | +| **L_onenoteexe** | Write | String | onent.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True) | `0`, `1` | +| **L_excelexe** | Write | String | excel.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True) | `0`, `1` | +| **L_mspubexe** | Write | String | mspub.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True) | `0`, `1` | +| **L_visioexe** | Write | String | visio.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True) | `0`, `1` | +| **L_exprwdexe** | Write | String | exprwd.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True) | `0`, `1` | +| **L_outlookexe** | Write | String | outlook.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True) | `0`, `1` | +| **L_pptviewexe** | Write | String | pptview.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True) | `0`, `1` | +| **L_winprojexe** | Write | String | winproj.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True) | `0`, `1` | +| **L_winwordexe** | Write | String | winword.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True) | `0`, `1` | +| **L_grooveexe** | Write | String | groove.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True) | `0`, `1` | +| **L_msaccessexe** | Write | String | msaccess.exe (Device) - Depends on L_RestrictActiveXInstall (0: False, 1: True) | `0`, `1` | +| **L_RestrictFileDownload** | Write | String | Restrict File Download (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_visioexe5** | Write | String | visio.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True) | `0`, `1` | +| **L_winprojexe6** | Write | String | winproj.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True) | `0`, `1` | +| **L_msaccessexe11** | Write | String | msaccess.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True) | `0`, `1` | +| **L_spdesignexe9** | Write | String | spDesign.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True) | `0`, `1` | +| **L_excelexe1** | Write | String | excel.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True) | `0`, `1` | +| **L_powerpntexe3** | Write | String | powerpnt.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True) | `0`, `1` | +| **L_mspubexe2** | Write | String | mspub.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True) | `0`, `1` | +| **L_exprwdexe10** | Write | String | exprwd.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True) | `0`, `1` | +| **L_outlookexe8** | Write | String | outlook.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True) | `0`, `1` | +| **L_pptviewexe4** | Write | String | pptview.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True) | `0`, `1` | +| **L_winwordexe7** | Write | String | winword.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True) | `0`, `1` | +| **L_onenoteexe12** | Write | String | onent.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True) | `0`, `1` | +| **L_mse7exe13** | Write | String | mse7.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True) | `0`, `1` | +| **L_grooveexe0** | Write | String | groove.exe (Device) - Depends on L_RestrictFileDownload (0: False, 1: True) | `0`, `1` | +| **L_SavedfromURL** | Write | String | Saved from URL (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_pptviewexe158** | Write | String | pptview.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True) | `0`, `1` | +| **L_exprwdexe164** | Write | String | exprwd.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True) | `0`, `1` | +| **L_mse7exe167** | Write | String | mse7.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True) | `0`, `1` | +| **L_spdesignexe163** | Write | String | spDesign.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True) | `0`, `1` | +| **L_winprojexe160** | Write | String | winproj.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True) | `0`, `1` | +| **L_mspubexe156** | Write | String | mspub.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True) | `0`, `1` | +| **L_visioexe159** | Write | String | visio.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True) | `0`, `1` | +| **L_winwordexe161** | Write | String | winword.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True) | `0`, `1` | +| **L_msaccessexe165** | Write | String | msaccess.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True) | `0`, `1` | +| **L_onenoteexe166** | Write | String | onent.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True) | `0`, `1` | +| **L_outlookexe162** | Write | String | outlook.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True) | `0`, `1` | +| **L_grooveexe154** | Write | String | groove.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True) | `0`, `1` | +| **L_excelexe155** | Write | String | excel.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True) | `0`, `1` | +| **L_powerpntexe157** | Write | String | powerpnt.exe (Device) - Depends on L_SavedfromURL (0: False, 1: True) | `0`, `1` | +| **L_ScriptedWindowSecurityRestrictions** | Write | String | Scripted Window Security Restrictions (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_exprwdexe94** | Write | String | exprwd.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True) | `0`, `1` | +| **L_mse7exe97** | Write | String | mse7.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True) | `0`, `1` | +| **L_mspubexe86** | Write | String | mspub.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True) | `0`, `1` | +| **L_outlookexe92** | Write | String | outlook.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True) | `0`, `1` | +| **L_msaccessexe95** | Write | String | msaccess.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True) | `0`, `1` | +| **L_powerpntexe87** | Write | String | powerpnt.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True) | `0`, `1` | +| **L_grooveexe84** | Write | String | groove.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True) | `0`, `1` | +| **L_excelexe85** | Write | String | excel.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True) | `0`, `1` | +| **L_pptviewexe88** | Write | String | pptview.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True) | `0`, `1` | +| **L_spdesignexe93** | Write | String | spDesign.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True) | `0`, `1` | +| **L_visioexe89** | Write | String | visio.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True) | `0`, `1` | +| **L_onenoteexe96** | Write | String | onent.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True) | `0`, `1` | +| **L_winprojexe90** | Write | String | winproj.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True) | `0`, `1` | +| **L_winwordexe91** | Write | String | winword.exe (Device) - Depends on L_ScriptedWindowSecurityRestrictions (0: False, 1: True) | `0`, `1` | + +### MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneSecurityBaselineMicrosoft365AppsForEnterprise + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **MicrosoftAccess_Security_TrustCenter_L_BlockMacroExecutionFromInternet** | Write | String | Block macros from running in Office files from the Internet (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftAccess_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned** | Write | String | Disable Trust Bar Notification for unsigned application add-ins and block them (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftAccess_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned** | Write | String | Require that application add-ins are signed by Trusted Publisher (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftAccess_Security_TrustCenterTrustedLocations_L_AllowTrustedLocationsOnTheNetwork** | Write | String | Allow Trusted Locations on the network (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftAccess_Security_TrustCenter_L_VBAWarningsPolicy** | Write | String | VBA Macro Notification Settings (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftAccess_Security_TrustCenter_L_VBAWarningsPolicy_L_Empty** | Write | String | - Depends on MicrosoftAccess_Security_TrustCenter_L_VBAWarningsPolicy (2: Disable all with notification, 3: Disable all except digitally signed macros, 4: Disable all without notification, 1: Enable all macros (not recommended)) | `2`, `3`, `4`, `1` | +| **L_Donotshowdataextractionoptionswhenopeningcorruptworkbooks** | Write | String | Do not show data extraction options when opening corrupt workbooks (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Asktoupdateautomaticlinks** | Write | String | Ask to update automatic links (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_LoadpicturesfromWebpagesnotcreatedinExcel** | Write | String | Load pictures from Web pages not created in Excel (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_DisableAutoRepublish** | Write | String | Disable AutoRepublish (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_DoNotShowAutoRepublishWarningAlert** | Write | String | Do not show AutoRepublish warning alert (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Forcefileextenstionstomatch** | Write | String | Force file extension to match file type (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Forcefileextenstionstomatch_L_Empty** | Write | String | - Depends on L_Forcefileextenstionstomatch (0: Allow different, 1: Allow different, but warn, 2: Always match file type) | `0`, `1`, `2` | +| **L_DeterminewhethertoforceencryptedExcel** | Write | String | Scan encrypted macros in Excel Open XML workbooks (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_DeterminewhethertoforceencryptedExcelDropID** | Write | String | - Depends on L_DeterminewhethertoforceencryptedExcel (0: Scan encrypted macros (default), 1: Scan if anti-virus software available, 2: Load macros without scanning) | `0`, `1`, `2` | +| **L_BlockXLLFromInternet** | Write | String | Block Excel XLL Add-ins that come from an untrusted source (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_BlockXLLFromInternetEnum** | Write | String | - Depends on L_BlockXLLFromInternet (1: Block, 0: Show Additional Warning, 2: Allow) | `1`, `0`, `2` | +| **MicrosoftExcel_Security_TrustCenter_L_BlockMacroExecutionFromInternet** | Write | String | Block macros from running in Office files from the Internet (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftExcel_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned** | Write | String | Disable Trust Bar Notification for unsigned application add-ins and block them (User) (Deprecated) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_EnableBlockUnsecureQueryFiles** | Write | String | Always prevent untrusted Microsoft Query files from opening (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_DBaseIIIANDIVFiles** | Write | String | dBase III / IV files (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_DBaseIIIANDIVFilesDropID** | Write | String | File block setting: (User) - Depends on L_DBaseIIIANDIVFiles (0: Do not block, 2: Open/Save blocked, use open policy) | `0`, `2` | +| **L_DifAndSylkFiles** | Write | String | Dif and Sylk files (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_DifAndSylkFilesDropID** | Write | String | File block setting: (User) - Depends on L_DifAndSylkFiles (0: Do not block, 1: Save blocked, 2: Open/Save blocked, use open policy) | `0`, `1`, `2` | +| **L_Excel2MacrosheetsAndAddInFiles** | Write | String | Excel 2 macrosheets and add-in files (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Excel2MacrosheetsAndAddInFilesDropID** | Write | String | File block setting: (User) - Depends on L_Excel2MacrosheetsAndAddInFiles (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View) | `0`, `2`, `3`, `4`, `5` | +| **L_Excel2Worksheets** | Write | String | Excel 2 worksheets (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Excel2WorksheetsDropID** | Write | String | File block setting: (User) - Depends on L_Excel2Worksheets (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View) | `0`, `2`, `3`, `4`, `5` | +| **L_Excel3MacrosheetsAndAddInFiles** | Write | String | Excel 3 macrosheets and add-in files (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Excel3MacrosheetsAndAddInFilesDropID** | Write | String | File block setting: (User) - Depends on L_Excel3MacrosheetsAndAddInFiles (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View) | `0`, `2`, `3`, `4`, `5` | +| **L_Excel3Worksheets** | Write | String | Excel 3 worksheets (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Excel3WorksheetsDropID** | Write | String | File block setting: (User) - Depends on L_Excel3Worksheets (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View) | `0`, `2`, `3`, `4`, `5` | +| **L_Excel4MacrosheetsAndAddInFiles** | Write | String | Excel 4 macrosheets and add-in files (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Excel4MacrosheetsAndAddInFilesDropID** | Write | String | File block setting: (User) - Depends on L_Excel4MacrosheetsAndAddInFiles (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View) | `0`, `2`, `3`, `4`, `5` | +| **L_Excel4Workbooks** | Write | String | Excel 4 workbooks (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Excel4WorkbooksDropID** | Write | String | File block setting: (User) - Depends on L_Excel4Workbooks (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View) | `0`, `2`, `3`, `4`, `5` | +| **L_Excel4Worksheets** | Write | String | Excel 4 worksheets (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Excel4WorksheetsDropID** | Write | String | File block setting: (User) - Depends on L_Excel4Worksheets (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View) | `0`, `2`, `3`, `4`, `5` | +| **L_Excel95Workbooks** | Write | String | Excel 95 workbooks (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Excel95WorkbooksDropID** | Write | String | File block setting: (User) - Depends on L_Excel95Workbooks (0: Do not block, 1: Save blocked, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View) | `0`, `1`, `2`, `3`, `4`, `5` | +| **L_Excel9597WorkbooksAndTemplates** | Write | String | Excel 95-97 workbooks and templates (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Excel9597WorkbooksAndTemplatesDropID** | Write | String | File block setting: (User) - Depends on L_Excel9597WorkbooksAndTemplates (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View) | `0`, `2`, `3`, `4`, `5` | +| **L_Excel972003WorkbooksAndTemplates** | Write | String | Excel 97-2003 workbooks and templates (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Excel972003WorkbooksAndTemplatesDropID** | Write | String | File block setting: (User) - Depends on L_Excel972003WorkbooksAndTemplates (0: Do not block, 1: Save blocked, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View) | `0`, `1`, `2`, `3`, `4`, `5` | +| **MicrosoftExcel_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehavior** | Write | String | Set default file block behavior (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftExcel_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehaviorDropID** | Write | String | - Depends on MicrosoftExcel_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehavior (0: Blocked files are not opened, 1: Blocked files open in Protected View and can not be edited, 2: Blocked files open in Protected View and can be edited) | `0`, `1`, `2` | +| **L_WebPagesAndExcel2003XMLSpreadsheets** | Write | String | Web pages and Excel 2003 XML spreadsheets (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_WebPagesAndExcel2003XMLSpreadsheetsDropID** | Write | String | File block setting: (User) - Depends on L_WebPagesAndExcel2003XMLSpreadsheets (0: Do not block, 1: Save blocked, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View) | `0`, `1`, `2`, `3`, `4`, `5` | +| **L_XL4KillSwitchPolicy** | Write | String | Prevent Excel from running XLM macros (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_EnableDataBaseFileProtectedView** | Write | String | Always open untrusted database files in Protected View (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftExcel_Security_TrustCenterProtectedView_L_DoNotOpenFilesFromTheInternetZoneInProtectedView** | Write | String | Do not open files from the Internet zone in Protected View (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftExcel_Security_TrustCenterProtectedView_L_DoNotOpenFilesInUnsafeLocationsInProtectedView** | Write | String | Do not open files in unsafe locations in Protected View (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftExcel_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails** | Write | String | Set document behavior if file validation fails (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftExcel_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsStr3** | Write | String | Checked: Allow edit. Unchecked: Do not allow edit. (User) - Depends on MicrosoftExcel_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails (0: False, 1: True) | `0`, `1` | +| **MicrosoftExcel_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsDropID** | Write | String | - Depends on MicrosoftExcel_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails (0: Block files, 1: Open in Protected View) | `0`, `1` | +| **MicrosoftExcel_Security_TrustCenterProtectedView_L_TurnOffProtectedViewForAttachmentsOpenedFromOutlook** | Write | String | Turn off Protected View for attachments opened from Outlook (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftExcel_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned** | Write | String | Require that application add-ins are signed by Trusted Publisher (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftExcel_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2** | Write | String | Disable Trust Bar Notification for unsigned application add-ins and block them (User) - Depends on MicrosoftExcel_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftExcel_Security_TrustCenterTrustedLocations_L_AllowTrustedLocationsOnTheNetwork** | Write | String | Allow Trusted Locations on the network (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftExcel_Security_TrustCenter_L_VBAWarningsPolicy** | Write | String | VBA Macro Notification Settings (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_empty4** | Write | String | - Depends on MicrosoftExcel_Security_TrustCenter_L_VBAWarningsPolicy (2: Disable VBA macros with notification, 3: Disable VBA macros except digitally signed macros, 4: Disable VBA macros without notification, 1: Enable VBA macros (not recommended)) | `2`, `3`, `4`, `1` | +| **MicrosoftExcel_Security_L_TurnOffFileValidation** | Write | String | Turn off file validation (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_WebContentWarningLevel** | Write | String | WEBSERVICE Function Notification Settings (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_WebContentWarningLevelValue** | Write | String | - Depends on L_WebContentWarningLevel (0: Enable all WEBSERVICE functions (not recommended), 1: Disable all with notification, 2: Disable all without notification) | `0`, `1`, `2` | +| **L_NoExtensibilityCustomizationFromDocumentPolicy** | Write | String | Disable UI extending from documents and templates (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_NoExtensibilityCustomizationFromDocumentPolicyWord** | Write | String | Disallow in Word (User) - Depends on L_NoExtensibilityCustomizationFromDocumentPolicy (0: False, 1: True) | `0`, `1` | +| **L_NoExtensibilityCustomizationFromDocumentPolicyExcel** | Write | String | Disallow in Excel (User) - Depends on L_NoExtensibilityCustomizationFromDocumentPolicy (0: False, 1: True) | `0`, `1` | +| **L_NoExtensibilityCustomizationFromDocumentPolicyVisio** | Write | String | Disallow in Visio (User) - Depends on L_NoExtensibilityCustomizationFromDocumentPolicy (0: False, 1: True) | `0`, `1` | +| **L_NoExtensibilityCustomizationFromDocumentPolicyPowerPoint** | Write | String | Disallow in PowerPoint (User) - Depends on L_NoExtensibilityCustomizationFromDocumentPolicy (0: False, 1: True) | `0`, `1` | +| **L_NoExtensibilityCustomizationFromDocumentPolicyPublisher** | Write | String | Disallow in Publisher (User) - Depends on L_NoExtensibilityCustomizationFromDocumentPolicy (0: False, 1: True) | `0`, `1` | +| **L_NoExtensibilityCustomizationFromDocumentPolicyOutlook** | Write | String | Disallow in Outlook (User) - Depends on L_NoExtensibilityCustomizationFromDocumentPolicy (0: False, 1: True) | `0`, `1` | +| **L_NoExtensibilityCustomizationFromDocumentPolicyProject** | Write | String | Disallow in Project (User) - Depends on L_NoExtensibilityCustomizationFromDocumentPolicy (0: False, 1: True) | `0`, `1` | +| **L_NoExtensibilityCustomizationFromDocumentPolicyAccess** | Write | String | Disallow in Access (User) - Depends on L_NoExtensibilityCustomizationFromDocumentPolicy (0: False, 1: True) | `0`, `1` | +| **L_NoExtensibilityCustomizationFromDocumentPolicyInfoPath** | Write | String | Disallow in InfoPath (User) - Depends on L_NoExtensibilityCustomizationFromDocumentPolicy (0: False, 1: True) | `0`, `1` | +| **L_ActiveXControlInitialization** | Write | String | ActiveX Control Initialization (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_ActiveXControlInitializationcolon** | Write | String | ActiveX Control Initialization: (User) - Depends on L_ActiveXControlInitialization (1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6) | `1`, `2`, `3`, `4`, `5`, `6` | +| **L_BasicAuthProxyBehavior** | Write | String | Allow Basic Authentication prompts from network proxies (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_AllowVbaIntranetRefs** | Write | String | Allow VBA to load typelib references by path from untrusted intranet locations (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_AutomationSecurity** | Write | String | Automation Security (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_SettheAutomationSecuritylevel** | Write | String | Set the Automation Security level (User) - Depends on L_AutomationSecurity (3: Disable macros by default, 2: Use application macro security level, 1: Macros enabled (default)) | `3`, `2`, `1` | +| **L_AuthenticationFBABehavior** | Write | String | Control how Office handles form-based sign-in prompts (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_AuthenticationFBAEnabledHostsID** | Write | String | Specify hosts allowed to show form-based sign-in prompts to users: (User) - Depends on L_AuthenticationFBABehavior | | +| **L_authenticationFBABehaviorEnum** | Write | String | Behavior: (User) - Depends on L_AuthenticationFBABehavior (1: Block all prompts, 2: Ask the user what to do for each new host, 3: Show prompts only from allowed hosts) | `1`, `2`, `3` | +| **L_DisableStrictVbaRefsSecurityPolicy** | Write | String | Disable additional security checks on VBA library references that may refer to unsafe locations on the local machine (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_DisableallTrustBarnotificationsfor** | Write | String | Disable all Trust Bar notifications for security issues (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Encryptiontypeforirm** | Write | String | Encryption mode for Information Rights Management (IRM) (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Encryptiontypeforirmcolon** | Write | String | IRM Encryption Mode: (User) - Depends on L_Encryptiontypeforirm (1: Cipher Block Chaining (CBC), 2: Electronic Codebook (ECB)) | `1`, `2` | +| **L_Encryptiontypeforpasswordprotectedoffice972003** | Write | String | Encryption type for password protected Office 97-2003 files (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_encryptiontypecolon318** | Write | String | Encryption type: (User) - Depends on L_Encryptiontypeforpasswordprotectedoffice972003 | | +| **L_Encryptiontypeforpasswordprotectedofficeopen** | Write | String | Encryption type for password protected Office Open XML files (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Encryptiontypecolon** | Write | String | Encryption type: (User) - Depends on L_Encryptiontypeforpasswordprotectedofficeopen | | +| **L_LoadControlsinForms3** | Write | String | Load Controls in Forms3 (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_LoadControlsinForms3colon** | Write | String | Load Controls in Forms3: (User) - Depends on L_LoadControlsinForms3 (1: 1, 2: 2, 3: 3, 4: 4) | `1`, `2`, `3`, `4` | +| **L_MacroRuntimeScanScope** | Write | String | Macro Runtime Scan Scope (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_MacroRuntimeScanScopeEnum** | Write | String | - Depends on L_MacroRuntimeScanScope (0: Disable for all documents, 1: Enable for low trust documents, 2: Enable for all documents) | `0`, `1`, `2` | +| **L_Protectdocumentmetadataforrightsmanaged** | Write | String | Protect document metadata for rights managed Office Open XML Files (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Allowmixofpolicyanduserlocations** | Write | String | Allow mix of policy and user locations (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_DisabletheOfficeclientfrompolling** | Write | String | Disable the Office client from polling the SharePoint Server for published links (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_DisableSmartDocumentsuseofmanifests** | Write | String | Disable Smart Document's use of manifests (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_OutlookSecurityMode** | Write | String | Outlook Security Mode (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_OOMAddressAccess** | Write | String | Configure Outlook object model prompt when reading address information (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_OOMAddressAccess_Setting** | Write | String | Guard behavior: (User) (1: Prompt User, 2: Automatically Approve, 0: Automatically Deny, 3: Prompt user based on computer security) | `1`, `2`, `0`, `3` | +| **L_OOMMeetingTaskRequest** | Write | String | Configure Outlook object model prompt when responding to meeting and task requests (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_OOMMeetingTaskRequest_Setting** | Write | String | Guard behavior: (User) (1: Prompt User, 2: Automatically Approve, 0: Automatically Deny, 3: Prompt user based on computer security) | `1`, `2`, `0`, `3` | +| **L_OOMSend** | Write | String | Configure Outlook object model prompt when sending mail (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_OOMSend_Setting** | Write | String | Guard behavior: (User) (1: Prompt User, 2: Automatically Approve, 0: Automatically Deny, 3: Prompt user based on computer security) | `1`, `2`, `0`, `3` | +| **L_Preventusersfromcustomizingattachmentsecuritysettings** | Write | String | Prevent users from customizing attachment security settings (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_RetrievingCRLsCertificateRevocationLists** | Write | String | Retrieving CRLs (Certificate Revocation Lists) (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_empty31** | Write | String | (0: Use system Default, 1: When online always retreive the CRL, 2: Never retreive the CRL) | `0`, `1`, `2` | +| **L_OOMFormula** | Write | String | Configure Outlook object model prompt When accessing the Formula property of a UserProperty object (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_OOMFormula_Setting** | Write | String | Guard behavior: (User) (1: Prompt User, 2: Automatically Approve, 0: Automatically Deny, 3: Prompt user based on computer security) | `1`, `2`, `0`, `3` | +| **L_AuthenticationwithExchangeServer** | Write | String | Authentication with Exchange Server (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_SelecttheauthenticationwithExchangeserver** | Write | String | Select the authentication with Exchange server. (User) (9: Kerberos/NTLM Password Authentication, 16: Kerberos Password Authentication, 10: NTLM Password Authentication, 2147545088: Insert a smart card) | `9`, `16`, `10`, `2147545088` | +| **L_EnableRPCEncryption** | Write | String | Enable RPC encryption (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Enablelinksinemailmessages** | Write | String | Allow hyperlinks in suspected phishing e-mail messages (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_OOMAddressBook** | Write | String | Configure Outlook object model prompt when accessing an address book (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_OOMAddressBook_Setting** | Write | String | Guard behavior: (User) (1: Prompt User, 2: Automatically Approve, 0: Automatically Deny, 3: Prompt user based on computer security) | `1`, `2`, `0`, `3` | +| **L_OutlookSecurityPolicy** | Write | String | Outlook Security Policy: (User) - Depends on L_OutlookSecurityMode (0: Outlook Default Security, 1: Use Security Form from 'Outlook Security Settings' Public Folder, 2: Use Security Form from 'Outlook 10 Security Settings' Public Folder, 3: Use Outlook Security Group Policy) | `0`, `1`, `2`, `3` | +| **L_AllowUsersToLowerAttachments** | Write | String | Allow users to demote attachments to Level 2 (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_AllowActiveXOneOffForms** | Write | String | Allow Active X One Off Forms (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_empty29** | Write | String | Sets which ActiveX controls to allow. (0: Load only Outlook Controls, 1: Allows only Safe Controls, 2: Allows all ActiveX Controls) | `0`, `1`, `2` | +| **L_EnableScriptsInOneOffForms** | Write | String | Allow scripts in one-off Outlook forms (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Level2RemoveFilePolicy** | Write | String | Remove file extensions blocked as Level 2 (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_removedextensions25** | Write | String | Removed Extensions: (User) | | +| **L_MSGUnicodeformatwhendraggingtofilesystem** | Write | String | Use Unicode format when dragging e-mail message to file system (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_OnExecuteCustomActionOOM** | Write | String | Set Outlook object model custom actions execution prompt (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_OnExecuteCustomActionOOM_Setting** | Write | String | When executing a custom action: (User) (1: Prompt User, 2: Automatically Approve, 0: Automatically Deny, 3: Prompt user based on computer security) | `1`, `2`, `0`, `3` | +| **L_DisableOutlookobjectmodelscriptsforpublicfolders** | Write | String | Do not allow Outlook object model scripts to run for public folders (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_BlockInternet** | Write | String | Include Internet in Safe Zones for Automatic Picture Download (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_SecurityLevelOutlook** | Write | String | Security setting for macros (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_SecurityLevel** | Write | String | Security Level (User) (2: Always warn, 4: Never warn, disable all, 3: Warn for signed, disable unsigned, 1: No security check) | `2`, `4`, `3`, `1` | +| **L_Level1RemoveFilePolicy** | Write | String | Remove file extensions blocked as Level 1 (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_RemovedExtensions** | Write | String | Removed Extensions: (User) | | +| **L_SignatureWarning** | Write | String | Signature Warning (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_signaturewarning30** | Write | String | Signature Warning (User) (0: Let user decide if they want to be warned, 1: Always warn about invalid signatures, 2: Never warn about invalid signatures) | `0`, `1`, `2` | +| **L_Level1Attachments** | Write | String | Display Level 1 attachments (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Minimumencryptionsettings** | Write | String | Minimum encryption settings (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Minimumkeysizeinbits** | Write | SInt32 | Minimum key size (in bits): (User) | | +| **L_DisableOutlookobjectmodelscripts** | Write | String | Do not allow Outlook object model scripts to run for shared folders (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_OOMSaveAs** | Write | String | Configure Outlook object model prompt when executing Save As (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_OOMSaveAs_Setting** | Write | String | Guard behavior: (User) (1: Prompt User, 2: Automatically Approve, 0: Automatically Deny, 3: Prompt user based on computer security) | `1`, `2`, `0`, `3` | +| **L_JunkEmailprotectionlevel** | Write | String | Junk E-mail protection level (User) - Depends on L_OutlookSecurityMode (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Selectlevel** | Write | String | Select level: (User) (4294967295: No Protection, 6: Low (Default), 3: High, 2147483648: Trusted Lists Only) | `4294967295`, `6`, `3`, `2147483648` | +| **L_RunPrograms** | Write | String | Run Programs (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_RunPrograms_L_Empty** | Write | String | - Depends on L_RunPrograms (0: disable (don't run any programs), 1: enable (prompt user before running), 2: enable all (run without prompting)) | `0`, `1`, `2` | +| **L_Determinewhethertoforceencryptedppt** | Write | String | Scan encrypted macros in PowerPoint Open XML presentations (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_DeterminewhethertoforceencryptedpptDropID** | Write | String | - Depends on L_Determinewhethertoforceencryptedppt (0: Scan encrypted macros (default), 1: Scan if anti-virus software available, 2: Load macros without scanning) | `0`, `1`, `2` | +| **MicrosoftPowerPoint_Security_TrustCenter_L_BlockMacroExecutionFromInternet** | Write | String | Block macros from running in Office files from the Internet (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftPowerPoint_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned** | Write | String | Disable Trust Bar Notification for unsigned application add-ins and block them (User) (Deprecated) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_PowerPoint972003PresentationsShowsTemplatesandAddInFiles** | Write | String | PowerPoint 97-2003 presentations, shows, templates and add-in files (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_PowerPoint972003PresentationsShowsTemplatesandAddInFilesDropID** | Write | String | File block setting: (User) - Depends on L_PowerPoint972003PresentationsShowsTemplatesandAddInFiles (0: Do not block, 1: Save blocked, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View) | `0`, `1`, `2`, `3`, `4`, `5` | +| **MicrosoftPowerPoint_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehavior** | Write | String | Set default file block behavior (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftPowerPoint_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehaviorDropID** | Write | String | - Depends on MicrosoftPowerPoint_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehavior (0: Blocked files are not opened, 1: Blocked files open in Protected View and can not be edited, 2: Blocked files open in Protected View and can be edited) | `0`, `1`, `2` | +| **MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_DoNotOpenFilesFromTheInternetZoneInProtectedView** | Write | String | Do not open files from the Internet zone in Protected View (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_DoNotOpenFilesInUnsafeLocationsInProtectedView** | Write | String | Do not open files in unsafe locations in Protected View (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails** | Write | String | Set document behavior if file validation fails (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsStr3** | Write | String | Checked: Allow edit. Unchecked: Do not allow edit. (User) - Depends on MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails (0: False, 1: True) | `0`, `1` | +| **MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsDropID** | Write | String | - Depends on MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails (0: Block files, 1: Open in Protected View) | `0`, `1` | +| **MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_TurnOffProtectedViewForAttachmentsOpenedFromOutlook** | Write | String | Turn off Protected View for attachments opened from Outlook (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftPowerPoint_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned** | Write | String | Require that application add-ins are signed by Trusted Publisher (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftPowerPoint_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2** | Write | String | Disable Trust Bar Notification for unsigned application add-ins and block them (User) - Depends on MicrosoftPowerPoint_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftPowerPoint_Security_TrustCenterTrustedLocations_L_AllowTrustedLocationsOnTheNetwork** | Write | String | Allow Trusted Locations on the network (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftPowerPoint_Security_TrustCenter_L_VBAWarningsPolicy** | Write | String | VBA Macro Notification Settings (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_empty3** | Write | String | - Depends on MicrosoftPowerPoint_Security_TrustCenter_L_VBAWarningsPolicy (2: Disable all with notification, 3: Disable all except digitally signed macros, 4: Disable all without notification, 1: Enable all macros (not recommended)) | `2`, `3`, `4`, `1` | +| **MicrosoftPowerPoint_Security_L_TurnOffFileValidation** | Write | String | Turn off file validation (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftProject_Security_TrustCenter_L_AllowTrustedLocationsOnTheNetwork** | Write | String | Allow Trusted Locations on the network (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftProject_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned** | Write | String | Disable Trust Bar Notification for unsigned application add-ins and block them (User) (Deprecated) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftProject_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned** | Write | String | Require that application add-ins are signed by Trusted Publisher (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftProject_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2** | Write | String | Disable Trust Bar Notification for unsigned application add-ins and block them (User) - Depends on MicrosoftProject_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftProject_Security_TrustCenter_L_VBAWarningsPolicy** | Write | String | VBA Macro Notification Settings (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftProject_Security_TrustCenter_L_VBAWarningsPolicy_L_Empty** | Write | String | - Depends on MicrosoftProject_Security_TrustCenter_L_VBAWarningsPolicy (2: Disable all with notification, 3: Disable all except digitally signed macros, 4: Disable all without notification, 1: Enable all macros (not recommended)) | `2`, `3`, `4`, `1` | +| **L_PublisherAutomationSecurityLevel** | Write | String | Publisher Automation Security Level (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_PublisherAutomationSecurityLevel_L_Empty** | Write | String | - Depends on L_PublisherAutomationSecurityLevel (1: Low (enabled), 2: By UI (prompted), 3: High (disabled)) | `1`, `2`, `3` | +| **MicrosoftPublisherV3_Security_TrustCenter_L_BlockMacroExecutionFromInternet** | Write | String | Block macros from running in Office files from the internet (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftPublisherV2_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned** | Write | String | Disable Trust Bar Notification for unsigned application add-ins (User) (Deprecated) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftPublisherV2_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned** | Write | String | Require that application add-ins are signed by Trusted Publisher (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftPublisherV2_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2** | Write | String | Disable Trust Bar Notification for unsigned application add-ins (User) - Depends on MicrosoftPublisherV2_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftPublisherV2_Security_TrustCenter_L_VBAWarningsPolicy** | Write | String | VBA Macro Notification Settings (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_empty0** | Write | String | - Depends on MicrosoftPublisherV2_Security_TrustCenter_L_VBAWarningsPolicy (2: Disable all with notification, 3: Disable all except digitally signed macros, 4: Disable all without notification, 1: Enable all macros (not recommended)) | `2`, `3`, `4`, `1` | +| **MicrosoftVisio_Security_TrustCenter_L_AllowTrustedLocationsOnTheNetwork** | Write | String | Allow Trusted Locations on the network (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftVisio_Security_TrustCenter_L_BlockMacroExecutionFromInternet** | Write | String | Block macros from running in Office files from the Internet (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftVisio_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned** | Write | String | Disable Trust Bar Notification for unsigned application add-ins and block them (User) (Deprecated) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Visio2000Files** | Write | String | Visio 2000-2002 Binary Drawings, Templates and Stencils (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Visio2000FilesDropID** | Write | String | File block setting: (User) - Depends on L_Visio2000Files (0: Do not block, 2: Open/Save blocked) | `0`, `2` | +| **L_Visio2003Files** | Write | String | Visio 2003-2010 Binary Drawings, Templates and Stencils (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Visio2003FilesDropID** | Write | String | File block setting: (User) - Depends on L_Visio2003Files (0: Do not block, 1: Save blocked, 2: Open/Save blocked) | `0`, `1`, `2` | +| **L_Visio50AndEarlierFiles** | Write | String | Visio 5.0 or earlier Binary Drawings, Templates and Stencils (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Visio50AndEarlierFilesDropID** | Write | String | File block setting: (User) - Depends on L_Visio50AndEarlierFiles (0: Do not block, 2: Open/Save blocked) | `0`, `2` | +| **MicrosoftVisio_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned** | Write | String | Require that application add-ins are signed by Trusted Publisher (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftVisio_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2** | Write | String | Disable Trust Bar Notification for unsigned application add-ins and block them (User) - Depends on MicrosoftVisio_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftVisio_Security_TrustCenter_L_VBAWarningsPolicy** | Write | String | VBA Macro Notification Settings (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftVisio_Security_TrustCenter_L_VBAWarningsPolicy_L_Empty** | Write | String | - Depends on MicrosoftVisio_Security_TrustCenter_L_VBAWarningsPolicy (2: Disable all with notification, 3: Disable all except digitally signed macros, 4: Disable all without notification, 1: Enable all macros (not recommended)) | `2`, `3`, `4`, `1` | +| **MicrosoftWord_Security_TrustCenter_L_BlockMacroExecutionFromInternet** | Write | String | Block macros from running in Office files from the Internet (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftWord_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned** | Write | String | Disable Trust Bar Notification for unsigned application add-ins and block them (User) (Deprecated) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_AllowDDE** | Write | String | Dynamic Data Exchange (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_AllowDDEDropID** | Write | String | Dynamic Data Exchange setting (User) - Depends on L_AllowDDE (1: Limited Dynamic Data Exchange, 2: Allow Dynamic Data Exchange) | `1`, `2` | +| **MicrosoftWord_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehavior** | Write | String | Set default file block behavior (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftWord_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehaviorDropID** | Write | String | - Depends on MicrosoftWord_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehavior (0: Blocked files are not opened, 1: Blocked files open in Protected View and can not be edited, 2: Blocked files open in Protected View and can be edited) | `0`, `1`, `2` | +| **L_Word2AndEarlierBinaryDocumentsAndTemplates** | Write | String | Word 2 and earlier binary documents and templates (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Word2AndEarlierBinaryDocumentsAndTemplatesDropID** | Write | String | File block setting: (User) - Depends on L_Word2AndEarlierBinaryDocumentsAndTemplates (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View) | `0`, `2`, `3`, `4`, `5` | +| **L_Word2000BinaryDocumentsAndTemplates** | Write | String | Word 2000 binary documents and templates (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Word2000BinaryDocumentsAndTemplatesDropID** | Write | String | File block setting: (User) - Depends on L_Word2000BinaryDocumentsAndTemplates (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View) | `0`, `2`, `3`, `4`, `5` | +| **L_Word2003BinaryDocumentsAndTemplates** | Write | String | Word 2003 binary documents and templates (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Word2003BinaryDocumentsAndTemplatesDropID** | Write | String | File block setting: (User) - Depends on L_Word2003BinaryDocumentsAndTemplates (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View) | `0`, `2`, `3`, `4`, `5` | +| **L_Word2007AndLaterBinaryDocumentsAndTemplates** | Write | String | Word 2007 and later binary documents and templates (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Word2007AndLaterBinaryDocumentsAndTemplatesDropID** | Write | String | File block setting: (User) - Depends on L_Word2007AndLaterBinaryDocumentsAndTemplates (0: Do not block, 1: Save blocked, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View) | `0`, `1`, `2`, `3`, `4`, `5` | +| **L_Word6Pt0BinaryDocumentsAndTemplates** | Write | String | Word 6.0 binary documents and templates (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Word6Pt0BinaryDocumentsAndTemplatesDropID** | Write | String | File block setting: (User) - Depends on L_Word6Pt0BinaryDocumentsAndTemplates (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View) | `0`, `2`, `3`, `4`, `5` | +| **L_Word95BinaryDocumentsAndTemplates** | Write | String | Word 95 binary documents and templates (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Word95BinaryDocumentsAndTemplatesDropID** | Write | String | File block setting: (User) - Depends on L_Word95BinaryDocumentsAndTemplates (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View) | `0`, `2`, `3`, `4`, `5` | +| **L_Word97BinaryDocumentsAndTemplates** | Write | String | Word 97 binary documents and templates (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_Word97BinaryDocumentsAndTemplatesDropID** | Write | String | File block setting: (User) - Depends on L_Word97BinaryDocumentsAndTemplates (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View) | `0`, `2`, `3`, `4`, `5` | +| **L_WordXPBinaryDocumentsAndTemplates** | Write | String | Word XP binary documents and templates (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_WordXPBinaryDocumentsAndTemplatesDropID** | Write | String | File block setting: (User) - Depends on L_WordXPBinaryDocumentsAndTemplates (0: Do not block, 2: Open/Save blocked, use open policy, 3: Block, 4: Open in Protected View, 5: Allow editing and open in Protected View) | `0`, `2`, `3`, `4`, `5` | +| **MicrosoftWord_Security_TrustCenterProtectedView_L_DoNotOpenFilesFromTheInternetZoneInProtectedView** | Write | String | Do not open files from the Internet zone in Protected View (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftWord_Security_TrustCenterProtectedView_L_DoNotOpenFilesInUnsafeLocationsInProtectedView** | Write | String | Do not open files in unsafe locations in Protected View (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftWord_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails** | Write | String | Set document behavior if file validation fails (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftWord_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsDropID** | Write | String | - Depends on MicrosoftWord_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails (0: Block files, 1: Open in Protected View) | `0`, `1` | +| **MicrosoftWord_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsStr3** | Write | String | Checked: Allow edit. Unchecked: Do not allow edit. (User) - Depends on MicrosoftWord_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails (0: False, 1: True) | `0`, `1` | +| **MicrosoftWord_Security_TrustCenterProtectedView_L_TurnOffProtectedViewForAttachmentsOpenedFromOutlook** | Write | String | Turn off Protected View for attachments opened from Outlook (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftWord_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned** | Write | String | Require that application add-ins are signed by Trusted Publisher (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftWord_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2** | Write | String | Disable Trust Bar Notification for unsigned application add-ins and block them (User) - Depends on MicrosoftWord_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_DeterminewhethertoforceencryptedWord** | Write | String | Scan encrypted macros in Word Open XML documents (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_DeterminewhethertoforceencryptedWordDropID** | Write | String | - Depends on L_DeterminewhethertoforceencryptedWord (0: Scan encrypted macros (default), 1: Scan if anti-virus software available, 2: Load macros without scanning) | `0`, `1`, `2` | +| **MicrosoftWord_Security_TrustCenter_L_VBAWarningsPolicy** | Write | String | VBA Macro Notification Settings (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **L_empty19** | Write | String | - Depends on MicrosoftWord_Security_TrustCenter_L_VBAWarningsPolicy (2: Disable all with notification, 3: Disable all except digitally signed macros, 4: Disable all without notification, 1: Enable all macros (not recommended)) | `2`, `3`, `4`, `1` | +| **MicrosoftWord_Security_L_TurnOffFileValidation** | Write | String | Turn off file validation (User) (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftWord_Security_TrustCenterTrustedLocations_L_AllowTrustedLocationsOnTheNetwork** | Write | String | Allow Trusted Locations on the network (User) (0: Disabled, 1: Enabled) | `0`, `1` | + + +## Description + +Intune Security Baseline Microsoft365 Apps For Enterprise + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - DeviceManagementConfiguration.Read.All + +- **Update** + + - DeviceManagementConfiguration.ReadWrite.All + +#### Application permissions + +- **Read** + + - DeviceManagementConfiguration.Read.All + +- **Update** + + - DeviceManagementConfiguration.ReadWrite.All + +## Examples + +### Example 1 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneSecurityBaselineMicrosoft365AppsForEnterprise 'mySecurityBaselineMicrosoft365AppsForEnterprisePolicy' + { + DisplayName = 'test' + DeviceSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneSecurityBaselineMicrosoft365AppsForEnterprise + { + L_ProtectionFromZoneElevation = '1' + L_grooveexe98 = '1' + L_excelexe99 = '1' + L_mspubexe100 = '1' + L_powerpntexe101 = '1' + L_pptviewexe102 = '1' + L_visioexe103 = '1' + L_winprojexe104 = '1' + L_winwordexe105 = '1' + L_outlookexe106 = '1' + L_spdesignexe107 = '1' + L_exprwdexe108 = '1' + L_msaccessexe109 = '1' + L_onenoteexe110 = '1' + L_mse7exe111 = '1' + } + UserSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneSecurityBaselineMicrosoft365AppsForEnterprise + { + MicrosoftPublisherV3_Security_TrustCenter_L_BlockMacroExecutionFromInternet = '1' + MicrosoftVisio_Security_TrustCenter_L_VBAWarningsPolicy = '1' + MicrosoftVisio_Security_TrustCenter_L_VBAWarningsPolicy_L_Empty = '3' + } + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} +``` + +### Example 2 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneSecurityBaselineMicrosoft365AppsForEnterprise 'mySecurityBaselineMicrosoft365AppsForEnterprisePolicy' + { + DisplayName = 'test' + DeviceSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneSecurityBaselineMicrosoft365AppsForEnterprise + { + L_ProtectionFromZoneElevation = '1' + L_grooveexe98 = '1' + L_excelexe99 = '1' + L_mspubexe100 = '1' + L_powerpntexe101 = '1' + L_pptviewexe102 = '1' + L_visioexe103 = '1' + L_winprojexe104 = '1' + L_winwordexe105 = '1' + L_outlookexe106 = '1' + L_spdesignexe107 = '1' + L_exprwdexe108 = '1' + L_msaccessexe109 = '1' + L_onenoteexe110 = '1' + L_mse7exe111 = '1' + } + UserSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneSecurityBaselineMicrosoft365AppsForEnterprise + { + MicrosoftPublisherV3_Security_TrustCenter_L_BlockMacroExecutionFromInternet = '1' + MicrosoftVisio_Security_TrustCenter_L_VBAWarningsPolicy = '1' + MicrosoftVisio_Security_TrustCenter_L_VBAWarningsPolicy_L_Empty = '2' # Updated property + } + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} +``` + +### Example 3 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneSecurityBaselineMicrosoft365AppsForEnterprise 'mySecurityBaselineMicrosoft365AppsForEnterprisePolicy' + { + DisplayName = 'test' + Ensure = 'Absent' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} +``` + From 7763a5b24485061a6a1ccc055ed3d65ccb28da2e Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 15 Oct 2024 12:32:28 +0000 Subject: [PATCH 224/252] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/teams/TeamsUpgradePolicy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/resources/teams/TeamsUpgradePolicy.md b/docs/docs/resources/teams/TeamsUpgradePolicy.md index f06cf2599e..e27774070c 100644 --- a/docs/docs/resources/teams/TeamsUpgradePolicy.md +++ b/docs/docs/resources/teams/TeamsUpgradePolicy.md @@ -5,7 +5,7 @@ | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | | **Identity** | Key | String | Identity of the Teams Upgrade Policy. | | -| **Users** | Write | StringArray[] | List of users that will be granted the Upgrade Policy to. | | +| **Users** | Write | StringArray[] | List of users that will be granted the Upgrade Policy to. Use value * to apply the policy globally. | | | **MigrateMeetingsToTeams** | Write | Boolean | Specifies whether to move existing Skype for Business meetings organized by the user to Teams. This parameter can only be true if the mode of the specified policy instance is either TeamsOnly or SfBWithTeamsCollabAndMeetings, and if the policy instance is being granted to a specific user. It not possible to trigger meeting migration when granting TeamsUpgradePolicy to the entire tenant. | | | **Credential** | Write | PSCredential | Credentials of the Teams Admin | | | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | From 252740163f061afef8d622051b7c47102e921dd4 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 15 Oct 2024 12:32:50 +0000 Subject: [PATCH 225/252] Updated {Create} AAD Integration Tests --- .../M365DSCIntegration.AAD.Create.Tests.ps1 | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 index 828bde930b..d0e9424d6f 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 @@ -360,6 +360,47 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + AADIdentityGovernanceLifecycleWorkflow 'AADIdentityGovernanceLifecycleWorkflow-Onboard pre-hire employee updated version' + { + Category = "joiner"; + Description = "Description the onboard of prehire employee"; + DisplayName = "Onboard pre-hire employee updated version"; + Ensure = "Present"; + ExecutionConditions = MSFT_IdentityGovernanceWorkflowExecutionConditions { + ScopeValue = MSFT_IdentityGovernanceScope { + Rule = '(not (country eq ''Brazil''))' + ODataType = '#microsoft.graph.identityGovernance.ruleBasedSubjectSet' + } + TriggerValue = MSFT_IdentityGovernanceTrigger { + OffsetInDays = 4 + TimeBasedAttribute = 'employeeHireDate' + ODataType = '#microsoft.graph.identityGovernance.timeBasedAttributeTrigger' + } + ODataType = '#microsoft.graph.identityGovernance.triggerAndScopeBasedConditions' + }; + IsEnabled = $True; + IsSchedulingEnabled = $False; + Tasks = @( + MSFT_AADIdentityGovernanceTask { + DisplayName = 'Add user to groups' + Description = 'Add user to selected groups' + Category = 'joiner,leaver,mover' + IsEnabled = $True + ExecutionSequence = 1 + ContinueOnError = $True + TaskDefinitionId = '22085229-5809-45e8-97fd-270d28d66910' + Arguments = @( + MSFT_AADIdentityGovernanceTaskArguments { + Name = 'groupID' + Value = '7ad01e00-8c3a-42a6-baaf-39f2390b2565' + } + ) + } + ); + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } AADNamedLocationPolicy 'CompanyNetwork' { DisplayName = "Company Network" From a183ffab04f425bb0c70eb0b012cd3e3ad568006 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 15 Oct 2024 12:33:11 +0000 Subject: [PATCH 226/252] Updated {Update} AAD Integration Tests --- .../M365DSCIntegration.AAD.Update.Tests.ps1 | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 index 38a257dddf..cce664e8ec 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 @@ -861,6 +861,50 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + AADIdentityGovernanceLifecycleWorkflow 'AADIdentityGovernanceLifecycleWorkflow-Onboard pre-hire employee updated version' + { + Category = "joiner"; + #updated description + Description = "Updated description the onboard of prehire employee"; + DisplayName = "Onboard pre-hire employee updated version"; + Ensure = "Present"; + ExecutionConditions = MSFT_IdentityGovernanceWorkflowExecutionConditions { + ScopeValue = MSFT_IdentityGovernanceScope { + #updated rule + Rule = '(not (country eq ''America''))' + ODataType = '#microsoft.graph.identityGovernance.ruleBasedSubjectSet' + } + TriggerValue = MSFT_IdentityGovernanceTrigger { + OffsetInDays = 4 + TimeBasedAttribute = 'employeeHireDate' + ODataType = '#microsoft.graph.identityGovernance.timeBasedAttributeTrigger' + } + ODataType = '#microsoft.graph.identityGovernance.triggerAndScopeBasedConditions' + }; + IsEnabled = $True; + IsSchedulingEnabled = $False; + Tasks = @( + MSFT_AADIdentityGovernanceTask { + DisplayName = 'Add user to groups' + #updated description + Description = 'Add user to selected groups updated' + Category = 'joiner,leaver,mover' + IsEnabled = $True + ExecutionSequence = 1 + ContinueOnError = $True + TaskDefinitionId = '22085229-5809-45e8-97fd-270d28d66910' + Arguments = @( + MSFT_AADIdentityGovernanceTaskArguments { + Name = 'groupID' + Value = '7ad01e00-8c3a-42a6-baaf-39f2390b2565' + } + ) + } + ); + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } AADLifecycleWorkflowSettings 'AADLifecycleWorkflowSettings' { ApplicationId = $ApplicationId; From 715e2b70a6b2377d105cbf32f4983a34d0522fc9 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 15 Oct 2024 12:33:27 +0000 Subject: [PATCH 227/252] Updated {Update} AAD Integration Tests --- .../M365DSCIntegration.AAD.Remove.Tests.ps1 | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 index c7f705b234..86e91dc321 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 @@ -285,6 +285,47 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + AADIdentityGovernanceLifecycleWorkflow 'AADIdentityGovernanceLifecycleWorkflow-Onboard pre-hire employee updated version' + { + Category = "joiner"; + Description = "Updated description the onboard of prehire employee"; + DisplayName = "Onboard pre-hire employee updated version"; + Ensure = "Absent"; + ExecutionConditions = MSFT_IdentityGovernanceWorkflowExecutionConditions { + ScopeValue = MSFT_IdentityGovernanceScope { + Rule = '(not (country eq ''America''))' + ODataType = '#microsoft.graph.identityGovernance.ruleBasedSubjectSet' + } + TriggerValue = MSFT_IdentityGovernanceTrigger { + OffsetInDays = 4 + TimeBasedAttribute = 'employeeHireDate' + ODataType = '#microsoft.graph.identityGovernance.timeBasedAttributeTrigger' + } + ODataType = '#microsoft.graph.identityGovernance.triggerAndScopeBasedConditions' + }; + IsEnabled = $True; + IsSchedulingEnabled = $False; + Tasks = @( + MSFT_AADIdentityGovernanceTask { + DisplayName = 'Add user to groups' + Description = 'Add user to selected groups updated' + Category = 'joiner,leaver,mover' + IsEnabled = $True + ExecutionSequence = 1 + ContinueOnError = $True + TaskDefinitionId = '22085229-5809-45e8-97fd-270d28d66910' + Arguments = @( + MSFT_AADIdentityGovernanceTaskArguments { + Name = 'groupID' + Value = '7ad01e00-8c3a-42a6-baaf-39f2390b2565' + } + ) + } + ); + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } AADNamedLocationPolicy 'CompanyNetwork' { DisplayName = "Company Network" From a722138f7f69370e86c600cf913ec23c20adf76d Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 15 Oct 2024 12:33:50 +0000 Subject: [PATCH 228/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 2283 ++++++++++++++++- 1 file changed, 2279 insertions(+), 4 deletions(-) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index b405f20354..0140e55ccc 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -19790,7 +19790,7 @@ ] }, { - "ClassName": "MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings", + "ClassName": "MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneAccountProtectionPolicyWindows10", "Parameters": [ { "CIMType": "String", @@ -19860,7 +19860,7 @@ ] }, { - "ClassName": "MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings", + "ClassName": "MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneAccountProtectionPolicyWindows10", "Parameters": [ { "CIMType": "String", @@ -19938,12 +19938,12 @@ "Option": "Write" }, { - "CIMType": "MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings", + "CIMType": "MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneAccountProtectionPolicyWindows10", "Name": "DeviceSettings", "Option": "Write" }, { - "CIMType": "MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings", + "CIMType": "MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneAccountProtectionPolicyWindows10", "Name": "UserSettings", "Option": "Write" }, @@ -36339,6 +36339,2281 @@ } ] }, + { + "ClassName": "MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneSecurityBaselineMicrosoft365AppsForEnterprise", + "Parameters": [ + { + "CIMType": "String", + "Name": "Pol_SecGuide_A001_Block_Flash", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Pol_SecGuide_Block_Flash", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Pol_SecGuide_Legacy_JScript", + "Option": "Write" + }, + { + "CIMType": "SInt32", + "Name": "POL_SG_powerpnt", + "Option": "Write" + }, + { + "CIMType": "SInt32", + "Name": "POL_SG_onenote", + "Option": "Write" + }, + { + "CIMType": "SInt32", + "Name": "POL_SG_mspub", + "Option": "Write" + }, + { + "CIMType": "SInt32", + "Name": "POL_SG_msaccess", + "Option": "Write" + }, + { + "CIMType": "SInt32", + "Name": "POL_SG_winproj", + "Option": "Write" + }, + { + "CIMType": "SInt32", + "Name": "POL_SG_visio", + "Option": "Write" + }, + { + "CIMType": "SInt32", + "Name": "POL_SG_outlook", + "Option": "Write" + }, + { + "CIMType": "SInt32", + "Name": "POL_SG_winword", + "Option": "Write" + }, + { + "CIMType": "SInt32", + "Name": "POL_SG_excel", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_PolicyEnableSIPHighSecurityMode", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_PolicyDisableHttpConnect", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_AddonManagement", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_powerpntexe17", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_excelexe15", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_visioexe19", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_onenoteexe26", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_outlookexe22", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_pptviewexe18", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winwordexe21", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_exprwdexe24", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_spdesignexe23", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winprojexe20", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_grooveexe14", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mspubexe16", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mse7exe27", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_msaccessexe25", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_ConsistentMimeHandling", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_excelexe43", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_spdesignexe51", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_onenoteexe54", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_outlookexe50", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_pptviewexe46", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mspubexe44", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_visioexe47", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winprojexe48", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_msaccessexe53", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_powerpntexe45", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_grooveexe42", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mse7exe55", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winwordexe49", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_exprwdexe52", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Disableusernameandpassword", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_excelexe127", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_grooveexe126", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_onenoteexe138", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mse7exe139", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mspubexe128", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_visioexe131", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_exprwdexe136", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_msaccessexe137", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_spdesignexe135", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winwordexe133", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_powerpntexe129", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_outlookexe134", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winprojexe132", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_pptviewexe130", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Informationbar", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_excelexe113", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mspubexe114", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_msaccessexe123", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_onenoteexe124", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_outlookexe120", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winprojexe118", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_powerpntexe115", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_spdesignexe121", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_grooveexe112", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_visioexe117", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mse7exe125", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winwordexe119", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_exprwdexe122", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_pptviewexe116", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_LocalMachineZoneLockdownSecurity", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mse7exe41", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_powerpntexe31", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mspubexe30", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_outlookexe36", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_pptviewexe32", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_excelexe29", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_exprwdexe38", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_grooveexe28", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winwordexe35", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_msaccessexe39", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_spdesignexe37", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_visioexe33", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_onenoteexe40", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winprojexe34", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_MimeSniffingSafetyFature", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_powerpntexe59", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_exprwdexe66", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_grooveexe56", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_visioexe61", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_outlookexe64", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mspubexe58", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mse7exe69", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_msaccessexe67", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_pptviewexe60", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winprojexe62", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_spdesignexe65", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_onenoteexe68", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winwordexe63", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_excelexe57", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_NavigateURL", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_spdesignexe177", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_onenoteexe180", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_pptviewexe172", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_outlookexe176", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winprojexe174", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_msaccessexe179", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winwordexe175", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_excelexe169", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mspubexe170", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_exprwdexe178", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_powerpntexe171", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_visioexe173", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mse7exe181", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_grooveexe168", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_ObjectCachingProtection", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winwordexe77", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_powerpntexe73", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_spdesignexe79", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mse7exe83", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mspubexe72", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_msaccessexe81", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_onenoteexe82", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_outlookexe78", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_grooveexe70", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_excelexe71", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_visioexe75", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_pptviewexe74", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winprojexe76", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_exprwdexe80", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_ProtectionFromZoneElevation", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mspubexe100", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_visioexe103", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_powerpntexe101", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_excelexe99", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mse7exe111", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winwordexe105", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_exprwdexe108", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_msaccessexe109", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_spdesignexe107", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_onenoteexe110", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_pptviewexe102", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winprojexe104", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_grooveexe98", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_outlookexe106", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_RestrictActiveXInstall", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mse7exe", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_powerpntexe", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_spDesignexe", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_onenoteexe", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_excelexe", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mspubexe", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_visioexe", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_exprwdexe", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_outlookexe", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_pptviewexe", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winprojexe", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winwordexe", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_grooveexe", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_msaccessexe", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_RestrictFileDownload", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_visioexe5", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winprojexe6", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_msaccessexe11", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_spdesignexe9", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_excelexe1", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_powerpntexe3", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mspubexe2", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_exprwdexe10", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_outlookexe8", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_pptviewexe4", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winwordexe7", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_onenoteexe12", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mse7exe13", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_grooveexe0", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_SavedfromURL", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_pptviewexe158", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_exprwdexe164", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mse7exe167", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_spdesignexe163", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winprojexe160", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mspubexe156", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_visioexe159", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winwordexe161", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_msaccessexe165", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_onenoteexe166", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_outlookexe162", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_grooveexe154", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_excelexe155", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_powerpntexe157", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_ScriptedWindowSecurityRestrictions", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_exprwdexe94", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mse7exe97", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_mspubexe86", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_outlookexe92", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_msaccessexe95", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_powerpntexe87", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_grooveexe84", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_excelexe85", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_pptviewexe88", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_spdesignexe93", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_visioexe89", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_onenoteexe96", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winprojexe90", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_winwordexe91", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneSecurityBaselineMicrosoft365AppsForEnterprise", + "Parameters": [ + { + "CIMType": "String", + "Name": "MicrosoftAccess_Security_TrustCenter_L_BlockMacroExecutionFromInternet", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftAccess_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftAccess_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftAccess_Security_TrustCenterTrustedLocations_L_AllowTrustedLocationsOnTheNetwork", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftAccess_Security_TrustCenter_L_VBAWarningsPolicy", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftAccess_Security_TrustCenter_L_VBAWarningsPolicy_L_Empty", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Donotshowdataextractionoptionswhenopeningcorruptworkbooks", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Asktoupdateautomaticlinks", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_LoadpicturesfromWebpagesnotcreatedinExcel", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_DisableAutoRepublish", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_DoNotShowAutoRepublishWarningAlert", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Forcefileextenstionstomatch", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Forcefileextenstionstomatch_L_Empty", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_DeterminewhethertoforceencryptedExcel", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_DeterminewhethertoforceencryptedExcelDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_BlockXLLFromInternet", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_BlockXLLFromInternetEnum", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftExcel_Security_TrustCenter_L_BlockMacroExecutionFromInternet", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftExcel_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_EnableBlockUnsecureQueryFiles", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_DBaseIIIANDIVFiles", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_DBaseIIIANDIVFilesDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_DifAndSylkFiles", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_DifAndSylkFilesDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Excel2MacrosheetsAndAddInFiles", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Excel2MacrosheetsAndAddInFilesDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Excel2Worksheets", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Excel2WorksheetsDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Excel3MacrosheetsAndAddInFiles", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Excel3MacrosheetsAndAddInFilesDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Excel3Worksheets", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Excel3WorksheetsDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Excel4MacrosheetsAndAddInFiles", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Excel4MacrosheetsAndAddInFilesDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Excel4Workbooks", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Excel4WorkbooksDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Excel4Worksheets", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Excel4WorksheetsDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Excel95Workbooks", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Excel95WorkbooksDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Excel9597WorkbooksAndTemplates", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Excel9597WorkbooksAndTemplatesDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Excel972003WorkbooksAndTemplates", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Excel972003WorkbooksAndTemplatesDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftExcel_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehavior", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftExcel_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehaviorDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_WebPagesAndExcel2003XMLSpreadsheets", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_WebPagesAndExcel2003XMLSpreadsheetsDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_XL4KillSwitchPolicy", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_EnableDataBaseFileProtectedView", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftExcel_Security_TrustCenterProtectedView_L_DoNotOpenFilesFromTheInternetZoneInProtectedView", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftExcel_Security_TrustCenterProtectedView_L_DoNotOpenFilesInUnsafeLocationsInProtectedView", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftExcel_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftExcel_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsStr3", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftExcel_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftExcel_Security_TrustCenterProtectedView_L_TurnOffProtectedViewForAttachmentsOpenedFromOutlook", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftExcel_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftExcel_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftExcel_Security_TrustCenterTrustedLocations_L_AllowTrustedLocationsOnTheNetwork", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftExcel_Security_TrustCenter_L_VBAWarningsPolicy", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_empty4", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftExcel_Security_L_TurnOffFileValidation", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_WebContentWarningLevel", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_WebContentWarningLevelValue", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_NoExtensibilityCustomizationFromDocumentPolicy", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_NoExtensibilityCustomizationFromDocumentPolicyWord", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_NoExtensibilityCustomizationFromDocumentPolicyExcel", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_NoExtensibilityCustomizationFromDocumentPolicyVisio", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_NoExtensibilityCustomizationFromDocumentPolicyPowerPoint", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_NoExtensibilityCustomizationFromDocumentPolicyPublisher", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_NoExtensibilityCustomizationFromDocumentPolicyOutlook", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_NoExtensibilityCustomizationFromDocumentPolicyProject", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_NoExtensibilityCustomizationFromDocumentPolicyAccess", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_NoExtensibilityCustomizationFromDocumentPolicyInfoPath", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_ActiveXControlInitialization", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_ActiveXControlInitializationcolon", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_BasicAuthProxyBehavior", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_AllowVbaIntranetRefs", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_AutomationSecurity", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_SettheAutomationSecuritylevel", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_AuthenticationFBABehavior", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_AuthenticationFBAEnabledHostsID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_authenticationFBABehaviorEnum", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_DisableStrictVbaRefsSecurityPolicy", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_DisableallTrustBarnotificationsfor", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Encryptiontypeforirm", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Encryptiontypeforirmcolon", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Encryptiontypeforpasswordprotectedoffice972003", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_encryptiontypecolon318", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Encryptiontypeforpasswordprotectedofficeopen", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Encryptiontypecolon", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_LoadControlsinForms3", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_LoadControlsinForms3colon", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_MacroRuntimeScanScope", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_MacroRuntimeScanScopeEnum", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Protectdocumentmetadataforrightsmanaged", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Allowmixofpolicyanduserlocations", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_DisabletheOfficeclientfrompolling", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_DisableSmartDocumentsuseofmanifests", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_OutlookSecurityMode", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_OOMAddressAccess", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_OOMAddressAccess_Setting", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_OOMMeetingTaskRequest", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_OOMMeetingTaskRequest_Setting", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_OOMSend", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_OOMSend_Setting", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Preventusersfromcustomizingattachmentsecuritysettings", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_RetrievingCRLsCertificateRevocationLists", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_empty31", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_OOMFormula", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_OOMFormula_Setting", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_AuthenticationwithExchangeServer", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_SelecttheauthenticationwithExchangeserver", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_EnableRPCEncryption", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Enablelinksinemailmessages", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_OOMAddressBook", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_OOMAddressBook_Setting", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_OutlookSecurityPolicy", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_AllowUsersToLowerAttachments", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_AllowActiveXOneOffForms", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_empty29", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_EnableScriptsInOneOffForms", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Level2RemoveFilePolicy", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_removedextensions25", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_MSGUnicodeformatwhendraggingtofilesystem", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_OnExecuteCustomActionOOM", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_OnExecuteCustomActionOOM_Setting", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_DisableOutlookobjectmodelscriptsforpublicfolders", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_BlockInternet", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_SecurityLevelOutlook", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_SecurityLevel", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Level1RemoveFilePolicy", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_RemovedExtensions", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_SignatureWarning", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_signaturewarning30", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Level1Attachments", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Minimumencryptionsettings", + "Option": "Write" + }, + { + "CIMType": "SInt32", + "Name": "L_Minimumkeysizeinbits", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_DisableOutlookobjectmodelscripts", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_OOMSaveAs", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_OOMSaveAs_Setting", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_JunkEmailprotectionlevel", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Selectlevel", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_RunPrograms", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_RunPrograms_L_Empty", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Determinewhethertoforceencryptedppt", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_DeterminewhethertoforceencryptedpptDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftPowerPoint_Security_TrustCenter_L_BlockMacroExecutionFromInternet", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftPowerPoint_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_PowerPoint972003PresentationsShowsTemplatesandAddInFiles", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_PowerPoint972003PresentationsShowsTemplatesandAddInFilesDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftPowerPoint_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehavior", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftPowerPoint_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehaviorDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_DoNotOpenFilesFromTheInternetZoneInProtectedView", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_DoNotOpenFilesInUnsafeLocationsInProtectedView", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsStr3", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftPowerPoint_Security_TrustCenterProtectedView_L_TurnOffProtectedViewForAttachmentsOpenedFromOutlook", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftPowerPoint_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftPowerPoint_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftPowerPoint_Security_TrustCenterTrustedLocations_L_AllowTrustedLocationsOnTheNetwork", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftPowerPoint_Security_TrustCenter_L_VBAWarningsPolicy", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_empty3", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftPowerPoint_Security_L_TurnOffFileValidation", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftProject_Security_TrustCenter_L_AllowTrustedLocationsOnTheNetwork", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftProject_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftProject_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftProject_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftProject_Security_TrustCenter_L_VBAWarningsPolicy", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftProject_Security_TrustCenter_L_VBAWarningsPolicy_L_Empty", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_PublisherAutomationSecurityLevel", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_PublisherAutomationSecurityLevel_L_Empty", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftPublisherV3_Security_TrustCenter_L_BlockMacroExecutionFromInternet", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftPublisherV2_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftPublisherV2_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftPublisherV2_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftPublisherV2_Security_TrustCenter_L_VBAWarningsPolicy", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_empty0", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftVisio_Security_TrustCenter_L_AllowTrustedLocationsOnTheNetwork", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftVisio_Security_TrustCenter_L_BlockMacroExecutionFromInternet", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftVisio_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Visio2000Files", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Visio2000FilesDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Visio2003Files", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Visio2003FilesDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Visio50AndEarlierFiles", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Visio50AndEarlierFilesDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftVisio_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftVisio_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftVisio_Security_TrustCenter_L_VBAWarningsPolicy", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftVisio_Security_TrustCenter_L_VBAWarningsPolicy_L_Empty", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftWord_Security_TrustCenter_L_BlockMacroExecutionFromInternet", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftWord_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_AllowDDE", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_AllowDDEDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftWord_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehavior", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftWord_Security_TrustCenterFileBlockSettings_L_SetDefaultFileBlockBehaviorDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Word2AndEarlierBinaryDocumentsAndTemplates", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Word2AndEarlierBinaryDocumentsAndTemplatesDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Word2000BinaryDocumentsAndTemplates", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Word2000BinaryDocumentsAndTemplatesDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Word2003BinaryDocumentsAndTemplates", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Word2003BinaryDocumentsAndTemplatesDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Word2007AndLaterBinaryDocumentsAndTemplates", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Word2007AndLaterBinaryDocumentsAndTemplatesDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Word6Pt0BinaryDocumentsAndTemplates", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Word6Pt0BinaryDocumentsAndTemplatesDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Word95BinaryDocumentsAndTemplates", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Word95BinaryDocumentsAndTemplatesDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Word97BinaryDocumentsAndTemplates", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_Word97BinaryDocumentsAndTemplatesDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_WordXPBinaryDocumentsAndTemplates", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_WordXPBinaryDocumentsAndTemplatesDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftWord_Security_TrustCenterProtectedView_L_DoNotOpenFilesFromTheInternetZoneInProtectedView", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftWord_Security_TrustCenterProtectedView_L_DoNotOpenFilesInUnsafeLocationsInProtectedView", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftWord_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFails", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftWord_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftWord_Security_TrustCenterProtectedView_L_SetDocumentBehaviorIfFileValidationFailsStr3", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftWord_Security_TrustCenterProtectedView_L_TurnOffProtectedViewForAttachmentsOpenedFromOutlook", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftWord_Security_TrustCenter_L_RequirethatApplicationExtensionsaresigned", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftWord_Security_TrustCenter_L_DisableTrustBarNotificationforunsigned_v2", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_DeterminewhethertoforceencryptedWord", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_DeterminewhethertoforceencryptedWordDropID", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftWord_Security_TrustCenter_L_VBAWarningsPolicy", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "L_empty19", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftWord_Security_L_TurnOffFileValidation", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftWord_Security_TrustCenterTrustedLocations_L_AllowTrustedLocationsOnTheNetwork", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_IntuneSecurityBaselineMicrosoft365AppsForEnterprise", + "Parameters": [ + { + "CIMType": "String", + "Name": "Description", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Key" + }, + { + "CIMType": "String[]", + "Name": "RoleScopeTagIds", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Id", + "Option": "Write" + }, + { + "CIMType": "MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneSecurityBaselineMicrosoft365AppsForEnterprise", + "Name": "DeviceSettings", + "Option": "Write" + }, + { + "CIMType": "MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneSecurityBaselineMicrosoft365AppsForEnterprise", + "Name": "UserSettings", + "Option": "Write" + }, + { + "CIMType": "MSFT_DeviceManagementConfigurationPolicyAssignments[]", + "Name": "Assignments", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "ApplicationSecret", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_IntuneSettingCatalogASRRulesPolicyWindows10", "Parameters": [ From 43ce1606c145080eb4277044950f7fa13f4def3c Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 15 Oct 2024 12:34:37 +0000 Subject: [PATCH 229/252] Updated {Create} Intune Integration Tests --- ...M365DSCIntegration.INTUNE.Create.Tests.ps1 | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 index dadb7d572a..c8d9f4947c 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 @@ -91,12 +91,12 @@ IntuneAccountProtectionPolicyWindows10 'myAccountProtectionPolicy' { DisplayName = 'test' - DeviceSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings + DeviceSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneAccountProtectionPolicyWindows10 { History = 10 EnablePinRecovery = 'true' } - UserSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings + UserSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneAccountProtectionPolicyWindows10 { History = 20 EnablePinRecovery = 'true' @@ -2631,6 +2631,38 @@ TenantId = $TenantId; CertificateThumbprint = $CertificateThumbprint; } + IntuneSecurityBaselineMicrosoft365AppsForEnterprise 'mySecurityBaselineMicrosoft365AppsForEnterprisePolicy' + { + DisplayName = 'test' + DeviceSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogDeviceSettings_IntuneSecurityBaselineMicrosoft365AppsForEnterprise + { + L_ProtectionFromZoneElevation = '1' + L_grooveexe98 = '1' + L_excelexe99 = '1' + L_mspubexe100 = '1' + L_powerpntexe101 = '1' + L_pptviewexe102 = '1' + L_visioexe103 = '1' + L_winprojexe104 = '1' + L_winwordexe105 = '1' + L_outlookexe106 = '1' + L_spdesignexe107 = '1' + L_exprwdexe108 = '1' + L_msaccessexe109 = '1' + L_onenoteexe110 = '1' + L_mse7exe111 = '1' + } + UserSettings = MSFT_MicrosoftGraphIntuneSettingsCatalogUserSettings_IntuneSecurityBaselineMicrosoft365AppsForEnterprise + { + MicrosoftPublisherV3_Security_TrustCenter_L_BlockMacroExecutionFromInternet = '1' + MicrosoftVisio_Security_TrustCenter_L_VBAWarningsPolicy = '1' + MicrosoftVisio_Security_TrustCenter_L_VBAWarningsPolicy_L_Empty = '3' + } + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } IntuneSettingCatalogASRRulesPolicyWindows10 'myASRRulesPolicy' { DisplayName = 'asr 2' From 5cfb6ea215cd3c1436346fb95043dcd6921bac60 Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Tue, 15 Oct 2024 09:16:54 -0700 Subject: [PATCH 230/252] add authentication params in examples --- .../IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 | 3 +++ .../IntuneMobileAppsWindowsOfficeSuiteApp/2-Update.ps1 | 3 +++ .../IntuneMobileAppsWindowsOfficeSuiteApp/3-Remove.ps1 | 3 +++ 3 files changed, 9 insertions(+) diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 index 0ae915356e..1eb9c2d9fb 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/1-Create.ps1 @@ -46,6 +46,9 @@ Configuration Example Id = '8e683524-4ec1-4813-bb3e-6256b2f293d8' DisplayName = 'Productivity' }); + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/2-Update.ps1 index 0ae915356e..1eb9c2d9fb 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/2-Update.ps1 @@ -46,6 +46,9 @@ Configuration Example Id = '8e683524-4ec1-4813-bb3e-6256b2f293d8' DisplayName = 'Productivity' }); + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/3-Remove.ps1 index da1bb82e9b..8b731ff4ac 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsWindowsOfficeSuiteApp/3-Remove.ps1 @@ -27,6 +27,9 @@ Configuration Example Id = "8e683524-4ec1-4813-bb3e-6256b2f293d8"; DisplayName = "Microsoft 365 Apps for Windows 10 and later"; Ensure = "Absent"; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint } } } From 9d17e08dabae8668cbb193f846c2771b10422768 Mon Sep 17 00:00:00 2001 From: "Katherine Hsu (from Dev Box)" Date: Tue, 15 Oct 2024 09:19:18 -0700 Subject: [PATCH 231/252] add update to changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b6d19afb3..f96a9674c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,8 @@ * Migrate to new Settings Catalog cmdlets. * IntuneMobileAppsMacOSLobApp * Initial release +* IntuneMobileAppsWindowsOfficeSuiteApp + * Initial release * PPAdminDLPPolicy * Initial release. * PPDLPPolicyConnectorConfigurations From 7e40b52454a241a6ff92e6cb6405fc58a9d51a0d Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Wed, 16 Oct 2024 08:35:10 +0200 Subject: [PATCH 232/252] Add Intune Security Baseline for Microsoft Edge --- CHANGELOG.md | 2 + ...T_IntuneSecurityBaselineMicrosoftEdge.psm1 | 904 ++++++++++++++++++ ...neSecurityBaselineMicrosoftEdge.schema.mof | 50 + .../readme.md | 6 + .../settings.json | 33 + .../1-Create.ps1 | 38 + .../2-Update.ps1 | 38 + .../3-Remove.ps1 | 34 + .../Modules/M365DSCDRGUtil.psm1 | 4 + .../M365DSCResourceGenerator.psm1 | 2 + ...uneSecurityBaselineMicrosoftEdge.Tests.ps1 | 359 +++++++ 11 files changed, 1470 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoftEdge/MSFT_IntuneSecurityBaselineMicrosoftEdge.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoftEdge/MSFT_IntuneSecurityBaselineMicrosoftEdge.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoftEdge/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoftEdge/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneSecurityBaselineMicrosoftEdge/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneSecurityBaselineMicrosoftEdge/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneSecurityBaselineMicrosoftEdge/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneSecurityBaselineMicrosoftEdge.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index fe3a0e3046..e3a64fe812 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,8 @@ * Initial release * IntuneSecurityBaselineMicrosoft365AppsForEnterprise * Initial release +* IntuneSecurityBaselineMicrosoftEdge + * Initial release * PPAdminDLPPolicy * Initial release. * PPDLPPolicyConnectorConfigurations diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoftEdge/MSFT_IntuneSecurityBaselineMicrosoftEdge.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoftEdge/MSFT_IntuneSecurityBaselineMicrosoftEdge.psm1 new file mode 100644 index 0000000000..c3b6e71fd2 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoftEdge/MSFT_IntuneSecurityBaselineMicrosoftEdge.psm1 @@ -0,0 +1,904 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $InternetExplorerIntegrationReloadInIEModeAllowed, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $SSLErrorOverrideAllowed, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $InternetExplorerIntegrationZoneIdentifierMhtFileAllowed, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $BrowserLegacyExtensionPointsBlockingEnabled, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $SitePerProcess, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $EdgeEnhanceImagesEnabled, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $ExtensionInstallBlocklist, + + [Parameter()] + [ValidateLength(0, 2048)] + [System.String[]] + $ExtensionInstallBlocklistDesc, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $WebSQLAccess, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $BasicAuthOverHttpEnabled, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $MicrosoftEdge_HTTPAuthentication_AuthSchemes, + + [Parameter()] + [System.String] + $authschemes, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $NativeMessagingUserLevelHosts, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $InsecurePrivateNetworkRequestsAllowed, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $InternetExplorerModeToolbarButtonEnabled, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $SmartScreenEnabled, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $SmartScreenPuaEnabled, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $PreventSmartScreenPromptOverride, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $PreventSmartScreenPromptOverrideForFiles, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $SharedArrayBufferUnrestrictedAccessAllowed, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $TyposquattingCheckerEnabled, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + #endregion + + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + try + { + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + + $getValue = $null + #region resource generator code + $getValue = Get-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $Id -ErrorAction SilentlyContinue + + if ($null -eq $getValue) + { + Write-Verbose -Message "Could not find an Intune Security Baseline Microsoft Edge with Id {$Id}" + + if (-not [System.String]::IsNullOrEmpty($DisplayName)) + { + $getValue = Get-MgBetaDeviceManagementConfigurationPolicy ` + -Filter "Name eq '$DisplayName'" ` + -ErrorAction SilentlyContinue + } + } + #endregion + if ($null -eq $getValue) + { + Write-Verbose -Message "Could not find an Intune Security Baseline Microsoft Edge with Name {$DisplayName}." + return $nullResult + } + $Id = $getValue.Id + Write-Verbose -Message "An Intune Security Baseline Microsoft Edge with Id {$Id} and Name {$DisplayName} was found" + + # Retrieve policy specific settings + [array]$settings = Get-MgBetaDeviceManagementConfigurationPolicySetting ` + -DeviceManagementConfigurationPolicyId $Id ` + -ExpandProperty 'settingDefinitions' ` + -All ` + -ErrorAction Stop + + $policySettings = @{} + $policySettings = Export-IntuneSettingCatalogPolicySettings -Settings $settings -ReturnHashtable $policySettings + + $results = @{ + #region resource generator code + Description = $getValue.Description + DisplayName = $getValue.Name + RoleScopeTagIds = $getValue.RoleScopeTagIds + Id = $getValue.Id + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + #endregion + } + $results += $policySettings + + $assignmentsValues = Get-MgBetaDeviceManagementConfigurationPolicyAssignment -DeviceManagementConfigurationPolicyId $Id + $assignmentResult = @() + if ($assignmentsValues.Count -gt 0) + { + $assignmentResult += ConvertFrom-IntunePolicyAssignment -Assignments $assignmentsValues -IncludeDeviceFilter $true + } + $results.Add('Assignments', $assignmentResult) + + return [System.Collections.Hashtable] $results + } + catch + { + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $InternetExplorerIntegrationReloadInIEModeAllowed, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $SSLErrorOverrideAllowed, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $InternetExplorerIntegrationZoneIdentifierMhtFileAllowed, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $BrowserLegacyExtensionPointsBlockingEnabled, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $SitePerProcess, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $EdgeEnhanceImagesEnabled, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $ExtensionInstallBlocklist, + + [Parameter()] + [ValidateLength(0, 2048)] + [System.String[]] + $ExtensionInstallBlocklistDesc, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $WebSQLAccess, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $BasicAuthOverHttpEnabled, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $MicrosoftEdge_HTTPAuthentication_AuthSchemes, + + [Parameter()] + [System.String] + $authschemes, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $NativeMessagingUserLevelHosts, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $InsecurePrivateNetworkRequestsAllowed, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $InternetExplorerModeToolbarButtonEnabled, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $SmartScreenEnabled, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $SmartScreenPuaEnabled, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $PreventSmartScreenPromptOverride, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $PreventSmartScreenPromptOverrideForFiles, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $SharedArrayBufferUnrestrictedAccessAllowed, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $TyposquattingCheckerEnabled, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + #endregion + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + + $BoundParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + $templateReferenceId = 'c66347b7-8325-4954-a235-3bf2233dfbfd_2' + $platforms = 'windows10' + $technologies = 'mdm' + + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + Write-Verbose -Message "Creating an Intune Security Baseline Microsoft Edge with Name {$DisplayName}" + $BoundParameters.Remove("Assignments") | Out-Null + + $settings = Get-IntuneSettingCatalogPolicySetting ` + -DSCParams ([System.Collections.Hashtable]$BoundParameters) ` + -TemplateId $templateReferenceId + + $createParameters = @{ + Name = $DisplayName + Description = $Description + TemplateReference = @{ templateId = $templateReferenceId } + Platforms = $platforms + Technologies = $technologies + Settings = $settings + } + + #region resource generator code + $policy = New-MgBetaDeviceManagementConfigurationPolicy -BodyParameter $createParameters + + if ($policy.Id) + { + $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + Update-DeviceConfigurationPolicyAssignment ` + -DeviceConfigurationPolicyId $policy.Id ` + -Targets $assignmentsHash ` + -Repository 'deviceManagement/configurationPolicies' + } + #endregion + } + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Updating the Intune Security Baseline Microsoft Edge with Id {$($currentInstance.Id)}" + $BoundParameters.Remove("Assignments") | Out-Null + + $settings = Get-IntuneSettingCatalogPolicySetting ` + -DSCParams ([System.Collections.Hashtable]$BoundParameters) ` + -TemplateId $templateReferenceId + + Update-IntuneDeviceConfigurationPolicy ` + -DeviceConfigurationPolicyId $currentInstance.Id ` + -Name $DisplayName ` + -Description $Description ` + -TemplateReferenceId $templateReferenceId ` + -Platforms $platforms ` + -Technologies $technologies ` + -Settings $settings + + #region resource generator code + $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + Update-DeviceConfigurationPolicyAssignment ` + -DeviceConfigurationPolicyId $currentInstance.Id ` + -Targets $assignmentsHash ` + -Repository 'deviceManagement/configurationPolicies' + #endregion + } + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Removing the Intune Security Baseline Microsoft Edge with Id {$($currentInstance.Id)}" + #region resource generator code + Remove-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $currentInstance.Id + #endregion + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $InternetExplorerIntegrationReloadInIEModeAllowed, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $SSLErrorOverrideAllowed, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $InternetExplorerIntegrationZoneIdentifierMhtFileAllowed, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $BrowserLegacyExtensionPointsBlockingEnabled, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $SitePerProcess, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $EdgeEnhanceImagesEnabled, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $ExtensionInstallBlocklist, + + [Parameter()] + [ValidateLength(0, 2048)] + [System.String[]] + $ExtensionInstallBlocklistDesc, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $WebSQLAccess, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $BasicAuthOverHttpEnabled, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $MicrosoftEdge_HTTPAuthentication_AuthSchemes, + + [Parameter()] + [System.String] + $authschemes, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $NativeMessagingUserLevelHosts, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $InsecurePrivateNetworkRequestsAllowed, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $InternetExplorerModeToolbarButtonEnabled, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $SmartScreenEnabled, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $SmartScreenPuaEnabled, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $PreventSmartScreenPromptOverride, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $PreventSmartScreenPromptOverrideForFiles, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $SharedArrayBufferUnrestrictedAccessAllowed, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $TyposquattingCheckerEnabled, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + #endregion + + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + Write-Verbose -Message "Testing configuration of the Intune Security Baseline Microsoft Edge with Id {$Id} and Name {$DisplayName}" + + $CurrentValues = Get-TargetResource @PSBoundParameters + [Hashtable]$ValuesToCheck = @{} + $MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object { + if ($_.Key -notlike '*Variable' -or $_.Key -notin @('Verbose', 'Debug', 'ErrorAction', 'WarningAction', 'InformationAction')) + { + if ($null -ne $CurrentValues[$_.Key] -or $null -ne $PSBoundParameters[$_.Key]) + { + $ValuesToCheck.Add($_.Key, $null) + if (-not $PSBoundParameters.ContainsKey($_.Key)) + { + $PSBoundParameters.Add($_.Key, $null) + } + } + } + } + + if ($CurrentValues.Ensure -ne $Ensure) + { + Write-Verbose -Message "Test-TargetResource returned $false" + return $false + } + $testResult = $true + + #Compare Cim instances + foreach ($key in $PSBoundParameters.Keys) + { + $source = $PSBoundParameters.$key + $target = $CurrentValues.$key + if ($null -ne $source -and $source.GetType().Name -like '*CimInstance*') + { + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + if (-not $testResult) + { + break + } + + $ValuesToCheck.Remove($key) | Out-Null + } + } + + $ValuesToCheck.Remove('Id') | Out-Null + $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + + if ($testResult) + { + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + } + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + #region resource generator code + $policyTemplateID = "c66347b7-8325-4954-a235-3bf2233dfbfd_2" + [array]$getValue = Get-MgBetaDeviceManagementConfigurationPolicy ` + -Filter $Filter ` + -All ` + -ErrorAction Stop | Where-Object ` + -FilterScript { + $_.TemplateReference.TemplateId -eq $policyTemplateID + } + #endregion + + $i = 1 + $dscContent = '' + if ($getValue.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $getValue) + { + $displayedKey = $config.Id + if (-not [String]::IsNullOrEmpty($config.displayName)) + { + $displayedKey = $config.displayName + } + elseif (-not [string]::IsNullOrEmpty($config.name)) + { + $displayedKey = $config.name + } + Write-Host " |---[$i/$($getValue.Count)] $displayedKey" -NoNewline + $params = @{ + Id = $config.Id + DisplayName = $config.Name + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + if ($Results.Assignments) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString -ComplexObject $Results.Assignments -CIMInstanceName DeviceManagementConfigurationPolicyAssignments + if ($complexTypeStringResult) + { + $Results.Assignments = $complexTypeStringResult + } + else + { + $Results.Remove('Assignments') | Out-Null + } + } + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + + if ($Results.Assignments) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "Assignments" -IsCIMArray:$true + } + + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoftEdge/MSFT_IntuneSecurityBaselineMicrosoftEdge.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoftEdge/MSFT_IntuneSecurityBaselineMicrosoftEdge.schema.mof new file mode 100644 index 0000000000..8a9515e3d3 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoftEdge/MSFT_IntuneSecurityBaselineMicrosoftEdge.schema.mof @@ -0,0 +1,50 @@ +[ClassVersion("1.0.0.0")] +class MSFT_DeviceManagementConfigurationPolicyAssignments +{ + [Write, Description("The type of the target assignment."), ValueMap{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget","#microsoft.graph.configurationManagerCollectionAssignmentTarget"}, Values{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget","#microsoft.graph.configurationManagerCollectionAssignmentTarget"}] String dataType; + [Write, Description("The type of filter of the target assignment i.e. Exclude or Include. Possible values are:none, include, exclude."), ValueMap{"none","include","exclude"}, Values{"none","include","exclude"}] String deviceAndAppManagementAssignmentFilterType; + [Write, Description("The Id of the filter for the target assignment.")] String deviceAndAppManagementAssignmentFilterId; + [Write, Description("The group Id that is the target of the assignment.")] String groupId; + [Write, Description("The group Display Name that is the target of the assignment.")] String groupDisplayName; + [Write, Description("The collection Id that is the target of the assignment.(ConfigMgr)")] String collectionId; +}; + + +[ClassVersion("1.0.0.0"), FriendlyName("IntuneSecurityBaselineMicrosoftEdge")] +class MSFT_IntuneSecurityBaselineMicrosoftEdge : OMI_BaseResource +{ + [Write, Description("Policy description")] String Description; + [Key, Description("Policy name")] String DisplayName; + [Write, Description("List of Scope Tags for this Entity instance.")] String RoleScopeTagIds[]; + [Write, Description("The unique identifier for an entity. Read-only.")] String Id; + [Write, Description("Allow unconfigured sites to be reloaded in Internet Explorer mode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String InternetExplorerIntegrationReloadInIEModeAllowed; + [Write, Description("Allow users to proceed from the HTTPS warning page (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String SSLErrorOverrideAllowed; + [Write, Description("Automatically open downloaded MHT or MHTML files from the web in Internet Explorer mode (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String InternetExplorerIntegrationZoneIdentifierMhtFileAllowed; + [Write, Description("Enable browser legacy extension point blocking (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String BrowserLegacyExtensionPointsBlockingEnabled; + [Write, Description("Enable site isolation for every site (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String SitePerProcess; + [Write, Description("Enhance images enabled (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String EdgeEnhanceImagesEnabled; + [Write, Description("Control which extensions cannot be installed (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String ExtensionInstallBlocklist; + [Write, Description("Extension IDs the user should be prevented from installing (or * for all) (Device) - Depends on ExtensionInstallBlocklist")] String ExtensionInstallBlocklistDesc[]; + [Write, Description("Force WebSQL to be enabled (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String WebSQLAccess; + [Write, Description("Allow Basic authentication for HTTP (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String BasicAuthOverHttpEnabled; + [Write, Description("Supported authentication schemes (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String MicrosoftEdge_HTTPAuthentication_AuthSchemes; + [Write, Description("Supported authentication schemes (Device) - Depends on MicrosoftEdge_HTTPAuthentication_AuthSchemes")] String authschemes; + [Write, Description("Allow user-level native messaging hosts (installed without admin permissions) (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String NativeMessagingUserLevelHosts; + [Write, Description("Specifies whether to allow insecure websites to make requests to more-private network endpoints (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String InsecurePrivateNetworkRequestsAllowed; + [Write, Description("Show the Reload in Internet Explorer mode button in the toolbar (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String InternetExplorerModeToolbarButtonEnabled; + [Write, Description("Configure Microsoft Defender SmartScreen (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String SmartScreenEnabled; + [Write, Description("Configure Microsoft Defender SmartScreen to block potentially unwanted apps (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String SmartScreenPuaEnabled; + [Write, Description("Prevent bypassing Microsoft Defender SmartScreen prompts for sites (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String PreventSmartScreenPromptOverride; + [Write, Description("Prevent bypassing of Microsoft Defender SmartScreen warnings about downloads (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String PreventSmartScreenPromptOverrideForFiles; + [Write, Description("Specifies whether SharedArrayBuffers can be used in a non cross-origin-isolated context (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String SharedArrayBufferUnrestrictedAccessAllowed; + [Write, Description("Configure Edge TyposquattingChecker (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String TyposquattingCheckerEnabled; + [Write, Description("Represents the assignment to the Intune policy."), EmbeddedInstance("MSFT_DeviceManagementConfigurationPolicyAssignments")] String Assignments[]; + [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; + [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Secret of the Azure Active Directory tenant used for authentication."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoftEdge/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoftEdge/readme.md new file mode 100644 index 0000000000..f614869e4f --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoftEdge/readme.md @@ -0,0 +1,6 @@ + +# IntuneSecurityBaselineMicrosoftEdge + +## Description + +Intune Security Baseline Microsoft Edge diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoftEdge/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoftEdge/settings.json new file mode 100644 index 0000000000..67b62b373e --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSecurityBaselineMicrosoftEdge/settings.json @@ -0,0 +1,33 @@ +{ + "resourceName": "IntuneSecurityBaselineMicrosoftEdge", + "description": "This resource configures an Intune Security Baseline Microsoft Edge.", + "permissions": { + "graph": { + "application": { + "read": [ + { + "name": "DeviceManagementConfiguration.Read.All" + } + ], + "update": [ + { + "name": "DeviceManagementConfiguration.ReadWrite.All" + } + ] + }, + "delegated": { + "read": [ + { + "name": "DeviceManagementConfiguration.Read.All" + } + ], + "update": [ + { + "name": "DeviceManagementConfiguration.ReadWrite.All" + } + ] + } + } +} + +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneSecurityBaselineMicrosoftEdge/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneSecurityBaselineMicrosoftEdge/1-Create.ps1 new file mode 100644 index 0000000000..fdb3b29ab6 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneSecurityBaselineMicrosoftEdge/1-Create.ps1 @@ -0,0 +1,38 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneSecurityBaselineMicrosoftEdge 'mySecurityBaselineMicrosoftEdge' + { + DisplayName = 'test' + InsecurePrivateNetworkRequestsAllowed = "0"; + InternetExplorerIntegrationReloadInIEModeAllowed = "0"; + InternetExplorerIntegrationZoneIdentifierMhtFileAllowed = "0"; + InternetExplorerModeToolbarButtonEnabled = "0"; + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneSecurityBaselineMicrosoftEdge/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneSecurityBaselineMicrosoftEdge/2-Update.ps1 new file mode 100644 index 0000000000..125c7be94d --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneSecurityBaselineMicrosoftEdge/2-Update.ps1 @@ -0,0 +1,38 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneSecurityBaselineMicrosoftEdge 'mySecurityBaselineMicrosoftEdge' + { + DisplayName = 'test' + InsecurePrivateNetworkRequestsAllowed = "0"; + InternetExplorerIntegrationReloadInIEModeAllowed = "0"; + InternetExplorerIntegrationZoneIdentifierMhtFileAllowed = "0"; + InternetExplorerModeToolbarButtonEnabled = "1"; # Drift + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneSecurityBaselineMicrosoftEdge/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneSecurityBaselineMicrosoftEdge/3-Remove.ps1 new file mode 100644 index 0000000000..d9830b3fe9 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneSecurityBaselineMicrosoftEdge/3-Remove.ps1 @@ -0,0 +1,34 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneSecurityBaselineMicrosoftEdge 'mySecurityBaselineMicrosoftEdge' + { + DisplayName = 'test' + Ensure = 'Absent' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} diff --git a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 index 7a3beda733..b2265143bf 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 @@ -2149,11 +2149,13 @@ function Get-IntuneSettingCatalogPolicySettingDSCValue $newKey = $key switch -wildcard ($newKey) { + '*_HTTPAuthentication_*' { $newKey = $newKey.Replace('HTTPAuthentication', '~HTTPAuthentication') } '*TrustCenterTrustedLocations_*' { $newKey = $newKey.Replace('TrustCenterTrustedLocations', 'TrustCenter~L_TrustedLocations') } '*TrustCenterFileBlockSettings_*' { $newKey = $newKey.Replace('TrustCenterFileBlockSettings', 'TrustCenter~L_FileBlockSettings') } '*TrustCenterProtectedView_*' { $newKey = $newKey.Replace('TrustCenterProtectedView', 'TrustCenter~L_ProtectedView') } '*_TrustCenter*' { $newKey = $newKey.Replace('_TrustCenter', '~L_TrustCenter') } '*_Security_*' { $newKey = $newKey.Replace('Security', '~L_Security') } + 'MicrosoftEdge_*' { $newKey = $newKey.Replace('MicrosoftEdge_', 'microsoft_edge~Policy~microsoft_edge') } 'MicrosoftPublisherV3_*' { $newKey = $newKey.Replace('MicrosoftPublisherV3_', 'pub16v3~Policy~L_MicrosoftOfficePublisher') } 'MicrosoftPublisherV2_*' { $newKey = $newKey.Replace('MicrosoftPublisherV2_', 'pub16v2~Policy~L_MicrosoftOfficePublisher') } 'MicrosoftVisio_*' { $newKey = $newKey.Replace('MicrosoftVisio_', 'visio16v2~Policy~L_MicrosoftVisio~L_VisioOptions') } @@ -2618,11 +2620,13 @@ function Export-IntuneSettingCatalogPolicySettings 'visio16v2~Policy~L_MicrosoftVisio~L_VisioOptions~*' { $settingName = $settingName.Replace('visio16v2~Policy~L_MicrosoftVisio~L_VisioOptions', 'MicrosoftVisio_') } 'pub16v2~Policy~L_MicrosoftOfficePublisher~*' { $settingName = $settingName.Replace('pub16v2~Policy~L_MicrosoftOfficePublisher', 'MicrosoftPublisherV2_') } 'pub16v3~Policy~L_MicrosoftOfficePublisher~*' { $settingName = $settingName.Replace('pub16v3~Policy~L_MicrosoftOfficePublisher', 'MicrosoftPublisherV3_') } + 'microsoft_edge~Policy~microsoft_edge~*' { $settingName = $settingName.Replace('microsoft_edge~Policy~microsoft_edge', 'MicrosoftEdge_') } '*~L_Security~*' { $settingName = $settingName.Replace('~L_Security', 'Security') } '*~L_TrustCenter*' { $settingName = $settingName.Replace('~L_TrustCenter', '_TrustCenter') } '*~L_ProtectedView_*' { $settingName = $settingName.Replace('~L_ProtectedView', 'ProtectedView') } '*~L_FileBlockSettings_*' { $settingName = $settingName.Replace('~L_FileBlockSettings', 'FileBlockSettings') } '*~L_TrustedLocations*' { $settingName = $settingName.Replace('~L_TrustedLocations', 'TrustedLocations') } + '*~HTTPAuthentication_*' { $settingName = $settingName.Replace('~HTTPAuthentication', 'HTTPAuthentication') } } } diff --git a/ResourceGenerator/M365DSCResourceGenerator.psm1 b/ResourceGenerator/M365DSCResourceGenerator.psm1 index 68b1aae17d..d3b13f84f9 100644 --- a/ResourceGenerator/M365DSCResourceGenerator.psm1 +++ b/ResourceGenerator/M365DSCResourceGenerator.psm1 @@ -3955,11 +3955,13 @@ function New-SettingsCatalogSettingDefinitionSettingsFromTemplate { 'visio16v2~Policy~L_MicrosoftVisio~L_VisioOptions~*' { $settingName = $settingName.Replace('visio16v2~Policy~L_MicrosoftVisio~L_VisioOptions', 'MicrosoftVisio_') } 'pub16v2~Policy~L_MicrosoftOfficePublisher~*' { $settingName = $settingName.Replace('pub16v2~Policy~L_MicrosoftOfficePublisher', 'MicrosoftPublisherV2_') } 'pub16v3~Policy~L_MicrosoftOfficePublisher~*' { $settingName = $settingName.Replace('pub16v3~Policy~L_MicrosoftOfficePublisher', 'MicrosoftPublisherV3_') } + 'microsoft_edge~Policy~microsoft_edge~*' { $settingName = $settingName.Replace('microsoft_edge~Policy~microsoft_edge', 'MicrosoftEdge_') } '*~L_Security~*' { $settingName = $settingName.Replace('~L_Security', 'Security') } '*~L_TrustCenter*' { $settingName = $settingName.Replace('~L_TrustCenter', '_TrustCenter') } '*~L_ProtectedView_*' { $settingName = $settingName.Replace('~L_ProtectedView', 'ProtectedView') } '*~L_FileBlockSettings_*' { $settingName = $settingName.Replace('~L_FileBlockSettings', 'FileBlockSettings') } '*~L_TrustedLocations*' { $settingName = $settingName.Replace('~L_TrustedLocations', 'TrustedLocations') } + '*~HTTPAuthentication_*' { $settingName = $settingName.Replace('~HTTPAuthentication', 'HTTPAuthentication') } } } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneSecurityBaselineMicrosoftEdge.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneSecurityBaselineMicrosoftEdge.Tests.ps1 new file mode 100644 index 0000000000..c5f003a76e --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneSecurityBaselineMicrosoftEdge.Tests.ps1 @@ -0,0 +1,359 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource "IntuneSecurityBaselineMicrosoftEdge" -GenericStubModule $GenericStubPath +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName Get-PSSession -MockWith { + } + + Mock -CommandName Remove-PSSession -MockWith { + } + + Mock -CommandName Update-MgBetaDeviceManagementConfigurationPolicy -MockWith { + } + + Mock -CommandName New-MgBetaDeviceManagementConfigurationPolicy -MockWith { + return @{ + Id = '12345-12345-12345-12345-12345' + } + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicy -MockWith { + return @{ + Id = '12345-12345-12345-12345-12345' + Description = 'My Test' + Name = 'My Test' + RoleScopeTagIds = @("FakeStringValue") + TemplateReference = @{ + TemplateId = 'c66347b7-8325-4954-a235-3bf2233dfbfd_2' + } + } + } + + Mock -CommandName Remove-MgBetaDeviceManagementConfigurationPolicy -MockWith { + } + + Mock -CommandName Update-IntuneDeviceConfigurationPolicy -MockWith { + } + + Mock -CommandName Get-IntuneSettingCatalogPolicySetting -MockWith { + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicySetting -MockWith { + return @( + @{ + Id = '0' + SettingDefinitions = @( + @{ + Id = 'device_vendor_msft_policy_config_microsoft_edgev92~policy~microsoft_edge~privatenetworkrequestsettings_insecureprivatenetworkrequestsallowed' + Name = 'InsecurePrivateNetworkRequestsAllowed' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + } + } + ) + SettingInstance = @{ + SettingDefinitionId = 'device_vendor_msft_policy_config_microsoft_edgev92~policy~microsoft_edge~privatenetworkrequestsettings_insecureprivatenetworkrequestsallowed' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = 'c6dec9f2-a235-4878-8462-e88569b47e0b' + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + choiceSettingValue = @{ + children = @() + value = 'device_vendor_msft_policy_config_microsoft_edgev92~policy~microsoft_edge~privatenetworkrequestsettings_insecureprivatenetworkrequestsallowed_0' + } + } + } + }, + @{ + Id = '1' + SettingDefinitions = @( + @{ + Id = 'device_vendor_msft_policy_config_microsoft_edgev92~policy~microsoft_edge_internetexplorerintegrationreloadiniemodeallowed' + Name = 'InternetExplorerIntegrationReloadInIEModeAllowed' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + } + } + ) + SettingInstance = @{ + SettingDefinitionId = 'device_vendor_msft_policy_config_microsoft_edgev92~policy~microsoft_edge_internetexplorerintegrationreloadiniemodeallowed' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = 'fd416796-3442-405c-9f9e-e1ca3c0b9e3f' + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + choiceSettingValue = @{ + children = @() + value = 'device_vendor_msft_policy_config_microsoft_edgev92~policy~microsoft_edge_internetexplorerintegrationreloadiniemodeallowed_0' + } + } + } + }, + @{ + Id = '2' + SettingDefinitions = @( + @{ + Id = 'device_vendor_msft_policy_config_microsoft_edgev117~policy~microsoft_edge_internetexplorerintegrationzoneidentifiermhtfileallowed' + Name = 'InternetExplorerIntegrationZoneIdentifierMhtFileAllowed' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + } + } + ) + SettingInstance = @{ + SettingDefinitionId = 'device_vendor_msft_policy_config_microsoft_edgev117~policy~microsoft_edge_internetexplorerintegrationzoneidentifiermhtfileallowed' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = 'ba15aa09-ea95-49bd-92bf-de9cec9c1146' + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + choiceSettingValue = @{ + children = @() + value = 'device_vendor_msft_policy_config_microsoft_edgev117~policy~microsoft_edge_internetexplorerintegrationzoneidentifiermhtfileallowed_0' + } + } + } + }, + @{ + Id = '3' + SettingDefinitions = @( + @{ + Id = 'device_vendor_msft_policy_config_microsoft_edgev96~policy~microsoft_edge_internetexplorermodetoolbarbuttonenabled' + Name = 'InternetExplorerModeToolbarButtonEnabled' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + } + } + ) + SettingInstance = @{ + SettingDefinitionId = 'device_vendor_msft_policy_config_microsoft_edgev96~policy~microsoft_edge_internetexplorermodetoolbarbuttonenabled' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = 'fd416796-3442-405c-9f9e-e1ca3c0b9e3f' + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + choiceSettingValue = @{ + children = @() + value = 'device_vendor_msft_policy_config_microsoft_edgev96~policy~microsoft_edge_internetexplorermodetoolbarbuttonenabled_0' + } + } + } + } + ) + } + + Mock -CommandName Update-DeviceConfigurationPolicyAssignment -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicyAssignment -MockWith { + return @(@{ + Id = '12345-12345-12345-12345-12345' + Source = 'direct' + SourceId = '12345-12345-12345-12345-12345' + Target = @{ + DeviceAndAppManagementAssignmentFilterId = '12345-12345-12345-12345-12345' + DeviceAndAppManagementAssignmentFilterType = 'none' + AdditionalProperties = @( + @{ + '@odata.type' = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + } + ) + } + }) + } + + } + # Test contexts + Context -Name "The IntuneSecurityBaselineMicrosoftEdge should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + deviceAndAppManagementAssignmentFilterType = 'none' + } -ClientOnly) + ) + Description = "My Test" + Id = "12345-12345-12345-12345-12345" + InsecurePrivateNetworkRequestsAllowed = "0" + InternetExplorerIntegrationReloadInIEModeAllowed = "0" + InternetExplorerIntegrationZoneIdentifierMhtFileAllowed = "0" + InternetExplorerModeToolbarButtonEnabled = "0" + DisplayName = "My Test" + RoleScopeTagIds = @("FakeStringValue") + Ensure = "Present" + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicy -MockWith { + return $null + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + It 'Should Create the group from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-MgBetaDeviceManagementConfigurationPolicy -Exactly 1 + } + } + + Context -Name "The IntuneSecurityBaselineMicrosoftEdge exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + deviceAndAppManagementAssignmentFilterType = 'none' + } -ClientOnly) + ) + Description = "My Test" + Id = "12345-12345-12345-12345-12345" + InsecurePrivateNetworkRequestsAllowed = "0" + InternetExplorerIntegrationReloadInIEModeAllowed = "0" + InternetExplorerIntegrationZoneIdentifierMhtFileAllowed = "0" + InternetExplorerModeToolbarButtonEnabled = "0" + DisplayName = "My Test" + RoleScopeTagIds = @("FakeStringValue") + Ensure = "Absent" + Credential = $Credential; + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should Remove the group from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-MgBetaDeviceManagementConfigurationPolicy -Exactly 1 + } + } + Context -Name "The IntuneSecurityBaselineMicrosoftEdge Exists and Values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + deviceAndAppManagementAssignmentFilterType = 'none' + } -ClientOnly) + ) + Description = "My Test" + Id = "12345-12345-12345-12345-12345" + InsecurePrivateNetworkRequestsAllowed = "0" + InternetExplorerIntegrationReloadInIEModeAllowed = "0" + InternetExplorerIntegrationZoneIdentifierMhtFileAllowed = "0" + InternetExplorerModeToolbarButtonEnabled = "0" + DisplayName = "My Test" + RoleScopeTagIds = @("FakeStringValue") + Ensure = "Present" + Credential = $Credential; + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The IntuneSecurityBaselineMicrosoftEdge exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + deviceAndAppManagementAssignmentFilterType = 'none' + } -ClientOnly) + ) + Description = "My Test" + Id = "12345-12345-12345-12345-12345" + InsecurePrivateNetworkRequestsAllowed = "0" + InternetExplorerIntegrationReloadInIEModeAllowed = "0" + InternetExplorerIntegrationZoneIdentifierMhtFileAllowed = "0" + InternetExplorerModeToolbarButtonEnabled = "1" # Drift + DisplayName = "My Test" + RoleScopeTagIds = @("FakeStringValue") + Ensure = "Present" + Credential = $Credential; + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Update-IntuneDeviceConfigurationPolicy -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope From c31cd7867b2453936b5e93a94d8f677fb2df7e7f Mon Sep 17 00:00:00 2001 From: Maarten Piederiet Date: Wed, 16 Oct 2024 10:57:30 +0200 Subject: [PATCH 233/252] Fixed bug where RestrictedSenderList always returned empty in the DSC resource --- .../MSFT_TeamsClientConfiguration.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsClientConfiguration/MSFT_TeamsClientConfiguration.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsClientConfiguration/MSFT_TeamsClientConfiguration.psm1 index b75b494596..52c9790f70 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsClientConfiguration/MSFT_TeamsClientConfiguration.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsClientConfiguration/MSFT_TeamsClientConfiguration.psm1 @@ -140,7 +140,7 @@ function Get-TargetResource ManagedIdentity = $ManagedIdentity.IsPresent AccessTokens = $AccessTokens } - if ([System.String]::IsNullOrEmpty($RestrictedSenderList)) + if ([System.String]::IsNullOrEmpty($Config.RestrictedSenderList)) { $result.Remove('RestrictedSenderList') | Out-Null } From 5c5da44c1cfd50f82976ef380c019cc33cd3f050 Mon Sep 17 00:00:00 2001 From: Maarten Piederiet Date: Wed, 16 Oct 2024 10:58:51 +0200 Subject: [PATCH 234/252] Improved/fixed setting the RestrictedSenderList value, using semicolon as separator as mentioned in the documentation --- .../MSFT_TeamsClientConfiguration.psm1 | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsClientConfiguration/MSFT_TeamsClientConfiguration.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsClientConfiguration/MSFT_TeamsClientConfiguration.psm1 index 52c9790f70..92381749be 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsClientConfiguration/MSFT_TeamsClientConfiguration.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsClientConfiguration/MSFT_TeamsClientConfiguration.psm1 @@ -282,12 +282,9 @@ function Set-TargetResource } else { - $tempValue = $null - foreach ($sender in $SetParams.RestrictedSenderList) - { - $tempValue += $sender + ',' - } - $tempValue = $tempValue.Substring(0, $tempValue.Length - 1) + # https://learn.microsoft.com/en-us/powershell/module/teams/set-csteamsclientconfiguration?view=teams-ps#-restrictedsenderlist + # This is a semicolon-separated string of the domains you'd like to allow to send emails to Teams channels + $tempValue = $SetParams['RestrictedSenderList'] -join ';' $SetParams.RestrictedSenderList = $tempValue } Set-CsTeamsClientConfiguration @SetParams From d6b5b495a7d5cb463e588b0c352e36f7381a7336 Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Wed, 16 Oct 2024 10:35:43 +0200 Subject: [PATCH 235/252] Update handling for non-unique settings --- .../Modules/M365DSCDRGUtil.psm1 | 34 ++++++++++++++++++- .../M365DSCResourceGenerator.psm1 | 6 ++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 index b2265143bf..e5ff29e4b2 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 @@ -2121,6 +2121,7 @@ function Get-IntuneSettingCatalogPolicySettingDSCValue $matchCombined = $false $matchesId = $false $matchesOffsetUri = $false + $offsetUriFound = $false $settingDefinitions = $SettingTemplates.SettingDefinitions ` | Where-Object -FilterScript { $_.Name -eq $key } @@ -2208,6 +2209,19 @@ function Get-IntuneSettingCatalogPolicySettingDSCValue $SettingDefinition = $_ } } + + if (-not $matchesId) + { + $definition = Get-SettingDefinitionFromNameWithParentFromOffsetUri -OffsetUriName $key -SettingDefinitions $SettingTemplates.SettingDefinitions + if ($null -ne $definition) + { + $offsetUriFound = $true + if ($SettingDefinition.Id -eq $definition.Id) + { + $matchesOffsetUri = $true + } + } + } } } @@ -2334,6 +2348,7 @@ function Get-SettingDefinitionFromNameWithParentFromOffsetUri $settingsWithSameName = $filteredDefinitions foreach ($definition in $filteredDefinitions) { + $parentSetting = Get-ParentSettingDefinition -SettingDefinition $definition -AllSettingDefinitions $SettingDefinitions $skip = 0 $breakCounter = 0 $newSettingName = $settingName @@ -2361,7 +2376,18 @@ function Get-SettingDefinitionFromNameWithParentFromOffsetUri if ($breakCounter -eq 8) { - throw "Could not find a unique setting definition for $settingName with parent from OffsetUri $OffsetUriName" + if ($null -ne $parentSetting) + { + # Alternative way if no unique setting name can be found + $parentSettingIdProperty = $parentSetting.Id.Split('_')[-1] + $parentSettingIdWithoutProperty = $parentSetting.Id.Replace("_$parentSettingIdProperty", "") + # We can't use the entire setting here, because the child setting id does not have to come after the parent setting id + $settingNameV2 = $definition.Id.Replace($parentSettingIdWithoutProperty + "_", "").Replace($parentSettingIdProperty + "_", "") + if ($settingNameV2 -eq $OffsetUriName) + { + $newSettingName = $settingNameV2 + } + } } if ($newSettingName -eq $OffsetUriName) @@ -2423,6 +2449,12 @@ function Get-SettingDefinitionNameWithParentFromOffsetUri { { $splittedOffsetUri = $splittedOffsetUri[1..($splittedOffsetUri.Length - 1)] } + + if ($Skip -gt $splittedOffsetUri.Length - 1) + { + return $SettingName + } + $splittedOffsetUri = $splittedOffsetUri[0..($splittedOffsetUri.Length - 1 - $Skip)] $traversed = $false while (-not $traversed -and $splittedOffsetUri.Length -gt 1) # Prevent adding the first element of the OffsetUri diff --git a/ResourceGenerator/M365DSCResourceGenerator.psm1 b/ResourceGenerator/M365DSCResourceGenerator.psm1 index d3b13f84f9..0f8d094ab5 100644 --- a/ResourceGenerator/M365DSCResourceGenerator.psm1 +++ b/ResourceGenerator/M365DSCResourceGenerator.psm1 @@ -4035,6 +4035,12 @@ function Get-SettingDefinitionNameWithParentFromOffsetUri { { $splittedOffsetUri = $splittedOffsetUri[1..($splittedOffsetUri.Length - 1)] } + + if ($Skip -gt $splittedOffsetUri.Length - 1) + { + return $SettingName + } + $splittedOffsetUri = $splittedOffsetUri[0..($splittedOffsetUri.Length - 1 - $Skip)] $traversed = $false while (-not $traversed -and $splittedOffsetUri.Length -gt 1) # Prevent adding the first element of the OffsetUri From 503d20a0cb08e5aac8a2abb5b8eb4e1475a827a0 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 16 Oct 2024 14:36:53 +0000 Subject: [PATCH 236/252] Updated Resources and Cmdlet documentation pages --- .../IntuneSecurityBaselineMicrosoftEdge.md | 206 ++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 docs/docs/resources/intune/IntuneSecurityBaselineMicrosoftEdge.md diff --git a/docs/docs/resources/intune/IntuneSecurityBaselineMicrosoftEdge.md b/docs/docs/resources/intune/IntuneSecurityBaselineMicrosoftEdge.md new file mode 100644 index 0000000000..439264f0bc --- /dev/null +++ b/docs/docs/resources/intune/IntuneSecurityBaselineMicrosoftEdge.md @@ -0,0 +1,206 @@ +# IntuneSecurityBaselineMicrosoftEdge + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Description** | Write | String | Policy description | | +| **DisplayName** | Key | String | Policy name | | +| **RoleScopeTagIds** | Write | StringArray[] | List of Scope Tags for this Entity instance. | | +| **Id** | Write | String | The unique identifier for an entity. Read-only. | | +| **InternetExplorerIntegrationReloadInIEModeAllowed** | Write | String | Allow unconfigured sites to be reloaded in Internet Explorer mode (0: Disabled, 1: Enabled) | `0`, `1` | +| **SSLErrorOverrideAllowed** | Write | String | Allow users to proceed from the HTTPS warning page (0: Disabled, 1: Enabled) | `0`, `1` | +| **InternetExplorerIntegrationZoneIdentifierMhtFileAllowed** | Write | String | Automatically open downloaded MHT or MHTML files from the web in Internet Explorer mode (0: Disabled, 1: Enabled) | `0`, `1` | +| **BrowserLegacyExtensionPointsBlockingEnabled** | Write | String | Enable browser legacy extension point blocking (0: Disabled, 1: Enabled) | `0`, `1` | +| **SitePerProcess** | Write | String | Enable site isolation for every site (0: Disabled, 1: Enabled) | `0`, `1` | +| **EdgeEnhanceImagesEnabled** | Write | String | Enhance images enabled (0: Disabled, 1: Enabled) | `0`, `1` | +| **ExtensionInstallBlocklist** | Write | String | Control which extensions cannot be installed (0: Disabled, 1: Enabled) | `0`, `1` | +| **ExtensionInstallBlocklistDesc** | Write | StringArray[] | Extension IDs the user should be prevented from installing (or * for all) (Device) - Depends on ExtensionInstallBlocklist | | +| **WebSQLAccess** | Write | String | Force WebSQL to be enabled (0: Disabled, 1: Enabled) | `0`, `1` | +| **BasicAuthOverHttpEnabled** | Write | String | Allow Basic authentication for HTTP (0: Disabled, 1: Enabled) | `0`, `1` | +| **MicrosoftEdge_HTTPAuthentication_AuthSchemes** | Write | String | Supported authentication schemes (0: Disabled, 1: Enabled) | `0`, `1` | +| **authschemes** | Write | String | Supported authentication schemes (Device) - Depends on MicrosoftEdge_HTTPAuthentication_AuthSchemes | | +| **NativeMessagingUserLevelHosts** | Write | String | Allow user-level native messaging hosts (installed without admin permissions) (0: Disabled, 1: Enabled) | `0`, `1` | +| **InsecurePrivateNetworkRequestsAllowed** | Write | String | Specifies whether to allow insecure websites to make requests to more-private network endpoints (0: Disabled, 1: Enabled) | `0`, `1` | +| **InternetExplorerModeToolbarButtonEnabled** | Write | String | Show the Reload in Internet Explorer mode button in the toolbar (0: Disabled, 1: Enabled) | `0`, `1` | +| **SmartScreenEnabled** | Write | String | Configure Microsoft Defender SmartScreen (0: Disabled, 1: Enabled) | `0`, `1` | +| **SmartScreenPuaEnabled** | Write | String | Configure Microsoft Defender SmartScreen to block potentially unwanted apps (0: Disabled, 1: Enabled) | `0`, `1` | +| **PreventSmartScreenPromptOverride** | Write | String | Prevent bypassing Microsoft Defender SmartScreen prompts for sites (0: Disabled, 1: Enabled) | `0`, `1` | +| **PreventSmartScreenPromptOverrideForFiles** | Write | String | Prevent bypassing of Microsoft Defender SmartScreen warnings about downloads (0: Disabled, 1: Enabled) | `0`, `1` | +| **SharedArrayBufferUnrestrictedAccessAllowed** | Write | String | Specifies whether SharedArrayBuffers can be used in a non cross-origin-isolated context (0: Disabled, 1: Enabled) | `0`, `1` | +| **TyposquattingCheckerEnabled** | Write | String | Configure Edge TyposquattingChecker (0: Disabled, 1: Enabled) | `0`, `1` | +| **Assignments** | Write | MSFT_DeviceManagementConfigurationPolicyAssignments[] | Represents the assignment to the Intune policy. | | +| **Ensure** | Write | String | Present ensures the policy exists, absent ensures it is removed. | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials of the Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **ApplicationSecret** | Write | PSCredential | Secret of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + +### MSFT_DeviceManagementConfigurationPolicyAssignments + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **dataType** | Write | String | The type of the target assignment. | `#microsoft.graph.groupAssignmentTarget`, `#microsoft.graph.allLicensedUsersAssignmentTarget`, `#microsoft.graph.allDevicesAssignmentTarget`, `#microsoft.graph.exclusionGroupAssignmentTarget`, `#microsoft.graph.configurationManagerCollectionAssignmentTarget` | +| **deviceAndAppManagementAssignmentFilterType** | Write | String | The type of filter of the target assignment i.e. Exclude or Include. Possible values are:none, include, exclude. | `none`, `include`, `exclude` | +| **deviceAndAppManagementAssignmentFilterId** | Write | String | The Id of the filter for the target assignment. | | +| **groupId** | Write | String | The group Id that is the target of the assignment. | | +| **groupDisplayName** | Write | String | The group Display Name that is the target of the assignment. | | +| **collectionId** | Write | String | The collection Id that is the target of the assignment.(ConfigMgr) | | + + +## Description + +Intune Security Baseline Microsoft Edge + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - DeviceManagementConfiguration.Read.All + +- **Update** + + - DeviceManagementConfiguration.ReadWrite.All + +#### Application permissions + +- **Read** + + - DeviceManagementConfiguration.Read.All + +- **Update** + + - DeviceManagementConfiguration.ReadWrite.All + +## Examples + +### Example 1 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneSecurityBaselineMicrosoftEdge 'mySecurityBaselineMicrosoftEdge' + { + DisplayName = 'test' + InsecurePrivateNetworkRequestsAllowed = "0"; + InternetExplorerIntegrationReloadInIEModeAllowed = "0"; + InternetExplorerIntegrationZoneIdentifierMhtFileAllowed = "0"; + InternetExplorerModeToolbarButtonEnabled = "0"; + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} +``` + +### Example 2 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneSecurityBaselineMicrosoftEdge 'mySecurityBaselineMicrosoftEdge' + { + DisplayName = 'test' + InsecurePrivateNetworkRequestsAllowed = "0"; + InternetExplorerIntegrationReloadInIEModeAllowed = "0"; + InternetExplorerIntegrationZoneIdentifierMhtFileAllowed = "0"; + InternetExplorerModeToolbarButtonEnabled = "1"; # Drift + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} +``` + +### Example 3 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneSecurityBaselineMicrosoftEdge 'mySecurityBaselineMicrosoftEdge' + { + DisplayName = 'test' + Ensure = 'Absent' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} +``` + From 875d79906db5f611abf05bc9a4adfeb9859adfff Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 16 Oct 2024 14:40:03 +0000 Subject: [PATCH 237/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 175 ++++++++++++++++++ 1 file changed, 175 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 0140e55ccc..3cf451f038 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -38614,6 +38614,181 @@ } ] }, + { + "ClassName": "MSFT_IntuneSecurityBaselineMicrosoftEdge", + "Parameters": [ + { + "CIMType": "String", + "Name": "Description", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Key" + }, + { + "CIMType": "String[]", + "Name": "RoleScopeTagIds", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Id", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "InternetExplorerIntegrationReloadInIEModeAllowed", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "SSLErrorOverrideAllowed", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "InternetExplorerIntegrationZoneIdentifierMhtFileAllowed", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "BrowserLegacyExtensionPointsBlockingEnabled", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "SitePerProcess", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "EdgeEnhanceImagesEnabled", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ExtensionInstallBlocklist", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "ExtensionInstallBlocklistDesc", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "WebSQLAccess", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "BasicAuthOverHttpEnabled", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MicrosoftEdge_HTTPAuthentication_AuthSchemes", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "authschemes", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "NativeMessagingUserLevelHosts", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "InsecurePrivateNetworkRequestsAllowed", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "InternetExplorerModeToolbarButtonEnabled", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "SmartScreenEnabled", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "SmartScreenPuaEnabled", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PreventSmartScreenPromptOverride", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PreventSmartScreenPromptOverrideForFiles", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "SharedArrayBufferUnrestrictedAccessAllowed", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TyposquattingCheckerEnabled", + "Option": "Write" + }, + { + "CIMType": "MSFT_DeviceManagementConfigurationPolicyAssignments[]", + "Name": "Assignments", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "ApplicationSecret", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_IntuneSettingCatalogASRRulesPolicyWindows10", "Parameters": [ From 5158539bf7a923154a253d83bd8d6b0fe4a65c6f Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 16 Oct 2024 14:40:19 +0000 Subject: [PATCH 238/252] Updated {Create} Intune Integration Tests --- .../M365DSCIntegration.INTUNE.Create.Tests.ps1 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 index c8d9f4947c..d85c0e2b0c 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 @@ -2663,6 +2663,18 @@ TenantId = $TenantId; CertificateThumbprint = $CertificateThumbprint; } + IntuneSecurityBaselineMicrosoftEdge 'mySecurityBaselineMicrosoftEdge' + { + DisplayName = 'test' + InsecurePrivateNetworkRequestsAllowed = "0"; + InternetExplorerIntegrationReloadInIEModeAllowed = "0"; + InternetExplorerIntegrationZoneIdentifierMhtFileAllowed = "0"; + InternetExplorerModeToolbarButtonEnabled = "0"; + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } IntuneSettingCatalogASRRulesPolicyWindows10 'myASRRulesPolicy' { DisplayName = 'asr 2' From 2e7bc1594636c80e91091b138dc5a9c4836688b3 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 16 Oct 2024 18:22:50 +0000 Subject: [PATCH 239/252] Updated Resources and Cmdlet documentation pages --- .../IntuneMobileAppsWindowsOfficeSuiteApp.md | 276 ++++++++++++++++++ 1 file changed, 276 insertions(+) create mode 100644 docs/docs/resources/intune/IntuneMobileAppsWindowsOfficeSuiteApp.md diff --git a/docs/docs/resources/intune/IntuneMobileAppsWindowsOfficeSuiteApp.md b/docs/docs/resources/intune/IntuneMobileAppsWindowsOfficeSuiteApp.md new file mode 100644 index 0000000000..52bfea559e --- /dev/null +++ b/docs/docs/resources/intune/IntuneMobileAppsWindowsOfficeSuiteApp.md @@ -0,0 +1,276 @@ +# IntuneMobileAppsWindowsOfficeSuiteApp + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **DisplayName** | Key | String | The admin provided or imported title of the app. Inherited from mobileApp. | | +| **Id** | Write | String | The unique identifier for an entity. Read-only. Inherited from mobileApp object. | | +| **Description** | Write | String | The description of the app. Inherited from mobileApp. | | +| **IsFeatured** | Write | Boolean | The value indicating whether the app is marked as featured by the admin. Inherited from mobileApp. | | +| **PrivacyInformationUrl** | Write | String | The privacy statement Url. Inherited from mobileApp. | | +| **InformationUrl** | Write | String | The InformationUrl of the app. Inherited from mobileApp. | | +| **Notes** | Write | String | Notes for the app. Inherited from mobileApp. | | +| **RoleScopeTagIds** | Write | StringArray[] | List of Scope Tag IDs for mobile app. | | +| **AutoAcceptEula** | Write | Boolean | Specifies if the EULA is accepted automatically on the end user's device. | | +| **ProductIds** | Write | StringArray[] | The Product IDs that represent the Office 365 Suite SKU, such as 'O365ProPlusRetail' or 'VisioProRetail'. | | +| **UseSharedComputerActivation** | Write | Boolean | Indicates whether shared computer activation is used for Office installations. | | +| **UpdateChannel** | Write | String | Specifies the update channel for the Office 365 app suite, such as 'Current' or 'Deferred'. | | +| **OfficeSuiteAppDefaultFileFormat** | Write | String | Specifies the default file format type for Office apps, such as 'OfficeOpenXMLFormat' or 'OfficeOpenDocumentFormat'. | | +| **OfficePlatformArchitecture** | Write | String | The architecture of the Office installation (e.g., 'X86', 'X64', or 'Arm64'). Cannot be changed after creation. | | +| **LocalesToInstall** | Write | StringArray[] | Specifies the locales to be installed when the Office 365 apps are deployed. Uses the standard RFC 5646 format (e.g., 'en-US', 'fr-FR'). | | +| **InstallProgressDisplayLevel** | Write | String | Specifies the display level of the installation progress for Office apps. Use 'Full' to display the installation UI, or 'None' for a silent installation. | | +| **ShouldUninstallOlderVersionsOfOffice** | Write | Boolean | Indicates whether older versions of Office should be uninstalled when deploying the Office 365 app suite. | | +| **TargetVersion** | Write | String | The specific target version of the Office 365 app suite to be deployed. | | +| **UpdateVersion** | Write | String | The update version in which the target version is available for the Office 365 app suite. | | +| **OfficeConfigurationXml** | Write | String | A base64-encoded XML configuration file that specifies Office ProPlus installation settings. Takes precedence over all other properties. When present, this XML file will be used to create the app. | | +| **Categories** | Write | MSFT_DeviceManagementMobileAppCategory[] | The list of categories for this app. | | +| **Assignments** | Write | MSFT_DeviceManagementMobileAppAssignment[] | The list of assignments for this app. | | +| **ExcludedApps** | Write | MSFT_DeviceManagementMobileAppExcludedApp | The property that represents the apps excluded from the selected Office 365 Product ID. | | +| **Ensure** | Write | String | Present ensures the policy exists, absent ensures it is removed. | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials of the Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **ApplicationSecret** | Write | PSCredential | Secret of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + +### MSFT_DeviceManagementMobileAppAssignment + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **dataType** | Write | String | The type of the target assignment. | `#microsoft.graph.groupAssignmentTarget`, `#microsoft.graph.allLicensedUsersAssignmentTarget`, `#microsoft.graph.allDevicesAssignmentTarget`, `#microsoft.graph.exclusionGroupAssignmentTarget`, `#microsoft.graph.mobileAppAssignment` | +| **deviceAndAppManagementAssignmentFilterId** | Write | String | The Id of the filter for the target assignment. | | +| **deviceAndAppManagementAssignmentFilterType** | Write | String | The type of filter of the target assignment i.e. Exclude or Include. Possible values are: none, include, exclude. | `none`, `include`, `exclude` | +| **groupId** | Write | String | The group Id that is the target of the assignment. | | +| **groupDisplayName** | Write | String | The group Display Name that is the target of the assignment. | | +| **intent** | Write | String | Possible values for the install intent chosen by the admin. | `available`, `required`, `uninstall`, `availableWithoutEnrollment` | + +### MSFT_DeviceManagementMimeContent + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Type** | Write | String | Indicates the type of content mime. | | +| **Value** | Write | String | The Base64 encoded string content. | | + +### MSFT_DeviceManagementMobileAppCategory + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **DisplayName** | Key | String | The name of the app category. | | +| **Id** | Write | String | The unique identifier for an entity. Read-only. | | + +### MSFT_DeviceManagementMobileAppExcludedApp + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Access** | Write | Boolean | Specifies whether to exclude Microsoft Office Access from the installation. | | +| **Bing** | Write | Boolean | Specifies whether to exclude Microsoft Search (Bing) as the default from the installation. | | +| **Excel** | Write | Boolean | Specifies whether to exclude Microsoft Office Excel from the installation. | | +| **Groove** | Write | Boolean | Specifies whether to exclude Microsoft Office OneDrive for Business (Groove) from the installation. | | +| **InfoPath** | Write | Boolean | Specifies whether to exclude Microsoft Office InfoPath from the installation. | | +| **Lync** | Write | Boolean | Specifies whether to exclude Microsoft Office Skype for Business (Lync) from the installation. | | +| **OneDrive** | Write | Boolean | Specifies whether to exclude Microsoft Office OneDrive from the installation. | | +| **OneNote** | Write | Boolean | Specifies whether to exclude Microsoft Office OneNote from the installation. | | +| **Outlook** | Write | Boolean | Specifies whether to exclude Microsoft Office Outlook from the installation. | | +| **PowerPoint** | Write | Boolean | Specifies whether to exclude Microsoft Office PowerPoint from the installation. | | +| **Publisher** | Write | Boolean | Specifies whether to exclude Microsoft Office Publisher from the installation. | | +| **SharePointDesigner** | Write | Boolean | Specifies whether to exclude Microsoft Office SharePoint Designer from the installation. | | +| **Teams** | Write | Boolean | Specifies whether to exclude Microsoft Office Teams from the installation. | | +| **Visio** | Write | Boolean | Specifies whether to exclude Microsoft Office Visio from the installation. | | +| **Word** | Write | Boolean | Specifies whether to exclude Microsoft Office Word from the installation. | | + + +## Description + +This resource configures an Intune mobile app of OfficeSuiteApp type for Windows devices. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - DeviceManagementApps.Read.All + +- **Update** + + - DeviceManagementApps.ReadWrite.All + +#### Application permissions + +- **Read** + + - DeviceManagementApps.Read.All + +- **Update** + + - DeviceManagementApps.ReadWrite.All + +## Examples + +### Example 1 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + IntuneMobileAppsWindowsOfficeSuiteApp "IntuneMobileAppsWindowsOfficeSuiteApp-Microsoft 365 Apps for Windows 10 and later" + { + Id = "8e683524-4ec1-4813-bb3e-6256b2f293d" + Description = "Microsoft 365 Apps for Windows 10 and laterr" + DisplayName = "Microsoft 365 Apps for Windows 10 and later" + Ensure = "Present"; + InformationUrl = ""; + IsFeatured = $False; + Notes = "" + PrivacyInformationUrl = "" + RoleScopeTagIds = @() + Assignments = @( + MSFT_DeviceManagementMobileAppAssignment{ + deviceAndAppManagementAssignmentFilterType = 'none' + dataType = '#microsoft.graph.groupAssignmentTarget' + groupId = '42c02b60-f28c-4eef-b3e1-973184cc4a6c' + intent = 'required' + } + ); + Categories = @( + MSFT_DeviceManagementMobileAppCategory { + Id = '8e683524-4ec1-4813-bb3e-6256b2f293d8' + DisplayName = 'Productivity' + }); + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} +``` + +### Example 2 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + IntuneMobileAppsWindowsOfficeSuiteApp "IntuneMobileAppsWindowsOfficeSuiteApp-Microsoft 365 Apps for Windows 10 and later" + { + Id = "8e683524-4ec1-4813-bb3e-6256b2f293d" + Description = "Microsoft 365 Apps for Windows 10 and laterr" + DisplayName = "Microsoft 365 Apps for Windows 10 and later" + Ensure = "Present"; + InformationUrl = ""; + IsFeatured = $False; + Notes = "" + PrivacyInformationUrl = "" + RoleScopeTagIds = @() + Assignments = @( + MSFT_DeviceManagementMobileAppAssignment{ + deviceAndAppManagementAssignmentFilterType = 'none' + dataType = '#microsoft.graph.groupAssignmentTarget' + groupId = '42c02b60-f28c-4eef-b3e1-973184cc4a6c' + intent = 'required' + } + ); + Categories = @( + MSFT_DeviceManagementMobileAppCategory { + Id = '8e683524-4ec1-4813-bb3e-6256b2f293d8' + DisplayName = 'Productivity' + }); + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} +``` + +### Example 3 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + IntuneMobileAppsWindowsOfficeSuiteApp "IntuneMobileAppsWindowsOfficeSuiteApp-Microsoft 365 Apps for Windows 10 and later" + { + Id = "8e683524-4ec1-4813-bb3e-6256b2f293d8"; + DisplayName = "Microsoft 365 Apps for Windows 10 and later"; + Ensure = "Absent"; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} +``` + From cbbd937786d5e863fac62887314001546221d47a Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 16 Oct 2024 18:25:41 +0000 Subject: [PATCH 240/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 240 ++++++++++++++++++ 1 file changed, 240 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 3cf451f038..529afc18db 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -36054,6 +36054,246 @@ } ] }, + { + "ClassName": "MSFT_DeviceManagementMobileAppExcludedApp", + "Parameters": [ + { + "CIMType": "Boolean", + "Name": "Access", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "Bing", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "Excel", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "Groove", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "InfoPath", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "Lync", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "OneDrive", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "OneNote", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "Outlook", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "PowerPoint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "Publisher", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SharePointDesigner", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "Teams", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "Visio", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "Word", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_IntuneMobileAppsWindowsOfficeSuiteApp", + "Parameters": [ + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "Id", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Description", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "IsFeatured", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PrivacyInformationUrl", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "InformationUrl", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Notes", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "RoleScopeTagIds", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AutoAcceptEula", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "ProductIds", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "UseSharedComputerActivation", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "UpdateChannel", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "OfficeSuiteAppDefaultFileFormat", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "OfficePlatformArchitecture", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "LocalesToInstall", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "InstallProgressDisplayLevel", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ShouldUninstallOlderVersionsOfOffice", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TargetVersion", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "UpdateVersion", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "OfficeConfigurationXml", + "Option": "Write" + }, + { + "CIMType": "MSFT_DeviceManagementMobileAppCategory[]", + "Name": "Categories", + "Option": "Write" + }, + { + "CIMType": "MSFT_DeviceManagementMobileAppAssignment[]", + "Name": "Assignments", + "Option": "Write" + }, + { + "CIMType": "MSFT_DeviceManagementMobileAppExcludedApp", + "Name": "ExcludedApps", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "ApplicationSecret", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_DeviceManagementConfigurationPolicyItems", "Parameters": [ From aa56db65caffa1dbd17581432a871bd50014a1f6 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 16 Oct 2024 18:26:21 +0000 Subject: [PATCH 241/252] Updated {Create} Intune Integration Tests --- ...M365DSCIntegration.INTUNE.Create.Tests.ps1 | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 index d85c0e2b0c..368146fdd0 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 @@ -2570,6 +2570,34 @@ DisplayName = 'Kajal 3' }); } + IntuneMobileAppsWindowsOfficeSuiteApp 'IntuneMobileAppsWindowsOfficeSuiteApp-Microsoft 365 Apps for Windows 10 and later' + { + Id = "8e683524-4ec1-4813-bb3e-6256b2f293d" + Description = "Microsoft 365 Apps for Windows 10 and laterr" + DisplayName = "Microsoft 365 Apps for Windows 10 and later" + Ensure = "Present"; + InformationUrl = ""; + IsFeatured = $False; + Notes = "" + PrivacyInformationUrl = "" + RoleScopeTagIds = @() + Assignments = @( + MSFT_DeviceManagementMobileAppAssignment{ + deviceAndAppManagementAssignmentFilterType = 'none' + dataType = '#microsoft.graph.groupAssignmentTarget' + groupId = '42c02b60-f28c-4eef-b3e1-973184cc4a6c' + intent = 'required' + } + ); + Categories = @( + MSFT_DeviceManagementMobileAppCategory { + Id = '8e683524-4ec1-4813-bb3e-6256b2f293d8' + DisplayName = 'Productivity' + }); + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } IntunePolicySets 'Example' { Assignments = @( From f781291230d9ed24236f150340c103c612342185 Mon Sep 17 00:00:00 2001 From: Maarten Piederiet Date: Wed, 16 Oct 2024 21:03:38 +0200 Subject: [PATCH 242/252] Updated changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe3a0e3046..3b875ee48e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,10 @@ * Initial release. * PPPowerAppPolicyUrlPatterns * Initial release. +* TeamsClientConfiguration + * Fixed bug where RestrictedSenderList was always empty in the MSFT_TeamsClientConfiguration resource + FIXES [#5190](https://github.com/microsoft/Microsoft365DSC/issues/5190) + * Changed Set-TargetResource to always use semicolon as separator as mentioned in the MS documentation * TeamsUpgradePolicy * Added support for tenant wide changes using the * value for users. FIXES [#5174](https://github.com/microsoft/Microsoft365DSC/issues/5174) From 51bf700c0befcc3ae9b69aa3bc98374e09bb817a Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 16 Oct 2024 16:25:34 -0400 Subject: [PATCH 243/252] Fixes --- CHANGELOG.md | 5 +++-- .../MSFT_AADApplication/MSFT_AADApplication.psm1 | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b479d5275..137fbe5e0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,14 +2,13 @@ # UNRELEASED -* IntuneDerivedCredential - * Initial release. * AADAdminConsentRequestPolicy * Initial release. * AADApplication * Fixed an issue trying to retrieve the beta instance. * Added support for OnPremisesPublishing. * Added support for ApplicationTemplate. + * Fixes an issue with granting the permissions. * AADAuthenticationRequirement * Initial release. * AADConnectorGroupApplicationProxy @@ -38,6 +37,8 @@ * IntuneAppAndBrowserIsolationPolicyWindows10 * Initial release. FIXES [#3028](https://github.com/microsoft/Microsoft365DSC/issues/3028) +* IntuneDerivedCredential + * Initial release. * IntuneDeviceConfigurationIdentityProtectionPolicyWindows10 * Added deprecation notice. * IntuneEndpointDetectionAndResponsePolicyWindows10 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index 4b4c6f68e7..c8e33c5291 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -971,7 +971,7 @@ function Set-TargetResource if ($needToUpdatePermissions -and -not [System.String]::IsNullOrEmpty($Permissions) -and $Permissions.Length -gt 0) { Write-Verbose -Message "Will update permissions for Azure AD Application {$($currentAADApp.DisplayName)}" - $allSourceAPIs = $Permissions.SourceAPI | Get-Unique + $allSourceAPIs = $Permissions.SourceAPI | Select-Object -Unique $allRequiredAccess = @() foreach ($sourceAPI in $allSourceAPIs) From 83005c5851e4a0ad9e47285b7e6ab49eef587cc3 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 16 Oct 2024 16:26:58 -0400 Subject: [PATCH 244/252] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 137fbe5e0d..fcb0d7002c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,8 @@ * Fixed an issue trying to retrieve the beta instance. * Added support for OnPremisesPublishing. * Added support for ApplicationTemplate. - * Fixes an issue with granting the permissions. + * Fixes an issue where trying to apply permissions complained about + duplicate entries. * AADAuthenticationRequirement * Initial release. * AADConnectorGroupApplicationProxy From 42b99a30c04a560c9c4f403eba10dc16aa965b7f Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Thu, 17 Oct 2024 02:20:51 +0530 Subject: [PATCH 245/252] adding delegated permission classification property --- .../MSFT_AADServicePrincipal.psm1 | 179 ++++++++++++++---- .../MSFT_AADServicePrincipal.schema.mof | 9 + 2 files changed, 156 insertions(+), 32 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADServicePrincipal/MSFT_AADServicePrincipal.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADServicePrincipal/MSFT_AADServicePrincipal.psm1 index a32fd0d623..5640892910 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADServicePrincipal/MSFT_AADServicePrincipal.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADServicePrincipal/MSFT_AADServicePrincipal.psm1 @@ -32,6 +32,10 @@ function Get-TargetResource [System.Boolean] $AppRoleAssignmentRequired, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $DelegatedPermissionClassifications, + [Parameter()] [System.String] $ErrorUrl, @@ -212,32 +216,43 @@ function Get-TargetResource } } + [Array]$complexDelegatedPermissionClassifications = @() + $permissionClassifications = Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/servicePrincipals(appId='$AppId')/delegatedPermissionClassifications" -Method Get + foreach ($permissionClassification in $permissionClassifications.Value){ + $hashtable = @{ + classification = $permissionClassification.Classification + permissionName = $permissionClassification.permissionName + } + $complexDelegatedPermissionClassifications += $hashtable + } + $result = @{ - AppId = $AADServicePrincipal.AppId - AppRoleAssignedTo = $AppRoleAssignedToValues - ObjectID = $AADServicePrincipal.Id - DisplayName = $AADServicePrincipal.DisplayName - AlternativeNames = $AADServicePrincipal.AlternativeNames - AccountEnabled = [boolean]$AADServicePrincipal.AccountEnabled - AppRoleAssignmentRequired = $AADServicePrincipal.AppRoleAssignmentRequired - ErrorUrl = $AADServicePrincipal.ErrorUrl - Homepage = $AADServicePrincipal.Homepage - LogoutUrl = $AADServicePrincipal.LogoutUrl - Owners = $ownersValues - PublisherName = $AADServicePrincipal.PublisherName - ReplyURLs = $AADServicePrincipal.ReplyURLs - SamlMetadataURL = $AADServicePrincipal.SamlMetadataURL - ServicePrincipalNames = $AADServicePrincipal.ServicePrincipalNames - ServicePrincipalType = $AADServicePrincipal.ServicePrincipalType - Tags = $AADServicePrincipal.Tags - Ensure = 'Present' - Credential = $Credential - ApplicationId = $ApplicationId - ApplicationSecret = $ApplicationSecret - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - Managedidentity = $ManagedIdentity.IsPresent - AccessTokens = $AccessTokens + AppId = $AADServicePrincipal.AppId + AppRoleAssignedTo = $AppRoleAssignedToValues + ObjectID = $AADServicePrincipal.Id + DisplayName = $AADServicePrincipal.DisplayName + AlternativeNames = $AADServicePrincipal.AlternativeNames + AccountEnabled = [boolean]$AADServicePrincipal.AccountEnabled + AppRoleAssignmentRequired = $AADServicePrincipal.AppRoleAssignmentRequired + DelegatedPermissionClassifications = [Array]$complexDelegatedPermissionClassifications + ErrorUrl = $AADServicePrincipal.ErrorUrl + Homepage = $AADServicePrincipal.Homepage + LogoutUrl = $AADServicePrincipal.LogoutUrl + Owners = $ownersValues + PublisherName = $AADServicePrincipal.PublisherName + ReplyURLs = $AADServicePrincipal.ReplyURLs + SamlMetadataURL = $AADServicePrincipal.SamlMetadataURL + ServicePrincipalNames = $AADServicePrincipal.ServicePrincipalNames + ServicePrincipalType = $AADServicePrincipal.ServicePrincipalType + Tags = $AADServicePrincipal.Tags + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + ApplicationSecret = $ApplicationSecret + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Managedidentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens } Write-Verbose -Message "Get-TargetResource Result: `n $(Convert-M365DscHashtableToString -Hashtable $result)" return $result @@ -289,6 +304,10 @@ function Set-TargetResource [System.Boolean] $AppRoleAssignmentRequired, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $DelegatedPermissionClassifications, + [Parameter()] [System.String] $ErrorUrl, @@ -398,6 +417,8 @@ function Set-TargetResource { $currentParameters.AppRoleAssignedTo = $AppRoleAssignedToValue } + # removing Delegated permission classifications from this new call, as adding below separately + $currentParameters.Remove('DelegatedPermissionClassifications') | Out-Null $ObjectGuid = [System.Guid]::empty if (-not [System.Guid]::TryParse($AppId, [System.Management.Automation.PSReference]$ObjectGuid)) { @@ -419,6 +440,17 @@ function Set-TargetResource Write-Verbose -Message "Adding new owner {$owner}" $newOwner = New-MgServicePrincipalOwnerByRef -ServicePrincipalId $newSP.Id -BodyParameter $body } + + #adding delegated permissions classifications + if($null -ne $DelegatedPermissionClassifications){ + foreach ($permissionClassification in $DelegatedPermissionClassifications){ + $params = @{ + classification = $permissionClassification.Classification + permissionName = $permissionClassification.permissionName + } + Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/servicePrincipals(appId='$($currentParameters.AppId)')/delegatedPermissionClassifications" -Method Post -Body $params + } + } } # ServicePrincipal should exist and will be configured to desired state elseif ($Ensure -eq 'Present' -and $currentAADServicePrincipal.Ensure -eq 'Present') @@ -434,6 +466,7 @@ function Set-TargetResource Write-Verbose -Message "ServicePrincipalID: $($currentAADServicePrincipal.ObjectID)" $currentParameters.Remove('AppRoleAssignedTo') | Out-Null $currentParameters.Remove('Owners') | Out-Null + $currentParameters.Remove('DelegatedPermissionClassifications') | Out-Null Update-MgServicePrincipal -ServicePrincipalId $currentAADServicePrincipal.ObjectID @currentParameters if ($AppRoleAssignedTo) @@ -546,6 +579,26 @@ function Set-TargetResource -DirectoryObjectId $userInfo.Id | Out-Null } } + + Write-Verbose -Message "Checking if DelegatedPermissionClassifications need to be updated..." + + if ($null -ne $DelegatedPermissionClassifications) + { + # removing old perm classifications + $permissionClassificationList = Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/servicePrincipals(appId='$($currentParameters.AppId)')/delegatedPermissionClassifications" -Method Get + foreach($permissionClassification in $permissionClassificationList.Value){ + Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/servicePrincipals(appId='$($currentParameters.AppId)')/delegatedPermissionClassifications/$($permissionClassification.Id)" -Method Delete + } + + # adding new perm classifications + foreach ($permissionClassification in $DelegatedPermissionClassifications){ + $params = @{ + classification = $permissionClassification.Classification + permissionName = $permissionClassification.permissionName + } + Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/servicePrincipals(appId='$($currentParameters.AppId)')/delegatedPermissionClassifications" -Method Post -Body $params + } + } } # ServicePrincipal exists but should not elseif ($Ensure -eq 'Absent' -and $currentAADServicePrincipal.Ensure -eq 'Present') @@ -589,6 +642,10 @@ function Test-TargetResource [System.Boolean] $AppRoleAssignmentRequired, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $DelegatedPermissionClassifications, + [Parameter()] [System.String] $ErrorUrl, @@ -677,21 +734,48 @@ function Test-TargetResource Write-Verbose -Message 'Testing configuration of Azure AD ServicePrincipal' + $testTargetResource = $true $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + #Compare Cim instances + foreach ($key in $PSBoundParameters.Keys) + { + $source = $PSBoundParameters.$key + $target = $CurrentValues.$key + if ($null -ne $source -and $source.GetType().Name -like '*CimInstance*') + { + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + if (-not $testResult) + { + $testTargetResource = $false + } + else { + $ValuesToCheck.Remove($key) | Out-Null + } + } + } Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" - $ValuesToCheck = $PSBoundParameters - $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` - -Source $($MyInvocation.MyCommand.Source) ` - -DesiredValues $PSBoundParameters ` - -ValuesToCheck $ValuesToCheck.Keys + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys ` + -IncludedDrifts $driftedParams + + if(-not $TestResult) + { + $testTargetResource = $false + } - Write-Verbose -Message "Test-TargetResource returned $TestResult" + Write-Verbose -Message "Test-TargetResource returned $testTargetResource" - return $TestResult + return $testTargetResource } function Export-TargetResource @@ -785,6 +869,10 @@ function Export-TargetResource { $Results.AppRoleAssignedTo = Get-M365DSCAzureADServicePrincipalAssignmentAsString -Assignments $Results.AppRoleAssignedTo } + if ($Results.DelegatedPermissionClassifications.Count -gt 0) + { + $Results.DelegatedPermissionClassifications = Get-M365DSCAzureADServicePrincipalDelegatedPermissionClassifications -PermissionClassifications $Results.DelegatedPermissionClassifications + } $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` -ConnectionMode $ConnectionMode ` -ModulePath $PSScriptRoot ` @@ -795,6 +883,11 @@ function Export-TargetResource $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock ` -ParameterName 'AppRoleAssignedTo' } + if ($null -ne $Results.DelegatedPermissionClassifications) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock ` + -ParameterName 'DelegatedPermissionClassifications' + } $dscContent += $currentDSCBlock Save-M365DSCPartialExport -Content $currentDSCBlock ` -FileName $Global:PartialExportFileName @@ -841,4 +934,26 @@ function Get-M365DSCAzureADServicePrincipalAssignmentAsString return $StringContent } +function Get-M365DSCAzureADServicePrincipalDelegatedPermissionClassifications +{ + [CmdletBinding()] + [OutputType([System.String])] + param( + [Parameter(Mandatory = $true)] + [System.Collections.ArrayList] + $PermissionClassifications + ) + + $StringContent = "@(`r`n" + foreach ($permissionClassification in $PermissionClassifications) + { + $StringContent += " MSFT_AADServicePrincipalDelegatedPermissionClassification {`r`n" + $StringContent += " Classification = '" + $PermissionClassification.Classification + "'`r`n" + $StringContent += " PermissionName = '" + $PermissionClassification.PermissionName + "'`r`n" + $StringContent += " }`r`n" + } + $StringContent += ' )' + return $StringContent +} + Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADServicePrincipal/MSFT_AADServicePrincipal.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADServicePrincipal/MSFT_AADServicePrincipal.schema.mof index 3d4c507c12..717b2e569f 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADServicePrincipal/MSFT_AADServicePrincipal.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADServicePrincipal/MSFT_AADServicePrincipal.schema.mof @@ -5,6 +5,13 @@ class MSFT_AADServicePrincipalRoleAssignment [Write, Description("Unique identity representing the principal.")] String Identity; }; +[ClassVersion("1.0.0")] +class MSFT_AADServicePrincipalDelegatedPermissionClassification +{ + [Write, Description("Classification of the delegated permission"), ValueMap{"low", "medium", "high"}, Values{"low", "medium", "high"}] String Classification; + [Write, Description("Name of the permission")] String PermissionName; +}; + [ClassVersion("1.0.0.0"), FriendlyName("AADServicePrincipal")] class MSFT_AADServicePrincipal : OMI_BaseResource { @@ -25,6 +32,8 @@ class MSFT_AADServicePrincipal : OMI_BaseResource [Write, Description("Specifies an array of service principal names. Based on the identifierURIs collection, plus the application's appId property, these URIs are used to reference an application's service principal.")] String ServicePrincipalNames[]; [Write, Description("The type of the service principal.")] String ServicePrincipalType; [Write, Description("Tags linked to this service principal.Note that if you intend for this service principal to show up in the All Applications list in the admin portal, you need to set this value to {WindowsAzureActiveDirectoryIntegratedApp}")] String Tags[]; + [Write, Description("The permission classifications for delegated permissions exposed by the app that this service principal represents."), EmbeddedInstance("MSFT_AADServicePrincipalDelegatedPermissionClassification")] String DelegatedPermissionClassifications[]; + [Write, Description("Specify if the Azure AD App should exist or not."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; From 095db5a1db88e52d6693e06ad8cbb4e2fc965093 Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Thu, 17 Oct 2024 02:24:29 +0530 Subject: [PATCH 246/252] modifying changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3a64fe812..fa88db2789 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,8 @@ * Initial release. * AADLifecycleWorkflowSettings * Initial release. +* AADServicePrincipal + * Adding Delegated Permission Classification Property * ADOPermissionGroupSettings * Initial release. * EXOATPBuiltInProtectionRule From bd6611057da452cd7324a9eda1539cff30011a1b Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 16 Oct 2024 22:13:50 +0000 Subject: [PATCH 247/252] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/azure-ad/AADServicePrincipal.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/docs/resources/azure-ad/AADServicePrincipal.md b/docs/docs/resources/azure-ad/AADServicePrincipal.md index 8e360204df..fc48241314 100644 --- a/docs/docs/resources/azure-ad/AADServicePrincipal.md +++ b/docs/docs/resources/azure-ad/AADServicePrincipal.md @@ -21,6 +21,7 @@ | **ServicePrincipalNames** | Write | StringArray[] | Specifies an array of service principal names. Based on the identifierURIs collection, plus the application's appId property, these URIs are used to reference an application's service principal. | | | **ServicePrincipalType** | Write | String | The type of the service principal. | | | **Tags** | Write | StringArray[] | Tags linked to this service principal.Note that if you intend for this service principal to show up in the All Applications list in the admin portal, you need to set this value to {WindowsAzureActiveDirectoryIntegratedApp} | | +| **DelegatedPermissionClassifications** | Write | MSFT_AADServicePrincipalDelegatedPermissionClassification[] | The permission classifications for delegated permissions exposed by the app that this service principal represents. | | | **Ensure** | Write | String | Specify if the Azure AD App should exist or not. | `Present`, `Absent` | | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | @@ -39,6 +40,15 @@ | **PrincipalType** | Write | String | Type of principal. Accepted values are User or Group | `Group`, `User` | | **Identity** | Write | String | Unique identity representing the principal. | | +### MSFT_AADServicePrincipalDelegatedPermissionClassification + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Classification** | Write | String | Classification of the delegated permission | `low`, `medium`, `high` | +| **PermissionName** | Write | String | Name of the permission | | + ## Description This resource configures an Azure Active Directory ServicePrincipal. From d32e11bb0cad5f7d5ddce3a8c087595bc43828b4 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 16 Oct 2024 22:16:52 +0000 Subject: [PATCH 248/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 529afc18db..a592c2b6d5 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -6024,6 +6024,21 @@ } ] }, + { + "ClassName": "MSFT_AADServicePrincipalDelegatedPermissionClassification", + "Parameters": [ + { + "CIMType": "String", + "Name": "Classification", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PermissionName", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_AADServicePrincipal", "Parameters": [ @@ -6112,6 +6127,11 @@ "Name": "Tags", "Option": "Write" }, + { + "CIMType": "MSFT_AADServicePrincipalDelegatedPermissionClassification[]", + "Name": "DelegatedPermissionClassifications", + "Option": "Write" + }, { "CIMType": "String", "Name": "Ensure", From 7dfddc2499923a77272869fd5fc8bc6987fc87eb Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 17 Oct 2024 10:49:35 -0400 Subject: [PATCH 249/252] Release Candidate for 1.24.1016.1 --- CHANGELOG.md | 2 +- Modules/Microsoft365DSC/Microsoft365DSC.psd1 | 175 +++++++------------ 2 files changed, 64 insertions(+), 113 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5eeb43cba..c4ed21867f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Change log for Microsoft365DSC -# UNRELEASED +# 1.24.1016.1 * AADAdminConsentRequestPolicy * Initial release. diff --git a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 index 68bd75c4a8..4cab0e3be0 100644 --- a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 +++ b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 @@ -3,7 +3,7 @@ # # Generated by: Microsoft Corporation # -# Generated on: 2024-10-02 +# Generated on: 2024-10-16 @{ @@ -11,7 +11,7 @@ # RootModule = '' # Version number of this module. - ModuleVersion = '1.24.1002.1' + ModuleVersion = '1.24.1016.1' # Supported PSEditions # CompatiblePSEditions = @() @@ -144,131 +144,82 @@ IconUri = 'https://github.com/microsoft/Microsoft365DSC/blob/Dev/Modules/Microsoft365DSC/Dependencies/Images/Logo.png?raw=true' # ReleaseNotes of this module - ReleaseNotes = '* AADApplication - * Added AppRoles - * Added AuthenticationBehavior - * Added KeyCredentials - * Added OptionalClaims - * Added PasswordCredentials - * Added PreAuthorizationApplications -* AADAuthenticationMethodPolicy - * Added ReportSuspiciousActivitySettings -* AADAuthenticationMethodPolicyHardware + ReleaseNotes = '* AADAdminConsentRequestPolicy * Initial release. -* AADEntitlementManagementSettings - * Initial release. -* AADFeatureRolloutPolicy - * Initial release -* AADGroup - * Fixes logic to evaluate license assignments and disabled plans. - FIXES [#5101](https://github.com/microsoft/Microsoft365DSC/issues/5101) - * Adds support to assign Service Principal as members or owners. - FIXES [#4972](https://github.com/microsoft/Microsoft365DSC/issues/4972) -* AADPasswordRuleSettings - * Initial release -* ADOOrganizationOwner +* AADApplication + * Fixed an issue trying to retrieve the beta instance. + * Added support for OnPremisesPublishing. + * Added support for ApplicationTemplate. + * Fixes an issue where trying to apply permissions complained about + duplicate entries. +* AADAuthenticationRequirement * Initial release. -* ADOPermissionGroup +* AADConnectorGroupApplicationProxy * Initial release. -* ADOSecurityPolicy +* AADCustomSecurityAttributeDefinition * Initial release. -* AzureSubscription - * Initial Release. -* DefenderSubscriptionDefenderPlan +* AADDeviceRegistrationPolicy * Initial release. -* EXOAntiPhishPolicy - * Use correct type integer for variable `PhishThresholdLevel` -* EXOArcConfig - * Initial Release. -* EXODnssecForVerifiedDomain - * Initial Release. -* EXOEmailTenantSettings - * Initial Release. -* EXOFocusedInbox - * Initial Release. -* EXOMailboxCalendarConfiguration - * Initial Release. -* EXOMailboxIRMAccess - * Initial Release. -* EXOMailboxFolderPermission - * Initial Release. -* EXOMailboxIRMAccess - * Initial Release. -* EXOMailTips - * Remove property `Ensure` since this resource is of type `IsSingleInstance` -* EXOManagementScope - * Initial Release. -* EXORetentionPolicy - * Initial Release. -* EXOPhishSimOverrideRule - * Initial Release. -* IntuneAntivirusPolicyWindows10SettingCatalog - * Fixes an issue with invalid parameter definition. - FIXES [#5015](https://github.com/microsoft/Microsoft365DSC/issues/5015) - * Fixes an issue where the `AccessTokens` parameter was not available. - FIXES [#5121](https://github.com/microsoft/Microsoft365DSC/issues/5121) -* IntuneAppCategory +* AADEntitlementManagementSettings + * Added support for ApplicationSecret +* AADIdentityGovernanceLifecycleWorkflow * Initial release. -* IntuneDeviceCompliancePolicyWindows10 - * Fixes an issue where the property `ValidOperatingSystemBuildRanges` was - not exported properly. - FIXES [#5030](https://github.com/microsoft/Microsoft365DSC/issues/5030) -* IntuneDeviceConfigurationSharedMultiDevicePolicyWindows10 - * Add missing `AccessTokens` parameter to `Export-TargetResource` - FIXES [#5034](https://github.com/microsoft/Microsoft365DSC/issues/5034) -* IntuneFirewallPolicyWindows10 - * Initial release - FIXES [#3033](https://github.com/microsoft/Microsoft365DSC/issues/3033) -* IntuneSettingCatalogCustomPolicyWindows10 - * Update export logic to target more specific policy types. - * Prevent thrown exception to be caught by exception handler. - FIXES [#5088](https://github.com/microsoft/Microsoft365DSC/issues/5088) -* M365DSCDRGUtil - * Add support for more complex Intune Settings Catalog properties - * Update handling of `Update-IntuneDeviceConfigurationPolicy` to throw on error - FIXES [#5055](https://github.com/microsoft/Microsoft365DSC/issues/5055) -* M365DSCResourceGenerator - * Update Intune resource generation for the Settings Catalog. -* O365ExternalConnection +* AADLifecycleWorkflowSettings * Initial release. -* SCDeviceConditionalAccessRule +* AADServicePrincipal + * Adding Delegated Permission Classification Property +* ADOPermissionGroupSettings * Initial release. -* SCDeviceConfigurationRule +* EXOATPBuiltInProtectionRule * Initial release. -* SCInsiderRiskEntityList +* EXOMigrationEndpoint + * Initial Release +* IntuneAccountProtectionPolicy + * Added deprecation notice. +* IntuneAccountProtectionPolicyWindows10 + * Initial Release + FIXES [#5073](https://github.com/microsoft/Microsoft365DSC/issues/5073) +* IntuneAppAndBrowserIsolationPolicyWindows10 * Initial release. -* SCInsiderRiskPolicy + FIXES [#3028](https://github.com/microsoft/Microsoft365DSC/issues/3028) +* IntuneDerivedCredential * Initial release. -* SCRecordReviewNotificationTemplateConfig +* IntuneDeviceConfigurationIdentityProtectionPolicyWindows10 + * Added deprecation notice. +* IntuneEndpointDetectionAndResponsePolicyWindows10 + * Migrate to new Settings Catalog cmdlets. +* IntuneMobileAppsMacOSLobApp + * Initial release +* IntuneMobileAppsWindowsOfficeSuiteApp + * Initial release +* IntuneSecurityBaselineMicrosoft365AppsForEnterprise + * Initial release +* IntuneSecurityBaselineMicrosoftEdge + * Initial release +* PPAdminDLPPolicy * Initial release. -* SCRoleGroup - * Fixes an issue with creation without specifying Displayname - * Fixes an issue with Drifts because of returned Role format - FIXES [#5036](https://github.com/microsoft/Microsoft365DSC/issues/5036) -* SCAutoSensitivityLabelRule - * Fixed issue with incorrectly applying HeaderMatchesPatterns, even when - parameter wasn`t specified. - FIXES [#4641](https://github.com/microsoft/Microsoft365DSC/issues/4641) -* SCSensitivityLabel - * Added support for Auto Labeling settings - FIXES [#3784](https://github.com/microsoft/Microsoft365DSC/issues/3784) -* SentinelSetting +* PPDLPPolicyConnectorConfigurations * Initial release. -* SentinelWatchlist +* PPPowerAppPolicyUrlPatterns * Initial release. -* SPOAccessControlSettings - * Added support for property EnableRestrictedAccessControl. -* M365DSCUtil - * Fixes an issue where the O365Group workload was not properly detected. - FIXES [#5095](https://github.com/microsoft/Microsoft365DSC/issues/5095) +* TeamsClientConfiguration + * Fixed bug where RestrictedSenderList was always empty in the MSFT_TeamsClientConfiguration resource + FIXES [#5190](https://github.com/microsoft/Microsoft365DSC/issues/5190) + * Changed Set-TargetResource to always use semicolon as separator as mentioned in the MS documentation +* TeamsUpgradePolicy + * Added support for tenant wide changes using the * value for users. + FIXES [#5174](https://github.com/microsoft/Microsoft365DSC/issues/5174) +* M365DSCDRGUtil + * Fixes an issue for the handling of skipped one-property elements in the + Settings Catalog. FIXES [#5086](https://github.com/microsoft/Microsoft365DSC/issues/5086) + * Add Set support for secret Settings Catalog values + * Removed unused functions + * Add support for device / user scoped settings. +* ResourceGenerator + * Add support for device / user scoped settings. * DEPENDENCIES - * Updated DSCParser to version 2.0.0.10. - * Updated Microsoft.Graph to version 2.23.0. - * Added dependencies on Az.Accounts, Az.Resources and Az.SecurityInsights - * Updated DSCParser to version 2.0.0.9. - * Updated MSCloudLoginAssistant to version 1.1.25. - * Added dependency on Microsoft.Graph.Beta.Search. - * Removed unnecessary dependency PSDesiredStateConfiguration v1.1' + * Updated DSCParser to version 2.0.0.11 + * Updated ReverseDSC to version 2.0.0.21' # Flag to indicate whether the module requires explicit user acceptance for install/update # RequireLicenseAcceptance = $false From 732535deb54029f7e88d532f6278c8e1f9bf1bf8 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 17 Oct 2024 12:31:51 -0400 Subject: [PATCH 250/252] Fixes --- .../MSFT_AADAdminConsentRequestPolicy.schema.mof | 1 + .../MSFT_AADCustomSecurityAttributeDefinition.schema.mof | 2 +- Modules/Microsoft365DSC/Dependencies/Manifest.psd1 | 2 +- Modules/Microsoft365DSC/Microsoft365DSC.psd1 | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/MSFT_AADAdminConsentRequestPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/MSFT_AADAdminConsentRequestPolicy.schema.mof index f06f5c010f..d9c7b838fc 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/MSFT_AADAdminConsentRequestPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdminConsentRequestPolicy/MSFT_AADAdminConsentRequestPolicy.schema.mof @@ -3,6 +3,7 @@ class MSFT_AADAdminConsentRequestPolicyReviewer { [Write, Description("Type of reviewwer. Can be User, Group or Role")] String ReviewerType; [Write, Description("Identifier for the reviewer instance.")] String ReviewerId; + [Write, Description("Associated query.")] String QueryRoot; }; [ClassVersion("1.0.0.0"), FriendlyName("AADAdminConsentRequestPolicy")] diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/MSFT_AADCustomSecurityAttributeDefinition.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/MSFT_AADCustomSecurityAttributeDefinition.schema.mof index 6aebad09ae..f440bccc52 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/MSFT_AADCustomSecurityAttributeDefinition.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADCustomSecurityAttributeDefinition/MSFT_AADCustomSecurityAttributeDefinition.schema.mof @@ -2,7 +2,7 @@ class MSFT_AADCustomSecurityAttributeDefinition : OMI_BaseResource { [Key, Description("Name of the custom security attribute. Must be unique within an attribute set. Can be up to 32 characters long and include Unicode characters. Can't contain spaces or special characters. Can't be changed later. Case sensitive.")] String Name; - [Write, Description("Name of the attribute set. Case sensitive.")] String AttributeSet; + [Key, Description("Name of the attribute set. Case sensitive.")] String AttributeSet; [Write, Description("Unique identifier of the Attribute Definition.")] String Id; [Write, Description("Description of the custom security attribute. Can be up to 128 characters long and include Unicode characters. Can't contain spaces or special characters. Can be changed later. ")] String Description; [Write, Description("Indicates whether multiple values can be assigned to the custom security attribute. Can't be changed later. If type is set to Boolean, isCollection can't be set to true.")] Boolean IsCollection; diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index 12b67f090a..7fd6bbe7fe 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -137,7 +137,7 @@ }, @{ ModuleName = 'ReverseDSC' - RequiredVersion = '2.0.0.21' + RequiredVersion = '2.0.0.22' } ) } diff --git a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 index 4cab0e3be0..db41671f0b 100644 --- a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 +++ b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 @@ -219,7 +219,7 @@ * Add support for device / user scoped settings. * DEPENDENCIES * Updated DSCParser to version 2.0.0.11 - * Updated ReverseDSC to version 2.0.0.21' + * Updated ReverseDSC to version 2.0.0.22' # Flag to indicate whether the module requires explicit user acceptance for install/update # RequireLicenseAcceptance = $false From 0b49932bf0a5d3cb93f7495cc7c79547bb5c057c Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 17 Oct 2024 16:48:57 +0000 Subject: [PATCH 251/252] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/azure-ad/AADAdminConsentRequestPolicy.md | 1 + .../resources/azure-ad/AADCustomSecurityAttributeDefinition.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/docs/resources/azure-ad/AADAdminConsentRequestPolicy.md b/docs/docs/resources/azure-ad/AADAdminConsentRequestPolicy.md index 2962d501f8..c87b4f13da 100644 --- a/docs/docs/resources/azure-ad/AADAdminConsentRequestPolicy.md +++ b/docs/docs/resources/azure-ad/AADAdminConsentRequestPolicy.md @@ -25,6 +25,7 @@ | --- | --- | --- | --- | --- | | **ReviewerType** | Write | String | Type of reviewwer. Can be User, Group or Role | | | **ReviewerId** | Write | String | Identifier for the reviewer instance. | | +| **QueryRoot** | Write | String | Associated query. | | ## Description diff --git a/docs/docs/resources/azure-ad/AADCustomSecurityAttributeDefinition.md b/docs/docs/resources/azure-ad/AADCustomSecurityAttributeDefinition.md index d1da8c4e1f..0c447db556 100644 --- a/docs/docs/resources/azure-ad/AADCustomSecurityAttributeDefinition.md +++ b/docs/docs/resources/azure-ad/AADCustomSecurityAttributeDefinition.md @@ -5,7 +5,7 @@ | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | | **Name** | Key | String | Name of the custom security attribute. Must be unique within an attribute set. Can be up to 32 characters long and include Unicode characters. Can't contain spaces or special characters. Can't be changed later. Case sensitive. | | -| **AttributeSet** | Write | String | Name of the attribute set. Case sensitive. | | +| **AttributeSet** | Key | String | Name of the attribute set. Case sensitive. | | | **Id** | Write | String | Unique identifier of the Attribute Definition. | | | **Description** | Write | String | Description of the custom security attribute. Can be up to 128 characters long and include Unicode characters. Can't contain spaces or special characters. Can be changed later. | | | **IsCollection** | Write | Boolean | Indicates whether multiple values can be assigned to the custom security attribute. Can't be changed later. If type is set to Boolean, isCollection can't be set to true. | | From 120553154f48aa5f7a810d7e4cc1583c3fdbb067 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 17 Oct 2024 16:53:05 +0000 Subject: [PATCH 252/252] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index a592c2b6d5..7ed3b00e3d 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -71,6 +71,11 @@ "CIMType": "String", "Name": "ReviewerId", "Option": "Write" + }, + { + "CIMType": "String", + "Name": "QueryRoot", + "Option": "Write" } ] }, @@ -3165,7 +3170,7 @@ { "CIMType": "String", "Name": "AttributeSet", - "Option": "Write" + "Option": "Key" }, { "CIMType": "String",