diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b6d19afb3..9879a4382a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ # UNRELEASED +* IntuneDerivedCredential + * Initial release. * AADAdminConsentRequestPolicy * Initial release. * AADApplication diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/MSFT_IntuneAppCategory.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/MSFT_IntuneAppCategory.schema.mof index 676bc98242..c9d08b3067 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/MSFT_IntuneAppCategory.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/MSFT_IntuneAppCategory.schema.mof @@ -1,7 +1,7 @@ [ClassVersion("1.0.0.0"), FriendlyName("IntuneAppCategory")] class MSFT_IntuneAppCategory : OMI_BaseResource { - [Key, Description("The name of the app category.")] String DisplayName; + [Key, Description("The name of the app.")] String DisplayName; [Write, Description("The unique identifier for an entity. Read-only.")] String Id; [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] string Ensure; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.psm1 new file mode 100644 index 0000000000..af4ecd222e --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.psm1 @@ -0,0 +1,499 @@ +function Get-TargetResource { + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param ( + + #region resource params + + [Parameter()] + [System.String] + $Id, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $HelpUrl, + + [Parameter()] + [ValidateSet('intercede', 'entrustData', 'purebred')] + [System.String] + $Issuer, + + [Parameter()] + [ValidateSet('none', 'email', 'companyPortal')] + [System.String] + $NotificationType = 'none', + + [Parameter()] + [System.Int32] + $RenewalThresholdPercentage, + + #endregion resource params + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [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 + + ) + + New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters | Out-Null + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + + try + { + $instance = $null + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Id -eq $Id} + } + + if ($null -eq $instance) + { + $instance = Get-MgBetaDeviceManagementDerivedCredential -DeviceManagementDerivedCredentialSettingsId $Id -ErrorAction Stop + + if ($null -eq $instance) + { + Write-Verbose -Message "Could not find Derived Credential by Id {$Id}." + + if (-Not [string]::IsNullOrEmpty($DisplayName)) + { + $instance = Get-MgBetaDeviceManagementDerivedCredential ` + -Filter "DisplayName eq '$DisplayName'" ` + -ErrorAction SilentlyContinue + if ($null -eq $instance) + { + Write-Verbose -Message "Could not find Derived Credential by DisplayName {$DisplayName}." + return $nullResult + } + } + } + } + + $results = @{ + Ensure = 'Present' + Id = $instance.Id + DisplayName = $instance.DisplayName + HelpUrl = $instance.HelpUrl + Issuer = $instance.Issuer.ToString() + NotificationType = $instance.NotificationType.ToString() + RenewalThresholdPercentage = $instance.RenewalThresholdPercentage + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ApplicationSecret = $ApplicationSecret + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + 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 params + + [Parameter()] + [System.String] + $Id, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $HelpUrl, + + [Parameter()] + [ValidateSet('intercede', 'entrustData', 'purebred')] + [System.String] + $Issuer, + + [Parameter()] + [System.Int32] + $RenewalThresholdPercentage, + + #endregion resource params + + [Parameter()] + [ValidateSet('none', 'email', 'companyPortal')] + [System.String] + $NotificationType = 'none', + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure='Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + $setParameters.remove('Id') | Out-Null + $setParameters.remove('Ensure') | Out-Null + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + New-MgBetaDeviceManagementDerivedCredential @SetParameters + } + # UPDATE is not supported API, it always creates a new Derived Credential instance + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Remove-MgBetaDeviceManagementDerivedCredential -DeviceManagementDerivedCredentialSettingsId $currentInstance.Id -Confirm:$false + } +} + +function Test-TargetResource { + [CmdletBinding()] + [OutputType([System.Boolean])] + param ( + + #region resource params + + [Parameter()] + [System.String] + $Id, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $HelpUrl, + + [Parameter()] + [ValidateSet('intercede', 'entrustData', 'purebred')] + [System.String] + $Issuer, + + [Parameter()] + [ValidateSet('none', 'email', 'companyPortal')] + [System.String] + $NotificationType = 'none', + + [Parameter()] + [System.Int32] + $RenewalThresholdPercentage, + + #endregion resource params + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [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 + ) + + 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 ( + + #region resource params + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $HelpUrl, + + [Parameter()] + [ValidateSet('intercede', 'entrustData', 'purebred')] + [System.String] + $Issuer, + + [Parameter()] + [ValidateSet('none', 'email', 'companyPortal')] + [System.String] + $NotificationType = 'none', + + [Parameter()] + [System.Int32] + $RenewalThresholdPercentage, + + #endregion resource params + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.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-MgBetaDeviceManagementDerivedCredential -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + $displayedKey = $config.Id + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + + $params = @{ + Ensure = 'Present' + Id = $config.Id + DisplayName = $config.DisplayName + HelpUrl = $config.HelpUrl + Issuer = $config.Issuer.ToString() + NotificationType = $config.NotificationType.ToString() + RenewalThresholdPercentage = $config.RenewalThresholdPercentage + Credential = $Credential + AccessTokens = $AccessTokens + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.schema.mof new file mode 100644 index 0000000000..e893173409 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/MSFT_IntuneDerivedCredential.schema.mof @@ -0,0 +1,31 @@ +[ClassVersion("1.0.0.0"), FriendlyName("IntuneDerivedCredential")] +class MSFT_IntuneDerivedCredential : OMI_BaseResource +{ + [Key, Description("The name of the app category.")] String DisplayName; + [Write, Description("The unique identifier for an entity. Read-only.")] String Id; + + [Write, Description("The URL that will be accessible to end users as they retrieve a derived credential using the Company Portal.")] String HelpUrl; + [Write, Description("The nominal percentage of time before certificate renewal is initiated by the client.")] Uint32 RenewalThresholdPercentage; + [Write, Description("Supported values for the derived credential issuer."), + ValueMap{"intercede", "entrustDatacard", "purebred"}, + Values{"intercede", "entrustDatacard", "purebred"}] + String Issuer; + + [Write, Description("Supported values for the notification type to use."), + ValueMap{"none", "email", "companyPortal"}, + Values{"none", "email", "companyPortal"}] + String NotificationType; + + [Write, Description("Supported values for the notification type to use."), + ValueMap{"Present", "Absent"}, + Values{"Present", "Absent"}] + String Ensure; + + [Write, Description("Credentials of the Intune Admin"), EmbeddedInstance("MSFT_Credential")] String Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com")] String TenantId; + [Write, Description("Secret of the Azure Active Directory tenant used for authentication."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/readme.md new file mode 100644 index 0000000000..124a837b06 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/readme.md @@ -0,0 +1,6 @@ + +# IntuneDerivedCredential + +## Description + +## Create new navigation property to derivedCredentials for deviceManagement for Intune. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/settings.json new file mode 100644 index 0000000000..488bd5b384 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDerivedCredential/settings.json @@ -0,0 +1,21 @@ +{ + "resourceName": "IntuneDerivedCredential", + "description": "Use this resource to create new navigation property to derivedCredentials for device Management in Intune.", + + "permissions": { + "graph": { + "delegated": { + "read": [ + ], + "update": [ + ] + }, + "application": { + "read": [ + ], + "update": [ + ] + } + } + } + } diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof index ec3e29882d..ce7f2b865f 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneMobileAppsMacOSLobApp/MSFT_IntuneMobileAppsMacOSLobApp.schema.mof @@ -57,12 +57,12 @@ class MSFT_IntuneMobileAppsMacOSLobApp : OMI_BaseResource [Write, Description("The owner of the app. Inherited from mobileApp.")] String Owner; [Write, Description("The privacy statement Url. Inherited from mobileApp.")] String PrivacyInformationUrl; [Write, Description("The publisher of the app. Inherited from mobileApp.")] String Publisher; + [Write, Description("The publishing state for the app. The app cannot be assigned unless the app is published. Inherited from mobileApp."), ValueMap{"notPublished", "processing","published"}, Values{"notPublished", "processing", "published"}] String PublishingState; [Write, Description("The bundleId of the app.")] String BundleId; [Write, Description("The 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("Whether to ignore the version of the app or not.")] Boolean IgnoreVersionDetection; - [Write, Description("Install the app as managed. Requires macOS 11.0.")] Boolean InstallAsManaged; [Write, Description("The icon for this app."), EmbeddedInstance("MSFT_DeviceManagementMimeContent")] String LargeIcon; [Write, Description("The minimum supported operating system to install the app."), EmbeddedInstance("MSFT_DeviceManagementMinimumOperatingSystem")] String MinimumSupportedOperatingSystem; [Write, Description("The list of categories for this app."), EmbeddedInstance("MSFT_DeviceManagementMobileAppCategory")] String Categories[]; diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/1-Create.ps1 new file mode 100644 index 0000000000..04a9cefe20 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/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 { + IntuneDerivedCredential "IntuneDerivedCredential-K5" + { + DisplayName = "K5"; + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; + Ensure = "Present"; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/2-Update.ps1 new file mode 100644 index 0000000000..04a9cefe20 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/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 { + IntuneDerivedCredential "IntuneDerivedCredential-K5" + { + DisplayName = "K5"; + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; + Ensure = "Present"; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/3-Remove.ps1 new file mode 100644 index 0000000000..4c67edeead --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneDerivedCredential/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 { + IntuneDerivedCredential "IntuneDerivedCredential-K5" + { + DisplayName = "K5"; + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; + Ensure = "Absent"; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 index 0241cc86d4..f19c52da7d 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/1-Create.ps1 @@ -39,7 +39,7 @@ Configuration Example PrivacyInformationUrl = ""; Publisher = "Contoso"; Assignments = @( - MSFT_DeviceManagementMobileAppAssignment{ + MSFT_DeviceManagementMobileAppAssignment { groupDisplayName = 'All devices' deviceAndAppManagementAssignmentFilterType = 'none' dataType = '#microsoft.graph.allDevicesAssignmentTarget' diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 index 0ccab66255..f7746f29b1 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneMobileAppsMacOSLobApp/2-Update.ps1 @@ -38,14 +38,15 @@ Configuration Example Owner = ""; PrivacyInformationUrl = ""; Publisher = "Contoso"; - Assignments = @( - MSFT_DeviceManagementMobileAppAssignment{ + PublishingState = "published"; + Assignments = @( + MSFT_DeviceManagementMobileAppAssignment { groupDisplayName = 'All devices' deviceAndAppManagementAssignmentFilterType = 'none' dataType = '#microsoft.graph.allDevicesAssignmentTarget' intent = 'required' } - MSFT_DeviceManagementMobileAppAssignment{ + MSFT_DeviceManagementMobileAppAssignment { deviceAndAppManagementAssignmentFilterType = 'none' dataType = '#microsoft.graph.groupAssignmentTarget' groupId = '57b5e81c-85bb-4644-a4fd-33b03e451c89' diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDerivedCredential.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDerivedCredential.Tests.ps1 new file mode 100644 index 0000000000..1d23b82ab7 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDerivedCredential.Tests.ps1 @@ -0,0 +1,207 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -GenericStubModule $GenericStubPath + +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + + Mock -CommandName Get-MgBetaDeviceManagementDerivedCredential -MockWith { + } + Mock -CommandName New-MgBetaDeviceManagementDerivedCredential -MockWith { + } + Mock -CommandName Remove-MgBetaDeviceManagementDerivedCredential -MockWith { + } + + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + + # Test contexts + Context -Name " 1. The instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + Ensure = 'Present' + DisplayName = "K5"; + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; + Credential = $Credential + } + + Mock -CommandName Get-MgBetaDeviceManagementDerivedCredential -MockWith { + return $null + } + } + It ' 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-MgBetaDeviceManagementDerivedCredential -Exactly 1 + } + } + + Context -Name " 2. The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + Ensure = 'Absent' + DisplayName = "K5"; + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; + Credential = $Credential + } + + Mock -CommandName Get-MgBetaDeviceManagementDerivedCredential -MockWith { + return @{ + DisplayName = "K5"; + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; + } + } + } + It ' 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-MgBetaDeviceManagementDerivedCredential -Exactly 1 + } + } + + Context -Name " 3. The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Ensure = 'Present' + DisplayName = "K5"; + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; + Credential = $Credential + } + + Mock -CommandName Get-MgBetaDeviceManagementDerivedCredential -MockWith { + return @{ + Ensure = 'Present' + DisplayName = "K5"; + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; + } + } + } + + It ' 3.0 Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name " 4. The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Ensure = 'Present' + DisplayName = "K5"; + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; + Credential = $Credential + } + + Mock -CommandName Get-MgBetaDeviceManagementDerivedCredential -MockWith { + return @{ + DisplayName = "K5 drift"; #drift + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; + } + } + } + + It ' 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 + } + + # Update is not allowed on DerivedCredential resource so it should be called 0 times. + } + + Context -Name ' 5. ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDeviceManagementDerivedCredential -MockWith { + return @{ + DisplayName = "K5"; + HelpUrl = "http://www.ff.com/"; + Id = "a409d85f-2a49-440d-884a-80fb52a557ab"; + Issuer = "purebred"; + NotificationType = "email"; + } + } + } + It ' 5.0 Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index b5c7007061..816dc46565 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -19348,7 +19348,8 @@ function Get-MgBetaDeviceManagementGroupPolicyConfigurationAssignment ) } -function New-MgBetaDeviceAppManagementMobileApp { +function New-MgBetaDeviceManagementDerivedCredential { + [CmdletBinding()] param ( [Parameter()] @@ -19359,6 +19360,74 @@ function New-MgBetaDeviceAppManagementMobileApp { [System.String] $DisplayName, + [Parameter()] + [System.String] + $HelpUrl, + + [Parameter()] + [ValidateSet('intercede', 'entrustData', 'purebred')] + [System.String] + $Issuer, + + [Parameter()] + [ValidateSet('none', 'email', 'companyPortal')] + [System.String] + $NotificationType = 'none' + ) +} + +function Get-MgBetaDeviceManagementDerivedCredential { + [CmdletBinding()] + param ( + [Parameter()] + [System.String] + $DeviceManagementDerivedCredentialSettingsId, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $HelpUrl, + + [Parameter()] + [ValidateSet('intercede', 'entrustData', 'purebred')] + [System.String] + $Issuer, + + [Parameter()] + [ValidateSet('none', 'email', 'companyPortal')] + [System.String] + $NotificationType = 'none' + ) +} + +function Remove-MgBetaDeviceManagementDerivedCredential +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $DeviceManagementDerivedCredentialSettingsId, + + [Parameter()] + [System.Boolean] + $Confirm + ) +} + +function New-MgBetaDeviceAppManagementMobileApp { + [CmdletBinding()] + param ( + [Parameter()] + [System.String] + $DeviceManagementDerivedCredentialSettingsId, + + [Parameter()] + [System.String] + $DisplayName, + [Parameter()] [System.String] $Description,