From da0d198f19022ed25f32a0f34fcecfad97c01cd6 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Mon, 23 Sep 2024 17:36:24 -0700 Subject: [PATCH 01/22] 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 02/22] 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 03/22] 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 b76d84d1ed5d8bb59a9ee3e688ed610ed8eba974 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Tue, 1 Oct 2024 23:46:13 -0700 Subject: [PATCH 04/22] 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 05/22] 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 06/22] 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 dc9142beb4df6d3c0aa83ce9b371a65379ecae22 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Thu, 3 Oct 2024 00:14:15 -0700 Subject: [PATCH 07/22] 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 08/22] 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 09/22] 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 c8512ffa0d9c5cecde33daa7b2e0be338b558933 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Thu, 3 Oct 2024 11:38:59 -0700 Subject: [PATCH 10/22] 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 11/22] 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 6953462c7091c22f1c9081fbd2be6ae9da6d319d Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Thu, 3 Oct 2024 15:44:38 -0700 Subject: [PATCH 12/22] 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 b823018445d026775002710e55677fa0e01f7876 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Fri, 4 Oct 2024 18:39:21 -0700 Subject: [PATCH 13/22] 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 93a4ce3a99f177c5e9d37b07ccfc3ac544ecd0f3 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Fri, 4 Oct 2024 20:25:47 -0700 Subject: [PATCH 14/22] 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 15/22] 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 bee771d1420f0e3151b954cf30eca9ad273b9fcb Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Sat, 5 Oct 2024 20:17:46 -0700 Subject: [PATCH 16/22] 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 17/22] 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 18/22] 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 19/22] 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 20/22] 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 41cba6437485a17310fd2aefeab46f45ffcd5bec Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Mon, 7 Oct 2024 00:28:47 -0700 Subject: [PATCH 21/22] 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 f52c909beecd3bf026627631e1c381253c67ecc3 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Mon, 7 Oct 2024 15:48:25 -0700 Subject: [PATCH 22/22] 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