diff --git a/CHANGELOG.md b/CHANGELOG.md index 16a833aab1..5b80025659 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ * Initial release. * AADCustomSecurityAttributeDefinition * Fixed missing permissions in settings.json +* AADHomeRealmDiscoveryPolicy + * Initial Release * AADIdentityB2XUserFlow * Initial release. * AADIdentityGovernanceProgram diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADHomeRealmDiscoveryPolicy/MSFT_AADHomeRealmDiscoveryPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADHomeRealmDiscoveryPolicy/MSFT_AADHomeRealmDiscoveryPolicy.psm1 new file mode 100644 index 0000000000..bd3c930dee --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADHomeRealmDiscoveryPolicy/MSFT_AADHomeRealmDiscoveryPolicy.psm1 @@ -0,0 +1,567 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + #region resource generator code + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Definition, + + [Parameter()] + [System.Boolean] + $IsOrganizationDefault, + + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + #endregion + + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + try + { + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + + $getValue = $null + #region resource generator code + $getValue = Get-MgBetaPolicyHomeRealmDiscoveryPolicy ` + -Filter "DisplayName eq '$DisplayName'" + + #endregion + if ($null -eq $getValue) + { + Write-Verbose -Message "Could not find an Azure AD Home Realm Discovery Policy with DisplayName {$DisplayName}." + return $nullResult + } + # if multiple objects with same name exist + if ($getValue -is [array]) { + Write-Verbose -Message "Multiple Azure AD Home Realm Discovery Policy with DisplayName {$DisplayName} found. Skipping Operation." + return $nullResult + } + + Write-Verbose -Message "An Azure AD Home Realm Discovery Policy with DisplayName {$DisplayName} was found" + + $DefinitionArray = @() + foreach ($definitionValue in $getValue.definition) { + $value = ConvertFrom-Json $definitionValue + $DefinitionArray += @{ + AccelerateToFederatedDomain = $value.HomeRealmDiscoveryPolicy.AccelerateToFederatedDomain + AllowCloudPasswordValidation = $value.HomeRealmDiscoveryPolicy.AllowCloudPasswordValidation + PreferredDomain = $value.HomeRealmDiscoveryPolicy.PreferredDomain + AlternateIdLogin = @{ + Enabled = $value.HomeRealmDiscoveryPolicy.AlternateIdLogin.Enabled + } + } + } + + $results = @{ + #region resource generator code + Definition = [Array]$DefinitionArray + IsOrganizationDefault = $getValue.isOrganizationDefault + Description = $getValue.description + DisplayName = $getValue.displayName + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + #endregion + } + + return [System.Collections.Hashtable] $results + } + catch + { + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + #region resource generator code + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Definition, + + [Parameter()] + [System.Boolean] + $IsOrganizationDefault, + + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + #endregion + + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + + $BoundParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # to get the id parameter + $getValue = Get-MgBetaPolicyHomeRealmDiscoveryPolicy ` + -Filter "DisplayName eq '$DisplayName'" + + $newDefinitions = @() + foreach ($Def in $Definition) { + $HomeRealmDiscoveryPolicy = @{} + if ($null -ne $Def.AccelerateToFederatedDomain){ + $HomeRealmDiscoveryPolicy.Add('AccelerateToFederatedDomain', $Def.AccelerateToFederatedDomain) + } + if ($null -ne $Def.AllowCloudPasswordValidation){ + $HomeRealmDiscoveryPolicy.Add('AllowCloudPasswordValidation', $Def.AllowCloudPasswordValidation) + } + if ($null -ne $Def.PreferredDomain){ + $HomeRealmDiscoveryPolicy.Add('PreferredDomain', $Def.PreferredDomain) + } + if ($null -ne $Def.AlternateIdLogin.Enabled){ + $HomeRealmDiscoveryPolicy.Add('AlternateIdLogin', @{Enabled = $Def.AlternateIdLogin.Enabled}) + } + $temp = @{ + HomeRealmDiscoveryPolicy = $HomeRealmDiscoveryPolicy + } + $newDefinitions += ConvertTo-Json $temp -Depth 10 -Compress + } + + $BoundParameters.Definition = $newDefinitions + + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + Write-Verbose -Message "Creating an Azure AD Home Realm Discovery Policy with DisplayName {$DisplayName}" + + $createParameters = ([Hashtable]$BoundParameters).Clone() + $createParameters = Rename-M365DSCCimInstanceParameter -Properties $createParameters + + #region resource generator code + $policy = New-MgBetaPolicyHomeRealmDiscoveryPolicy -BodyParameter $createParameters + #endregion + } + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Updating the Azure AD Home Realm Discovery Policy with DisplayName {$($currentInstance.DisplayName)}" + + $updateParameters = ([Hashtable]$BoundParameters).Clone() + $updateParameters = Rename-M365DSCCimInstanceParameter -Properties $updateParameters + + #region resource generator code + Update-MgBetaPolicyHomeRealmDiscoveryPolicy ` + -HomeRealmDiscoveryPolicyId $getValue.Id ` + -BodyParameter $UpdateParameters + #endregion + } + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Removing the Azure AD Home Realm Discovery Policy with DisplayName {$($currentInstance.DisplayName)}" + #region resource generator code + Remove-MgBetaPolicyHomeRealmDiscoveryPolicy -HomeRealmDiscoveryPolicyId $getValue.Id + #endregion + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + #region resource generator code + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Definition, + + [Parameter()] + [System.Boolean] + $IsOrganizationDefault, + + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + #endregion + + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + Write-Verbose -Message "Testing configuration of the Azure AD Home Realm Discovery Policy with DisplayName {$DisplayName}" + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() + + if ($CurrentValues.Ensure -ne $Ensure) + { + Write-Verbose -Message "Test-TargetResource returned $false" + return $false + } + $testResult = $true + + #Compare Cim instances + foreach ($key in $PSBoundParameters.Keys) + { + $source = $PSBoundParameters.$key + $target = $CurrentValues.$key + if ($null -ne $source -and $source.GetType().Name -like '*CimInstance*') + { + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + if (-not $testResult) + { + break + } + $ValuesToCheck.Remove($key) | Out-Null + } + } + + $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + if ($testResult) + { + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + } + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + #region resource generator code + [array]$getValue = Get-MgBetaPolicyHomeRealmDiscoveryPolicy ` + -Filter $Filter ` + -All ` + -ErrorAction Stop + #endregion + + $i = 1 + $dscContent = '' + if ($getValue.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $getValue) + { + $displayedKey = $config.DisplayName + if (-not [String]::IsNullOrEmpty($config.displayName)) + { + $displayedKey = $config.displayName + } + elseif (-not [string]::IsNullOrEmpty($config.name)) + { + $displayedKey = $config.name + } + Write-Host " |---[$i/$($getValue.Count)] $displayedKey" -NoNewline + $params = @{ + DisplayName = $config.DisplayName + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + if ($null -ne $Results.Definition) + { + $Results.Definition = Get-M365DSCAADHomeRealDiscoveryPolicyDefinitionAsString $Results.Definition + } + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + + if ($null -ne $Results.Definition) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock ` + -ParameterName 'Definition' + } + + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +function Get-M365DSCAADHomeRealDiscoveryPolicyDefinitionAsString +{ + [CmdletBinding()] + [OutputType([System.String])] + param( + [Parameter(Mandatory = $true)] + [System.Collections.ArrayList] + $Definitions + ) + + $StringContent = [System.Text.StringBuilder]::new() + $StringContent.Append('@(') | Out-Null + + foreach ($definition in $Definitions) + { + $StringContent.Append("`n MSFT_AADHomeRealDiscoveryPolicyDefinition {`r`n") | Out-Null + $StringContent.Append(" PreferredDomain = '" + $definition.PreferredDomain + "'`r`n") | Out-Null + if ($null -ne $definition.AccelerateToFederatedDomain) { + $StringContent.Append(" AccelerateToFederatedDomain = $" + $definition.AccelerateToFederatedDomain + "`r`n") | Out-Null + } + if ($null -ne $definition.AllowCloudPasswordValidation) { + $StringContent.Append(" AllowCloudPasswordValidation = $" + $definition.AllowCloudPasswordValidation + "`r`n") | Out-Null + } + $StringContent.Append(" AlternateIdLogin = MSFT_AADHomeRealDiscoveryPolicyDefinitionAlternateIdLogin {`r`n") | Out-Null + $StringContent.Append(" Enabled = $" + $definition.AlternateIdLogin.Enabled + "`r`n") | Out-Null + $StringContent.Append(" }`r`n") | Out-Null + $StringContent.Append(" }`r`n") | Out-Null + } + + $StringContent.Append(' )') | Out-Null + return $StringContent.ToString() +} + + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADHomeRealmDiscoveryPolicy/MSFT_AADHomeRealmDiscoveryPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADHomeRealmDiscoveryPolicy/MSFT_AADHomeRealmDiscoveryPolicy.schema.mof new file mode 100644 index 0000000000..b352209efe --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADHomeRealmDiscoveryPolicy/MSFT_AADHomeRealmDiscoveryPolicy.schema.mof @@ -0,0 +1,33 @@ +[ClassVersion("1.0.0")] +class MSFT_AADHomeRealDiscoveryPolicyDefinition +{ + [Write, Description("Accelerate to Federated Domain.")] Boolean AccelerateToFederatedDomain; + [Write, Description("Allow cloud password validation.")] Boolean AllowCloudPasswordValidation; + [Write, Description("AlternateIdLogin complex object."), EmbeddedInstance("MSFT_AADHomeRealDiscoveryPolicyDefinitionAlternateIdLogin")] String AlternateIdLogin; + [Write, Description("Preffered Domain value.")] String PreferredDomain; +}; + +[ClassVersion("1.0.0")] +class MSFT_AADHomeRealDiscoveryPolicyDefinitionAlternateIdLogin +{ + [Write, Description("Boolean for whether AlternateIdLogin is enabled.")] Boolean Enabled; +}; + +[ClassVersion("1.0.0.0"), FriendlyName("AADHomeRealmDiscoveryPolicy")] +class MSFT_AADHomeRealmDiscoveryPolicy : OMI_BaseResource +{ + [Key, Description("Display name for this policy. Required.")] String DisplayName; + [Write, Description("A string collection containing a complex object array that defines the rules and settings for a policy. The syntax for the definition differs for each derived policy type. Required."), EmbeddedInstance("MSFT_AADHomeRealDiscoveryPolicyDefinition")] String Definition[]; + [Write, Description("If set to true, activates this policy. There can be many policies for the same policy type, but only one can be activated as the organization default. Optional, default value is false.")] Boolean IsOrganizationDefault; + [Write, Description("Description for this policy. Required.")] String Description; + + [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_AADHomeRealmDiscoveryPolicy/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_AADHomeRealmDiscoveryPolicy/readme.md new file mode 100644 index 0000000000..97b2da84f0 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADHomeRealmDiscoveryPolicy/readme.md @@ -0,0 +1,6 @@ + +# AADHomeRealmDiscoveryPolicy + +## Description + +Azure AD Home Realm Discovery Policy diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADHomeRealmDiscoveryPolicy/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADHomeRealmDiscoveryPolicy/settings.json new file mode 100644 index 0000000000..b3c6ae18bd --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADHomeRealmDiscoveryPolicy/settings.json @@ -0,0 +1,33 @@ +{ + "resourceName": "AADHomeRealmDiscoveryPolicy", + "description": "This resource configures an Azure AD Home Realm Discovery Policy.", + "permissions": { + "graph": { + "delegated": { + "read": [ + { + "name": "Policy.Read.All" + } + ], + "update": [ + { + "name": "Policy.ReadWrite.ApplicationConfiguration" + } + ] + }, + "application": { + "read": [ + { + "name": "Policy.Read.All" + } + ], + "update": [ + { + "name": "Policy.ReadWrite.ApplicationConfiguration" + } + ] + } + } +} + +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADAccessReviewPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADAccessReviewPolicy/2-Update.ps1 index f69b86add3..3c1dc8a687 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/AADAccessReviewPolicy/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/AADAccessReviewPolicy/2-Update.ps1 @@ -23,11 +23,11 @@ Configuration Example { AADAccessReviewPolicy "AADAccessReviewPolicy" { - ApplicationId = $ConfigurationData.NonNodeData.ApplicationId; - CertificateThumbprint = $ConfigurationData.NonNodeData.CertificateThumbprint; IsGroupOwnerManagementEnabled = $False; IsSingleInstance = "Yes"; - TenantId = $OrganizationName; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADHomeRealmDiscoveryPolicy/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADHomeRealmDiscoveryPolicy/1-Create.ps1 new file mode 100644 index 0000000000..c6145aca64 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADHomeRealmDiscoveryPolicy/1-Create.ps1 @@ -0,0 +1,43 @@ +<# +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 + { + AADHomeRealmDiscoveryPolicy "AADHomeRealmDiscoveryPolicy-displayName-value" + { + Definition = @( + MSFT_AADHomeRealDiscoveryPolicyDefinition { + PreferredDomain = 'federated.example.edu' + AccelerateToFederatedDomain = $False + AlternateIdLogin = MSFT_AADHomeRealDiscoveryPolicyDefinitionAlternateIdLogin { + Enabled = $True + } + } + ); + DisplayName = "displayName-value"; + Ensure = "Present"; + IsOrganizationDefault = $False; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADHomeRealmDiscoveryPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADHomeRealmDiscoveryPolicy/2-Update.ps1 new file mode 100644 index 0000000000..12c5f39fff --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADHomeRealmDiscoveryPolicy/2-Update.ps1 @@ -0,0 +1,43 @@ +<# +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 + { + AADHomeRealmDiscoveryPolicy "AADHomeRealmDiscoveryPolicy-displayName-value" + { + Definition = @( + MSFT_AADHomeRealDiscoveryPolicyDefinition { + PreferredDomain = 'federated.example.edu' + AccelerateToFederatedDomain = $True # updating here + AlternateIdLogin = MSFT_AADHomeRealDiscoveryPolicyDefinitionAlternateIdLogin { + Enabled = $True + } + } + ); + DisplayName = "displayName-value"; + Ensure = "Present"; + IsOrganizationDefault = $False; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADHomeRealmDiscoveryPolicy/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADHomeRealmDiscoveryPolicy/3-Remove.ps1 new file mode 100644 index 0000000000..edfc129f1f --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADHomeRealmDiscoveryPolicy/3-Remove.ps1 @@ -0,0 +1,43 @@ +<# +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 + { + AADHomeRealmDiscoveryPolicy "AADHomeRealmDiscoveryPolicy-displayName-value" + { + Definition = @( + MSFT_AADHomeRealDiscoveryPolicyDefinition { + PreferredDomain = 'federated.example.edu' + AccelerateToFederatedDomain = $False + AlternateIdLogin = MSFT_AADHomeRealDiscoveryPolicyDefinitionAlternateIdLogin { + Enabled = $True + } + } + ); + DisplayName = "displayName-value"; + Ensure = "Absent"; + IsOrganizationDefault = $False; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADHomeRealmDiscoveryPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADHomeRealmDiscoveryPolicy.Tests.ps1 new file mode 100644 index 0000000000..1f82f559fd --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADHomeRealmDiscoveryPolicy.Tests.ps1 @@ -0,0 +1,242 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource "AADHomeRealmDiscoveryPolicy" -GenericStubModule $GenericStubPath +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName Get-PSSession -MockWith { + } + + Mock -CommandName Remove-PSSession -MockWith { + } + + Mock -CommandName Update-MgBetaPolicyHomeRealmDiscoveryPolicy -MockWith { + } + + Mock -CommandName New-MgBetaPolicyHomeRealmDiscoveryPolicy -MockWith { + } + + Mock -CommandName Remove-MgBetaPolicyHomeRealmDiscoveryPolicy -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + Context -Name "The AADHomeRealmDiscoveryPolicy should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + Definition = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_AADHomeRealDiscoveryPolicyDefinition -Property @{ + PreferredDomain = 'federated.example.edu' + AccelerateToFederatedDomain = $False + AlternateIdLogin = New-CimInstance -ClassName MSFT_AADHomeRealDiscoveryPolicyDefinitionAlternateIdLogin -Property @{ + Enabled = $True + } -ClientOnly + } -ClientOnly ) + Description = "FakeStringValue" + DisplayName = "FakeStringValue" + IsOrganizationDefault = $True + Ensure = "Present" + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaPolicyHomeRealmDiscoveryPolicy -MockWith { + return $null + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + It 'Should Create the group from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-MgBetaPolicyHomeRealmDiscoveryPolicy -Exactly 1 + } + } + + Context -Name "The AADHomeRealmDiscoveryPolicy exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + Definition = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_AADHomeRealDiscoveryPolicyDefinition -Property @{ + PreferredDomain = 'federated.example.edu' + AccelerateToFederatedDomain = $False + AlternateIdLogin = New-CimInstance -ClassName MSFT_AADHomeRealDiscoveryPolicyDefinitionAlternateIdLogin -Property @{ + Enabled = $True + } -ClientOnly + } -ClientOnly ) + Description = "FakeStringValue" + DisplayName = "FakeStringValue" + IsOrganizationDefault = $True + Ensure = 'Absent' + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaPolicyHomeRealmDiscoveryPolicy -MockWith { + return @{ + id = "randomguid" + definition = @( + '{"HomeRealmDiscoveryPolicy":{"PreferredDomain":"federated.example.edu","AlternateIdLogin":{"Enabled":true},"AccelerateToFederatedDomain":false}}' + ) + displayName = "FakeStringValue" + description = "FakeStringValue" + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should Remove the group from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-MgBetaPolicyHomeRealmDiscoveryPolicy -Exactly 1 + } + } + Context -Name "The AADHomeRealmDiscoveryPolicy Exists and Values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Definition = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_AADHomeRealDiscoveryPolicyDefinition -Property @{ + PreferredDomain = 'federated.example.edu' + AccelerateToFederatedDomain = $False + AlternateIdLogin = New-CimInstance -ClassName MSFT_AADHomeRealDiscoveryPolicyDefinitionAlternateIdLogin -Property @{ + Enabled = $True + } -ClientOnly + } -ClientOnly ) + Description = "FakeStringValue" + DisplayName = "FakeStringValue" + IsOrganizationDefault = $True + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaPolicyHomeRealmDiscoveryPolicy -MockWith { + return @{ + id = "randomguid" + definition = @( + '{"HomeRealmDiscoveryPolicy":{"PreferredDomain":"federated.example.edu","AlternateIdLogin":{"Enabled":true},"AccelerateToFederatedDomain":false}}' + ) + displayName = "FakeStringValue" + description = "FakeStringValue" + isOrganizationDefault = $True + } + } + } + + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The AADHomeRealmDiscoveryPolicy exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Definition = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_AADHomeRealDiscoveryPolicyDefinition -Property @{ + PreferredDomain = 'federated.example.edu' + AccelerateToFederatedDomain = $False + AlternateIdLogin = New-CimInstance -ClassName MSFT_AADHomeRealDiscoveryPolicyDefinitionAlternateIdLogin -Property @{ + Enabled = $True + } -ClientOnly + } -ClientOnly ) + Description = "FakeStringValue" + DisplayName = "FakeStringValue" + IsOrganizationDefault = $True + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaPolicyHomeRealmDiscoveryPolicy -MockWith { + return @{ + id = "randomguid" + definition = @( + '{"HomeRealmDiscoveryPolicy":{"PreferredDomain":"federated.example.edu","AlternateIdLogin":{"Enabled":true},"AccelerateToFederatedDomain":false}}' + ) + displayName = "FakeStringValue" + description = "FakeStringValue New" + isOrganizationDefault = $False + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Update-MgBetaPolicyHomeRealmDiscoveryPolicy -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + + Mock -CommandName Get-MgBetaPolicyHomeRealmDiscoveryPolicy -MockWith { + return @{ + id = "randomguid" + definition = @( + '{"HomeRealmDiscoveryPolicy":{"PreferredDomain":"federated.example.edu","AlternateIdLogin":{"Enabled":true},"AccelerateToFederatedDomain":false}}' + ) + displayName = "FakeStringValue" + description = "FakeStringValue" + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 9e4da8633c..2885031d7b 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -99495,3 +99495,314 @@ function Invoke-MgBetaUploadIdentityApiConnectorClientCertificate } #endregion +#region MgBetaPolicyHomeRealmDiscoveryPolicy +function Get-MgBetaPolicyHomeRealmDiscoveryPolicy +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $HomeRealmDiscoveryPolicyId, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject[]] + $HttpPipelineAppend, + + [Parameter()] + [PSObject[]] + $HttpPipelinePrepend, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $CountVariable + ) +} + +function New-MgBetaPolicyHomeRealmDiscoveryPolicy +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.Collections.Hashtable] + $BodyParameter, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [PSObject[]] + $AppliesTo, + + [Parameter()] + [System.String[]] + $Definition, + + [Parameter()] + [System.DateTime] + $DeletedDateTime, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsOrganizationDefault, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject[]] + $HttpPipelineAppend, + + [Parameter()] + [PSObject[]] + $HttpPipelinePrepend, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm + ) +} + +function Remove-MgBetaPolicyHomeRealmDiscoveryPolicy +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $HomeRealmDiscoveryPolicyId, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject[]] + $HttpPipelineAppend, + + [Parameter()] + [PSObject[]] + $HttpPipelinePrepend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm + ) +} + +function Update-MgBetaPolicyHomeRealmDiscoveryPolicy +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $HomeRealmDiscoveryPolicyId, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Collections.Hashtable] + $BodyParameter, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [PSObject[]] + $AppliesTo, + + [Parameter()] + [System.String[]] + $Definition, + + [Parameter()] + [System.DateTime] + $DeletedDateTime, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsOrganizationDefault, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject[]] + $HttpPipelineAppend, + + [Parameter()] + [PSObject[]] + $HttpPipelinePrepend, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm + ) +} + +#endregion +