diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityB2XUserFlow/MSFT_AADIdentityB2XUserFlow.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityB2XUserFlow/MSFT_AADIdentityB2XUserFlow.psm1 new file mode 100644 index 0000000000..41be1d79fe --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityB2XUserFlow/MSFT_AADIdentityB2XUserFlow.psm1 @@ -0,0 +1,719 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + #region resource generator code + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $ApiConnectorConfiguration, + + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + [Parameter()] + [System.String[]] + $IdentityProviders, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $UserAttributeAssignments, + + #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-MgBetaIdentityB2XUserFlow -B2XIdentityUserFlowId $Id -ErrorAction SilentlyContinue + + if ($null -eq $getValue) + { + Write-Verbose -Message "Could not find an Azure AD Identity B2 X User Flow with Id {$Id}" + return $nullResult + } + #endregion + + $Id = $getValue.Id + Write-Verbose -Message "An Azure AD Identity B2 X User Flow with Id {$Id} was found" + + #region Get ApiConnectorConfiguration + $connectorConfiguration = Get-MgBetaIdentityB2XUserFlowApiConnectorConfiguration -B2xIdentityUserFlowId $Id -ExpandProperty "postFederationSignup,postAttributeCollection" + + $complexApiConnectorConfiguration = @{ + postFederationSignupConnectorName = Get-ConnectorName($connectorConfiguration.PostFederationSignup.DisplayName) + postAttributeCollectionConnectorName = Get-ConnectorName($connectorConfiguration.PostAttributeCollection.DisplayName) + } + #endregion + + #region Get IdentityProviders + $getIdentityProviders = Get-MgBetaIdentityB2XUserFlowIdentityProvider -B2XIdentityUserFlowId $Id | Select-Object Id + if ($getIdentityProviders.Count -eq 0) + { + $getIdentityProviders = @() + } + #endregion + + $complexUserAttributeAssignments = @() + $getUserAttributeAssignments = Get-MgBetaIdentityB2XUserFlowUserAttributeAssignment -B2XIdentityUserFlowId $Id -ExpandProperty UserAttribute + foreach ($getUserAttributeAssignment in $getUserAttributeAssignments) + { + $getuserAttributeValues = @() + foreach ($getUserAttributeAssignmentAttributeValue in $getUserAttributeAssignment.UserAttributeValues) + { + $getuserAttributeValues += @{ + Name = $getUserAttributeAssignmentAttributeValue.Name + Value = $getUserAttributeAssignmentAttributeValue.Value + IsDefault = $getUserAttributeAssignmentAttributeValue.IsDefault + } + } + $complexUserAttributeAssignments += @{ + Id = $getUserAttributeAssignment.Id + DisplayName = $getUserAttributeAssignment.DisplayName + IsOptional = $getUserAttributeAssignment.IsOptional + UserInputType = $getUserAttributeAssignment.UserInputType + UserAttributeValues = $getuserAttributeValues + } + } + + $results = @{ + #region resource generator code + ApiConnectorConfiguration = $complexApiConnectorConfiguration + Id = $getValue.Id + IdentityProviders = $getIdentityProviders + UserAttributeAssignments = $complexUserAttributeAssignments + 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] + $ApiConnectorConfiguration, + + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + [Parameter()] + [System.String[]] + $IdentityProviders, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $UserAttributeAssignments, + + #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 + + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + Write-Verbose -Message "Creating an Azure AD Identity B2 X User Flow with Id {$Id}" + + #region Create ApiConnectorConfiguration object + $newApiConnectorConfiguration = @{} + if (-not [string]::IsNullOrEmpty($ApiConnectorConfiguration.postFederationSignupConnectorName)) + { + $getConnector = Get-MgBetaIdentityApiConnector -Filter "DisplayName eq '$($ApiConnectorConfiguration.postFederationSignupConnectorName)'" + $newApiConnectorConfiguration['PostFederationSignup'] = @{ + 'Id' = $getConnector.Id + } + } + + if (-not [string]::IsNullOrEmpty($ApiConnectorConfiguration.postAttributeCollectionConnectorName)) + { + $getConnector = Get-MgBetaIdentityApiConnector -Filter "DisplayName eq '$($ApiConnectorConfiguration.postAttributeCollectionConnectorName)'" + $newApiConnectorConfiguration['PostAttributeCollection'] = @{ + 'Id' = $getConnector.Id + } + } + #endregion + + $params = @{ + id = $Id + userFlowType = "signUpOrSignIn" + userFlowTypeVersion = 1 + apiConnectorConfiguration = $newApiConnectorConfiguration + } + + $newObj = New-MgBetaIdentityB2XUserFlow -BodyParameter $params + + #region Add IdentityProvider objects to the newly created object + foreach ($provider in $IdentityProviders) + { + $params = @{ + "@odata.id" = "https://graph.microsoft.com/beta/identityProviders/$($provider)" + } + + Write-Verbose -Message "Adding the Identity Provider with Id {$provider} to the newly created Azure AD Identity B2X User Flow with Id {$($newObj.Id)}" + + New-MgBetaIdentityB2XUserFlowIdentityProviderByRef -B2XIdentityUserFlowId $newObj.Id -BodyParameter $params + } + #endregion + + #region Add UserAtrributeAssignments to the newly created object + $currentAttributes = Get-MgBetaIdentityB2XUserFlowUserAttributeAssignment -B2XIdentityUserFlowId $newObj.Id | Select-Object -ExpandProperty Id + $attributesToAdd = $UserAttributeAssignments | Where-Object {$_.Id -notin $currentAttributes} + + foreach ($userAttributeAssignment in $attributesToAdd) + { + $params = @{ + displayName = $userAttributeAssignment.DisplayName + isOptional = $userAttributeAssignment.IsOptional + userInputType = $userAttributeAssignment.UserInputType + userAttributeValues = @() + userAttribute = @{ + id = $userAttributeAssignment.Id + } + } + + foreach ($userAttributeValue in $userAttributeAssignment.UserAttributeValues) + { + $params['userAttributeValues'] += @{ + "Name" = $userAttributeValue.Name + "Value" = $userAttributeValue.Value + "IsDefault" = $userAttributeValue.IsDefault + } + } + + Write-Verbose -Message "Adding the User Attribute Assignment with Id {$($userAttributeAssignment.Id)} to the newly created Azure AD Identity B2X User Flow with Id {$($newObj.Id)}" + + New-MgBetaIdentityB2XUserFlowUserAttributeAssignment -B2XIdentityUserFlowId $newObj.Id -BodyParameter $params + } + #endregion + } + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Updating the Azure AD Identity B2X User Flow with Id {$($currentInstance.Id)}" + + #region Update ApiConnectorConfiguration object + if (-not [string]::IsNullOrEmpty($ApiConnectorConfiguration.postFederationSignupConnectorName)) + { + $getConnector = Get-MgBetaIdentityApiConnector -Filter "DisplayName eq '$($ApiConnectorConfiguration.postFederationSignupConnectorName)'" + $params = @{ + "@odata.id" = "https://graph.microsoft.com/beta/identity/apiConnectors/$($getConnector.Id)" + } + + Write-Verbose -Message "Updating the Post Federation Signup connector for Azure AD Identity B2X User Flow with Id {$($currentInstance.Id)}" + + Set-MgBetaIdentityB2XUserFlowPostFederationSignupByRef -B2xIdentityUserFlowId $currentInstance.Id -BodyParameter $params + } + + if (-not [string]::IsNullOrEmpty($ApiConnectorConfiguration.postAttributeCollectionConnectorName)) + { + $getConnector = Get-MgBetaIdentityApiConnector -Filter "DisplayName eq '$($ApiConnectorConfiguration.postAttributeCollectionConnectorName)'" + $params = @{ + "@odata.id" = "https://graph.microsoft.com/beta/identity/apiConnectors/$($getConnector.Id)" + } + + Write-Verbose -Message "Updating the Post Attribute Collection connector for Azure AD Identity B2X User Flow with Id {$($currentInstance.Id)}" + + Set-MgBetaIdentityB2XUserFlowPostAttributeCollectionByRef -B2xIdentityUserFlowId $currentInstance.Id -BodyParameter $params + } + #endregion + + #region Add or Remove Identity Providers on the current instance + $providersToAdd = $IdentityProviders | Where-Object {$_ -notin $currentInstance.IdentityProviders} + foreach ($provider in $providersToAdd) + { + $params = @{ + "@odata.id" = "https://graph.microsoft.com/beta/identityProviders/$($provider)" + } + + Write-Verbose -Message "Adding the Identity Provider with Id {$provider} to the Azure AD Identity B2X User Flow with Id {$($currentInstance.Id)}" + + New-MgBetaIdentityB2XUserFlowIdentityProviderByRef -B2XIdentityUserFlowId $currentInstance.Id -BodyParameter $params + } + + $providersToRemove = $currentInstance.IdentityProviders | Where-Object {$_ -notin $IdentityProviders} + foreach ($provider in $providersToRemove) + { + Write-Verbose -Message "Removing the Identity Provider with Id {$provider} from the Azure AD Identity B2X User Flow with Id {$($currentInstance.Id)}" + + Remove-MgBetaIdentityB2XUserFlowIdentityProviderByRef -B2XIdentityUserFlowId $currentInstance.Id -IdentityProviderBaseId $provider + } + #endregion + + #region Add, remove or update User Attribute Assignments on the current instance + $attributesToRemove = $currentInstance.UserAttributeAssignments | Where-Object {$_.Id -notin $UserAttributeAssignments.Id} + + #Remove + foreach ($userAttributeAssignment in $attributesToRemove) + { + Write-Verbose -Message "Removing the User Attribute Assignment with Id {$($userAttributeAssignment.Id)} from the Azure AD Identity B2X User Flow with Id {$($currentInstance.Id)}" + + Remove-MgBetaIdentityB2XUserFlowUserAttributeAssignment -B2XIdentityUserFlowId $currentInstance.Id -IdentityUserFlowAttributeAssignmentId $userAttributeAssignment.Id + } + + #Add/Update + foreach ($userAttributeAssignment in $UserAttributeAssignments) + { + $params = @{ + displayName = $userAttributeAssignment.DisplayName + isOptional = $userAttributeAssignment.IsOptional + userInputType = $userAttributeAssignment.UserInputType + userAttributeValues = @() + } + + foreach ($userAttributeValue in $userAttributeAssignment.UserAttributeValues) + { + $params['userAttributeValues'] += @{ + "Name" = $userAttributeValue.Name + "Value" = $userAttributeValue.Value + "IsDefault" = $userAttributeValue.IsDefault + } + } + + if ($userAttributeAssignment.Id -notin $currentInstance.UserAttributeAssignments.Id) + { + $params["userAttribute"] = @{ + id = $userAttributeAssignment.Id + } + + Write-Verbose -Message "Adding the User Attribute Assignment with Id {$($userAttributeAssignment.Id)} to the Azure AD Identity B2X User Flow with Id {$($currentInstance.Id)}" + + New-MgBetaIdentityB2XUserFlowUserAttributeAssignment -B2XIdentityUserFlowId $currentInstance.Id -BodyParameter $params + } + else + { + Write-Verbose -Message "Updating the User Attribute Assignment with Id {$($userAttributeAssignment.Id)} in the Azure AD Identity B2X User Flow with Id {$($currentInstance.Id)}" + + Update-MgBetaIdentityB2XUserFlowUserAttributeAssignment -B2xIdentityUserFlowId $currentInstance.Id -IdentityUserFlowAttributeAssignmentId $userAttributeAssignment.Id -BodyParameter $params + } + } + #endregion + } + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Removing the Azure AD Identity B2 X User Flow with Id {$($currentInstance.Id)}" + Remove-MgBetaIdentityB2XUserFlow -B2XIdentityUserFlowId $currentInstance.Id + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + #region resource generator code + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $ApiConnectorConfiguration, + + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + [Parameter()] + [System.String[]] + $IdentityProviders, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $UserAttributeAssignments, + + #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 Identity B2 X User Flow with Id {$Id}" + + $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('Id') | Out-Null + $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + if ($ValuesToCheck.Count -gt 0 -and $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-MgBetaIdentityB2XUserFlow ` + -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.Id + Write-Host " |---[$i/$($getValue.Count)] $displayedKey" -NoNewline + $params = @{ + Id = $config.Id + 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.ApiConnectorConfiguration) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.ApiConnectorConfiguration ` + -CIMInstanceName 'MicrosoftGraphuserFlowApiConnectorConfiguration' + if (-not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.ApiConnectorConfiguration = $complexTypeStringResult + } + else + { + $Results.Remove('ApiConnectorConfiguration') | Out-Null + } + } + + if ($null -ne $Results.UserAttributeAssignments) + { + $complexMapping = @( + @{ + Name = 'UserAttributeValues' + CimInstanceName = 'MicrosoftGraphuserFlowUserAttributeAssignmentUserAttributeValues' + IsRequired = $False + } + ) + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.UserAttributeAssignments ` + -CIMInstanceName 'MicrosoftGraphuserFlowUserAttributeAssignment' ` + -ComplexTypeMapping $complexMapping + + if (-not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.UserAttributeAssignments = $complexTypeStringResult + } + else + { + $Results.Remove('UserAttributeAssignments') | Out-Null + } + } + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + if ($Results.ApiConnectorConfiguration) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "ApiConnectorConfiguration" -IsCIMArray:$False + } + if ($Results.UserAttributeAssignments) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "UserAttributeAssignments" -IsCIMArray:$True + } + + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +function Get-ConnectorName($connectorName) { + if ($null -ne $connectorName) { + return $connectorName + } else { + return "" + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityB2XUserFlow/MSFT_AADIdentityB2XUserFlow.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityB2XUserFlow/MSFT_AADIdentityB2XUserFlow.schema.mof new file mode 100644 index 0000000000..4ea315f134 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityB2XUserFlow/MSFT_AADIdentityB2XUserFlow.schema.mof @@ -0,0 +1,41 @@ +[ClassVersion("1.0.0")] +class MSFT_MicrosoftGraphUserFlowApiConnectorConfiguration +{ + [Write, Description("The name of the connector used for post federation signup step.")] String postFederationSignupConnectorName; + [Write, Description("The name of the connector used for post attribute collection step.")] String postAttributeCollectionConnectorName; +}; + +[ClassVersion("1.0.0")] +class MSFT_MicrosoftGraphuserFlowUserAttributeAssignmentUserAttributeValues +{ + [Write, Description("The display name of the property displayed to the end user in the user flow.")] String Name; + [Write, Description("The value that is set when this item is selected.")] String Value; + [Write, Description("Used to set the value as the default.")] Boolean IsDefault; +}; + +[ClassVersion("1.0.0")] +class MSFT_MicrosoftGraphuserFlowUserAttributeAssignment +{ + [Write, Description("The unique identifier of identityUserFlowAttributeAssignment.")] String Id; + [Write, Description("The display name of the identityUserFlowAttribute within a user flow.")] String DisplayName; + [Write, Description("Determines whether the identityUserFlowAttribute is optional.")] Boolean IsOptional; + [Write, Description("User Flow Attribute Input Type."), ValueMap{"textBox","dateTimeDropdown","radioSingleSelect","dropdownSingleSelect","emailBox","checkboxMultiSelect"}, Values{"textBox","dateTimeDropdown","radioSingleSelect","dropdownSingleSelect","emailBox","checkboxMultiSelect"}] String UserInputType; + [Write, Description("The list of user attribute values for this assignment."), EmbeddedInstance("MSFT_MicrosoftGraphuserFlowUserAttributeAssignmentUserAttributeValues")] String UserAttributeValues[]; +}; + +[ClassVersion("1.0.0.0"), FriendlyName("AADIdentityB2XUserFlow")] +class MSFT_AADIdentityB2XUserFlow : OMI_BaseResource +{ + [Write, Description("Configuration for enabling an API connector for use as part of the self-service sign-up user flow. You can only obtain the value of this object using Get userFlowApiConnectorConfiguration."), EmbeddedInstance("MSFT_MicrosoftGraphuserFlowApiConnectorConfiguration")] String ApiConnectorConfiguration; + [Key, Description("The unique identifier for an entity. Read-only.")] String Id; + [Write, Description("The identity providers included in the user flow.")] String IdentityProviders[]; + [Write, Description("The user attribute assignments included in the user flow."), EmbeddedInstance("MSFT_MicrosoftGraphuserFlowUserAttributeAssignment")] String UserAttributeAssignments[]; + [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_AADIdentityB2XUserFlow/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityB2XUserFlow/readme.md new file mode 100644 index 0000000000..c81de81f9b --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityB2XUserFlow/readme.md @@ -0,0 +1,6 @@ + +# AADIdentityB2XUserFlow + +## Description + +Azure AD Identity B2 X User Flow diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityB2XUserFlow/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityB2XUserFlow/settings.json new file mode 100644 index 0000000000..d6df4d957a --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADIdentityB2XUserFlow/settings.json @@ -0,0 +1,29 @@ +{ + "resourceName": "AADIdentityB2XUserFlow", + "description": "This resource configures an Azure AD Identity B2 X User Flow.", + "permissions": { + "graph": { + "delegated": { + "read": [ + { + "name": "IdentityUserFlow.Read.All" + } + ], + "update": [ + + ] + }, + "application": { + "read": [ + { + "name": "IdentityUserFlow.Read.All" + } + ], + "update": [ + + ] + } + } +} + +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADIdentityB2XUserFlow/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADIdentityB2XUserFlow/1-Create.ps1 new file mode 100644 index 0000000000..643146f6ca --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADIdentityB2XUserFlow/1-Create.ps1 @@ -0,0 +1,79 @@ +<# +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 + { + AADIdentityB2XUserFlow "AADIdentityB2XUserFlow-B2X_1_TestFlow" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ApiConnectorConfiguration = MSFT_MicrosoftGraphuserFlowApiConnectorConfiguration + { + postAttributeCollectionConnectorId = 'RestApi_f6e8e73d-6b17-433e-948f-f578f12bd57c' + postFederationSignupConnectorId = 'RestApi_beeb7152-673c-48b3-b143-9975949a93ca' + }; + Credential = $Credscredential; + Ensure = "Present"; + Id = "B2X_1_TestFlow"; + IdentityProviders = @("MSASignup-OAUTH","EmailOtpSignup-OAUTH"); + UserAttributeAssignments = @( + MSFT_MicrosoftGraphuserFlowUserAttributeAssignment + { + UserInputType = 'textBox' + IsOptional = $True + DisplayName = 'Email Address' + Id = 'emailReadonly' + + } + MSFT_MicrosoftGraphuserFlowUserAttributeAssignment + { + UserInputType = 'dropdownSingleSelect' + IsOptional = $True + DisplayName = 'Random' + Id = 'city' + UserAttributeValues = @( + MSFT_MicrosoftGraphuserFlowUserAttributeAssignmentUserAttributeValues + { + IsDefault = $True + Name = 'S' + Value = '2' + } + MSFT_MicrosoftGraphuserFlowUserAttributeAssignmentUserAttributeValues + { + IsDefault = $True + Name = 'X' + Value = '1' + } + ) + } + MSFT_MicrosoftGraphuserFlowUserAttributeAssignment{ + UserInputType = 'textBox' + IsOptional = $False + DisplayName = 'Piyush1' + Id = 'extension_91d51274096941f786b07b9d723d93f4_Piyush1' + + } + ); + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADIdentityB2XUserFlow/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADIdentityB2XUserFlow/2-Update.ps1 new file mode 100644 index 0000000000..643146f6ca --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADIdentityB2XUserFlow/2-Update.ps1 @@ -0,0 +1,79 @@ +<# +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 + { + AADIdentityB2XUserFlow "AADIdentityB2XUserFlow-B2X_1_TestFlow" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ApiConnectorConfiguration = MSFT_MicrosoftGraphuserFlowApiConnectorConfiguration + { + postAttributeCollectionConnectorId = 'RestApi_f6e8e73d-6b17-433e-948f-f578f12bd57c' + postFederationSignupConnectorId = 'RestApi_beeb7152-673c-48b3-b143-9975949a93ca' + }; + Credential = $Credscredential; + Ensure = "Present"; + Id = "B2X_1_TestFlow"; + IdentityProviders = @("MSASignup-OAUTH","EmailOtpSignup-OAUTH"); + UserAttributeAssignments = @( + MSFT_MicrosoftGraphuserFlowUserAttributeAssignment + { + UserInputType = 'textBox' + IsOptional = $True + DisplayName = 'Email Address' + Id = 'emailReadonly' + + } + MSFT_MicrosoftGraphuserFlowUserAttributeAssignment + { + UserInputType = 'dropdownSingleSelect' + IsOptional = $True + DisplayName = 'Random' + Id = 'city' + UserAttributeValues = @( + MSFT_MicrosoftGraphuserFlowUserAttributeAssignmentUserAttributeValues + { + IsDefault = $True + Name = 'S' + Value = '2' + } + MSFT_MicrosoftGraphuserFlowUserAttributeAssignmentUserAttributeValues + { + IsDefault = $True + Name = 'X' + Value = '1' + } + ) + } + MSFT_MicrosoftGraphuserFlowUserAttributeAssignment{ + UserInputType = 'textBox' + IsOptional = $False + DisplayName = 'Piyush1' + Id = 'extension_91d51274096941f786b07b9d723d93f4_Piyush1' + + } + ); + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADIdentityB2XUserFlow/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADIdentityB2XUserFlow/3-Remove.ps1 new file mode 100644 index 0000000000..295893f499 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADIdentityB2XUserFlow/3-Remove.ps1 @@ -0,0 +1,33 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + AADIdentityB2XUserFlow "AADIdentityB2XUserFlow-B2X_1_TestFlow" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Id = "B2X_1_TestFlow"; + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADIdentityB2XUserFlow.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADIdentityB2XUserFlow.Tests.ps1 new file mode 100644 index 0000000000..b0dd2cbd56 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADIdentityB2XUserFlow.Tests.ps1 @@ -0,0 +1,502 @@ +[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 "AADIdentityB2XUserFlow" -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-MgBetaIdentityB2XUserFlow -MockWith { + } + + Mock -CommandName New-MgBetaIdentityB2XUserFlow -MockWith { + } + + Mock -CommandName Remove-MgBetaIdentityB2XUserFlow -MockWith { + } + + Mock -CommandName Remove-MgBetaIdentityB2XUserFlowIdentityProviderByRef -MockWith { + } + + Mock -CommandName New-MgBetaIdentityB2XUserFlowIdentityProviderByRef -MockWith { + } + + Mock -CommandName Remove-MgBetaIdentityB2XUserFlowUserAttributeAssignment -MockWith { + } + + Mock -CommandName Update-MgBetaIdentityB2XUserFlowUserAttributeAssignment -MockWith { + } + + Mock -CommandName New-MgBetaIdentityB2XUserFlowUserAttributeAssignment -MockWith { + } + + Mock -CommandName Set-MgBetaIdentityB2XUserFlowPostAttributeCollectionByRef -MockWith { + } + + Mock -CommandName Set-MgBetaIdentityB2XUserFlowPostFederationSignupByRef -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 AADIdentityB2XUserFlow should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + ApiConnectorConfiguration = (New-CimInstance -ClassName MSFT_MicrosoftGraphuserFlowApiConnectorConfiguration -Property @{ + postAttributeCollectionConnectorName = 'FakeConnector1' + postFederationSignupConnectorName = 'FakeConnector2' + } -ClientOnly) + Id = "FakeStringValue" + IdentityProviders = @("Provider1", "Provider2") + UserAttributeAssignments = @((New-CimInstance -ClassName MSFT_MicrosoftGraphuserFlowUserAttributeAssignment -Property @{ + UserInputType = 'textBox' + IsOptional = $True + DisplayName = 'Email Address' + Id = 'emailReadonly' + UserAttributeValues = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_MicrosoftGraphuserFlowUserAttributeAssignment -Property @{ + IsDefault = $True + Name = 'S' + Value = '2' + } -ClientOnly + ) + } -ClientOnly)) + Ensure = "Present" + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaIdentityB2XUserFlow -MockWith { + return $null + } + + Mock -CommandName Get-MgBetaIdentityApiConnector -MockWith { + return $null + } + + Mock -CommandName Get-MgBetaIdentityB2XUserFlowUserAttributeAssignment -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-MgBetaIdentityB2XUserFlow -Exactly 1 + Should -Invoke -CommandName Get-MgBetaIdentityApiConnector -Exactly 2 + Should -Invoke -CommandName New-MgBetaIdentityB2XUserFlowIdentityProviderByRef -Exactly 2 + Should -Invoke -CommandName Get-MgBetaIdentityB2XUserFlowUserAttributeAssignment -Exactly 1 + Should -Invoke -CommandName New-MgBetaIdentityB2XUserFlowUserAttributeAssignment -Exactly 1 + } + } + + Context -Name "The AADIdentityB2XUserFlow exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + ApiConnectorConfiguration = (New-CimInstance -ClassName MSFT_MicrosoftGraphuserFlowApiConnectorConfiguration -Property @{ + postAttributeCollectionConnectorName = 'FakeConnector1' + postFederationSignupConnectorName = 'FakeConnector2' + } -ClientOnly) + Id = "FakeStringValue" + IdentityProviders = @("Provider1", "Provider2") + UserAttributeAssignments = @((New-CimInstance -ClassName MSFT_MicrosoftGraphuserFlowUserAttributeAssignment -Property @{ + UserInputType = 'textBox' + IsOptional = $True + DisplayName = 'Email Address' + Id = 'emailReadonly' + UserAttributeValues = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_MicrosoftGraphuserFlowUserAttributeAssignment -Property @{ + IsDefault = $True + Name = 'S' + Value = '2' + } -ClientOnly + ) + } -ClientOnly)) + Ensure = "Absent" + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaIdentityB2XUserFlow -MockWith { + return @{ + id = "FakeStringValue" + } + } + + Mock -CommandName Get-MgBetaIdentityB2XUserFlowIdentityProvider -MockWith { + return @( + @{ + id = "Provider1" + }, + @{ + id = "Provider2" + } + ) + } + + Mock -CommandName Get-MgBetaIdentityB2XUserFlowApiConnectorConfiguration -MockWith { + return @{ + PostFederationSignup = [PSCustomObject]@{ + DisplayName = "FakeConnector2" + } + PostAttributeCollection = [PSCustomObject]@{ + DisplayName = "FakeConnector1" + } + } + } + + Mock -CommandName Get-MgBetaIdentityB2XUserFlowUserAttributeAssignment -MockWith { + return @( + [PSCustomObject]@{ + UserInputType = 'textBox' + IsOptional = $True + DisplayName = 'Email Address' + Id = 'emailReadonly' + UserAttributeValues = @( + [PSCustomObject]@{ + IsDefault = $True + Name = 'S' + Value = '2' + } + ) + } + ) + } + } + + 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-MgBetaIdentityB2XUserFlow -Exactly 1 + } + } + Context -Name "The AADIdentityB2XUserFlow Exists and Values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ApiConnectorConfiguration = (New-CimInstance -ClassName MSFT_MicrosoftGraphuserFlowApiConnectorConfiguration -Property @{ + postAttributeCollectionConnectorName = 'FakeConnector1' + postFederationSignupConnectorName = 'FakeConnector2' + } -ClientOnly) + Id = "FakeStringValue" + IdentityProviders = @("Provider1", "Provider2") + UserAttributeAssignments = @((New-CimInstance -ClassName MSFT_MicrosoftGraphuserFlowUserAttributeAssignment -Property @{ + UserInputType = 'textBox' + IsOptional = $True + DisplayName = 'Email Address' + Id = 'emailReadonly' + UserAttributeValues = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_MicrosoftGraphuserFlowUserAttributeAssignment -Property @{ + IsDefault = $True + Name = 'S' + Value = '2' + } -ClientOnly + ) + } -ClientOnly)) + Ensure = "Present" + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaIdentityB2XUserFlow -MockWith { + return @{ + id = "FakeStringValue" + } + } + + Mock -CommandName Get-MgBetaIdentityB2XUserFlowIdentityProvider -MockWith { + return @( + @{ + id = "Provider1" + }, + @{ + id = "Provider2" + } + ) + } + + Mock -CommandName Get-MgBetaIdentityB2XUserFlowApiConnectorConfiguration -MockWith { + return @{ + PostFederationSignup = [PSCustomObject]@{ + DisplayName = "FakeConnector2" + } + PostAttributeCollection = [PSCustomObject]@{ + DisplayName = "FakeConnector1" + } + } + } + + Mock -CommandName Get-MgBetaIdentityB2XUserFlowUserAttributeAssignment -MockWith { + return @( + [PSCustomObject]@{ + UserInputType = 'textBox' + IsOptional = $True + DisplayName = 'Email Address' + Id = 'emailReadonly' + UserAttributeValues = @( + [PSCustomObject]@{ + IsDefault = $True + Name = 'S' + Value = '2' + } + ) + } + ) + } + } + + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The AADIdentityB2XUserFlow exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ApiConnectorConfiguration = (New-CimInstance -ClassName MSFT_MicrosoftGraphuserFlowApiConnectorConfiguration -Property @{ + postAttributeCollectionConnectorName = 'FakeConnector1' + postFederationSignupConnectorName = 'FakeConnector2' + } -ClientOnly) + Id = "FakeStringValue" + IdentityProviders = @("Provider1", "Provider2") + UserAttributeAssignments = @((New-CimInstance -ClassName MSFT_MicrosoftGraphuserFlowUserAttributeAssignment -Property @{ + UserInputType = 'dropdownSingleSelect' + IsOptional = $True + DisplayName = 'Email Address' + Id = 'emailReadonly' + UserAttributeValues = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_MicrosoftGraphuserFlowUserAttributeAssignment -Property @{ + IsDefault = $True + Name = 'Z' + Value = '2' + } -ClientOnly + ) + } -ClientOnly), + (New-CimInstance -ClassName MSFT_MicrosoftGraphuserFlowUserAttributeAssignment -Property @{ + UserInputType = 'textBox' + IsOptional = $True + DisplayName = 'Surname' + Id = 'surname' + UserAttributeValues = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_MicrosoftGraphuserFlowUserAttributeAssignment -Property @{ + IsDefault = $True + Name = 'S' + Value = '2' + } -ClientOnly + ) + } -ClientOnly)) + Ensure = "Present" + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaIdentityB2XUserFlow -MockWith { + return @{ + id = "FakeStringValue" + } + } + + Mock -CommandName Get-MgBetaIdentityApiConnector -MockWith { + return @{ + id = "FakeStringValue" + } + } + + Mock -CommandName Get-MgBetaIdentityB2XUserFlowIdentityProvider -MockWith { + return @( + @{ + id = "Provider3" + }, + @{ + id = "Provider2" + } + ) + } + + Mock -CommandName Get-MgBetaIdentityB2XUserFlowApiConnectorConfiguration -MockWith { + return @{ + PostFederationSignup = [PSCustomObject]@{ + DisplayName = "FakeConnector2" + } + PostAttributeCollection = [PSCustomObject]@{ + DisplayName = "FakeConnector1" + } + } + } + + Mock -CommandName Get-MgBetaIdentityB2XUserFlowUserAttributeAssignment -MockWith { + return @( + [PSCustomObject]@{ + UserInputType = 'textBox' + IsOptional = $True + DisplayName = 'Email Address' + Id = 'emailReadonly' + UserAttributeValues = @( + [PSCustomObject]@{ + IsDefault = $True + Name = 'S' + Value = '2' + } + ) + }, + [PSCustomObject]@{ + UserInputType = 'textBox' + IsOptional = $True + DisplayName = 'City' + Id = 'city' + UserAttributeValues = @( + [PSCustomObject]@{ + IsDefault = $True + Name = 'S' + Value = '2' + } + ) + } + ) + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-MgBetaIdentityB2XUserFlowIdentityProviderByRef -Exactly 1 + Should -Invoke -CommandName Remove-MgBetaIdentityB2XUserFlowIdentityProviderByRef -Exactly 1 + Should -Invoke -CommandName Set-MgBetaIdentityB2XUserFlowPostFederationSignupByRef -Exactly 1 + Should -Invoke -CommandName Set-MgBetaIdentityB2XUserFlowPostAttributeCollectionByRef -Exactly 1 + Should -Invoke -CommandName New-MgBetaIdentityB2XUserFlowUserAttributeAssignment -Exactly 1 + Should -Invoke -CommandName Update-MgBetaIdentityB2XUserFlowUserAttributeAssignment -Exactly 1 + Should -Invoke -CommandName Remove-MgBetaIdentityB2XUserFlowUserAttributeAssignment -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + + Mock -CommandName Get-MgBetaIdentityB2XUserFlow -MockWith { + return @{ + id = "FakeStringValue" + } + } + + Mock -CommandName Get-MgBetaIdentityApiConnector -MockWith { + return @{ + id = "FakeStringValue" + } + } + + Mock -CommandName Get-MgBetaIdentityB2XUserFlowIdentityProvider -MockWith { + return @( + @{ + id = "Provider3" + }, + @{ + id = "Provider2" + } + ) + } + + Mock -CommandName Get-MgBetaIdentityB2XUserFlowApiConnectorConfiguration -MockWith { + return @{ + PostFederationSignup = [PSCustomObject]@{ + DisplayName = "FakeConnector2" + } + PostAttributeCollection = [PSCustomObject]@{ + DisplayName = "FakeConnector1" + } + } + } + + Mock -CommandName Get-MgBetaIdentityB2XUserFlowUserAttributeAssignment -MockWith { + return @( + [PSCustomObject]@{ + UserInputType = 'textBox' + IsOptional = $True + DisplayName = 'Email Address' + Id = 'emailReadonly' + UserAttributeValues = @( + [PSCustomObject]@{ + IsDefault = $True + Name = 'S' + Value = '2' + } + ) + }, + [PSCustomObject]@{ + UserInputType = 'textBox' + IsOptional = $True + DisplayName = 'City' + Id = 'city' + UserAttributeValues = @( + [PSCustomObject]@{ + IsDefault = $True + Name = 'S' + Value = '2' + } + ) + } + ) + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index cdcf592740..7d0f828598 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -97638,3 +97638,569 @@ function Invoke-PnPSPRestMethod $Content ) } + +#region MgBetaIdentityB2XUserFlow +function Get-MgBetaIdentityB2XUserFlow +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $B2XIdentityUserFlowId, + + [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-MgBetaIdentityB2XUserFlow +{ + [CmdletBinding()] + param + ( + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [PSObject] + $ApiConnectorConfiguration, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [PSObject[]] + $IdentityProviders, + + [Parameter()] + [PSObject[]] + $Languages, + + [Parameter()] + [PSObject[]] + $UserAttributeAssignments, + + [Parameter()] + [PSObject[]] + $UserFlowIdentityProviders, + + [Parameter()] + [System.String] + $UserFlowType, + + [Parameter()] + [System.Single] + $UserFlowTypeVersion, + + [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-MgBetaIdentityB2XUserFlow +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $B2XIdentityUserFlowId, + + [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-MgBetaIdentityB2XUserFlow +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $B2XIdentityUserFlowId, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [PSObject] + $ApiConnectorConfiguration, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [PSObject[]] + $IdentityProviders, + + [Parameter()] + [PSObject[]] + $Languages, + + [Parameter()] + [PSObject[]] + $UserAttributeAssignments, + + [Parameter()] + [PSObject[]] + $UserFlowIdentityProviders, + + [Parameter()] + [System.String] + $UserFlowType, + + [Parameter()] + [System.Single] + $UserFlowTypeVersion, + + [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 + +#region MgBetaIdentityB2XUserFlowApiConnectorConfiguration +function Get-MgBetaIdentityB2XUserFlowApiConnectorConfiguration +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $B2XIdentityUserFlowId, + + [Parameter()] + [System.String[]] + $ExpandProperty + ) +} + +function Set-MgBetaIdentityB2XUserFlowPostFederationSignupByRef +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $B2XIdentityUserFlowId, + + [Parameter()] + [PSObject] + $BodyParameter + ) +} + +function Set-MgBetaIdentityB2XUserFlowPostAttributeCollectionByRef +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $B2XIdentityUserFlowId, + + [Parameter()] + [PSObject] + $BodyParameter + ) +} +#endregion + +#region MgBetaIdentityB2XUserFlowUserAttributeAssignment +function Get-MgBetaIdentityB2XUserFlowUserAttributeAssignment +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $B2XIdentityUserFlowId, + + [Parameter()] + [System.String[]] + $ExpandProperty + ) +} + +function New-MgBetaIdentityB2XUserFlowUserAttributeAssignment +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $B2XIdentityUserFlowId, + + [Parameter()] + [PSObject] + $BodyParameter + ) +} + +function Update-MgBetaIdentityB2XUserFlowUserAttributeAssignment +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $B2XIdentityUserFlowId, + + [Parameter()] + [System.String] + $IdentityUserFlowAttributeAssignmentId, + + [Parameter()] + [PSObject] + $BodyParameter + ) +} + +function Remove-MgBetaIdentityB2XUserFlowUserAttributeAssignment +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $B2XIdentityUserFlowId, + + [Parameter()] + [System.String] + $IdentityUserFlowAttributeAssignmentId + ) +} + +#endregion + +#region MgBetaIdentityB2XUserFlowIdentityProvider +function Get-MgBetaIdentityB2XUserFlowIdentityProvider +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $B2XIdentityUserFlowId, + + [Parameter()] + [System.String[]] + $ExpandProperty + ) +} + +function New-MgBetaIdentityB2XUserFlowIdentityProviderByRef +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $B2XIdentityUserFlowId, + + [Parameter()] + [PSObject] + $BodyParameter + ) +} + +function Remove-MgBetaIdentityB2XUserFlowIdentityProviderByRef +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $B2XIdentityUserFlowId, + + [Parameter()] + [System.String] + $IdentityProviderBaseId + ) +} +#endregion + +function Get-MgBetaIdentityApiConnector +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $IdentityApiConnectorId, + + [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 + ) +}