diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b25814bdd..baae0e73ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,8 @@ * Initial release. * AADSocialIdentityProvider * Fixed missing permissions in settings.json +* AADVerifiedIdAuthority + * Initial release. * AzureBillingAccountsAssociatedTenant * Initial release. * AzureBillingAccountsRoleAssignment diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADVerifiedIdAuthority/MSFT_AADVerifiedIdAuthority.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADVerifiedIdAuthority/MSFT_AADVerifiedIdAuthority.psm1 new file mode 100644 index 0000000000..e986ac2baf --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADVerifiedIdAuthority/MSFT_AADVerifiedIdAuthority.psm1 @@ -0,0 +1,591 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [System.String] + $Id, + + [Parameter()] + [System.String] + $Name, + + [Parameter(Mandatory = $true)] + [System.String] + $LinkedDomainUrl, + + [Parameter()] + [System.String] + $DidMethod, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $KeyVaultMetadata, + + [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 + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'AdminAPI' ` + -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' + try + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + $instances = $Script:exportedInstances + } + else + { + $uri = "https://verifiedid.did.msidentity.com/v1.0/verifiableCredentials/authorities" + $response = Invoke-M365DSCVerifiedIdWebRequest -Uri $uri -Method 'GET' + $instances = $response.value + } + if ($null -eq $instances) + { + return $nullResult + } + + $instance = Get-M365DSCVerifiedIdAuthorityObject -Authority ($instances | Where-Object -FilterScript {$_.didModel.linkedDomainUrls[0] -eq $LinkedDomainUrl}) + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + Id = $instance.Id + Name = $instance.Name + LinkedDomainUrl = $instance.LinkedDomainUrl + DidMethod = $instance.DidMethod + KeyVaultMetadata = $instance.KeyVaultMetadata + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ApplicationSecret = $ApplicationSecret + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + + } + catch + { + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [System.String] + $Id, + + [Parameter()] + [System.String] + $Name, + + [Parameter(Mandatory = $true)] + [System.String] + $LinkedDomainUrl, + + [Parameter()] + [System.String] + $DidMethod, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $KeyVaultMetadata, + + [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 + + New-M365DSCConnection -Workload 'AdminAPI' ` + -InboundParameters $PSBoundParameters | Out-Null + + $currentInstance = Get-TargetResource @PSBoundParameters + + Write-Verbose -Message "Retrieved current instance: $($currentInstance.Name) with Id $($currentInstance.Id)" + $BoundParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + $uri = "https://verifiedid.did.msidentity.com/v1.0/verifiableCredentials/authorities/" + $currentInstance.Id + + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + Write-Verbose -Message "Creating an VerifiedId Authority with Name {$Name} and Id $($currentInstance.Id)" + + $body = @{ + name = $Name + linkedDomainUrl = $LinkedDomainUrl + didMethod = $DidMethod + keyVaultMetadata = @{ + subscriptionId = $KeyVaultMetadata.SubscriptionId + resourceGroup = $KeyVaultMetadata.ResourceGroup + resourceName = $KeyVaultMetadata.ResourceName + resourceUrl = $KeyVaultMetadata.ResourceUrl + } + } + Write-Verbose -Message "Creating VerifiedId Authority with body $($body | ConvertTo-Json -Depth 5)" + + $uri = "https://verifiedid.did.msidentity.com/v1.0/verifiableCredentials/authorities" + Invoke-M365DSCVerifiedIdWebRequest -Uri $uri -Method 'POST' -Body $body + } + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Updating an VerifiedId Authority with Name {$Name} and Id $($currentInstance.Id)" + + Write-Warning -Message "You can only update Name of the VerifiedId Authority, if you want to update other properties, please delete and recreate the VerifiedId Authority." + $body = @{ + name = $Name + } + Invoke-M365DSCVerifiedIdWebRequest -Uri $uri -Method 'PATCH' -Body $body + } + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Removing VerifiedId Authority with Name {$Name} and Id $($currentInstance.Id)" + + $uri = "https://verifiedid.did.msidentity.com/beta/verifiableCredentials/authorities/" + $currentInstance.Id + Invoke-M365DSCVerifiedIdWebRequest -Uri $uri -Method 'DELETE' + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [System.String] + $Id, + + [Parameter()] + [System.String] + $Name, + + [Parameter(Mandatory = $true)] + [System.String] + $LinkedDomainUrl, + + [Parameter()] + [System.String] + $DidMethod, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $KeyVaultMetadata, + + [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 AADVerifiedIdAuthority' + + $CurrentValues = Get-TargetResource @PSBoundParameters + + $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() + + $testTargetResource = $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*' -and $source -notlike '*Permission*') + { + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + if (-not $testResult) + { + Write-Verbose "TestResult returned False for $source" + $testTargetResource = $false + } + else { + $ValuesToCheck.Remove($key) | Out-Null + } + } + } + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + + $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys ` + -IncludedDrifts $driftedParams + + if(-not $TestResult) + { + $testTargetResource = $false + } + + + Write-Verbose -Message "Test-TargetResource returned $testTargetResource" + + return $testTargetResource + + +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'AdminAPI' ` + -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 + + $dscContent = [System.Text.StringBuilder]::new() + $i = 1 + Write-Host "`r`n" -NoNewline + try + { + $Script:ExportMode = $true + $uri = "https://verifiedid.did.msidentity.com/v1.0/verifiableCredentials/authorities" + $response = Invoke-M365DSCVerifiedIdWebRequest -Uri $uri -Method 'GET' + [array] $Script:exportedInstances = $response.value + + foreach ($authority in $Script:exportedInstances) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $($authority.didModel.linkedDomainUrls[0])" -NoNewline + $Params = @{ + LinkedDomainUrl = $authority.didModel.linkedDomainUrls[0] + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ApplicationSecret = $ApplicationSecret + Credential = $Credential + Managedidentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + $Results = Get-TargetResource @Params + if ($Results.Ensure -eq 'Present') + { + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + if ($null -ne $Results.KeyVaultMetadata) + { + $complexMapping = @( + @{ + Name = 'KeyVaultMetadata' + CimInstanceName = 'AADVerifiedIdAuthorityKeyVaultMetadata' + IsRequired = $False + } + ) + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.KeyVaultMetadata ` + -CIMInstanceName 'AADVerifiedIdAuthorityKeyVaultMetadata' ` + -ComplexTypeMapping $complexMapping + + if (-not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.KeyVaultMetadata = $complexTypeStringResult + } + else + { + $Results.Remove('KeyVaultMetadata') | Out-Null + } + } + + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + + if ($Results.KeyVaultMetadata) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "KeyVaultMetadata" -IsCIMArray:$False + } + + $dscContent.Append($currentDSCBlock) | Out-Null + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + Write-Host $Global:M365DSCEmojiGreenCheckMark + $i++ + } + } + return $dscContent.ToString() + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + + +function Get-M365DSCVerifiedIdAuthorityObject +{ + [CmdletBinding()] + [OutputType([PSCustomObject])] + param( + [Parameter()] + $Authority + ) + + if ($null -eq $Authority) + { + return $null + } + + Write-Verbose -Message "Retrieving values for authority {$($Authority.didModel.linkedDomainUrls[0])}" + $did = ($Authority.didModel.did -split ":")[1] + $values = @{ + Id = $Authority.Id + Name = $Authority.Name + LinkedDomainUrl = $Authority.didModel.linkedDomainUrls[0] + DidMethod = $did + } + if ($null -ne $Authority.KeyVaultMetadata) + { + $KeyVaultMetadata = @{ + SubscriptionId = $Authority.KeyVaultMetadata.SubscriptionId + ResourceGroup = $Authority.KeyVaultMetadata.ResourceGroup + ResourceName = $Authority.KeyVaultMetadata.ResourceName + ResourceUrl = $Authority.KeyVaultMetadata.ResourceUrl + } + + $values.Add('KeyVaultMetadata', $KeyVaultMetadata) + } + return $values +} + +function Invoke-M365DSCVerifiedIdWebRequest +{ + [OutputType([PSCustomObject])] + [CmdletBinding()] + param( + [Parameter(Mandatory = $true)] + [System.String] + $Uri, + + [Parameter()] + [System.String] + $Method = 'GET', + + [Parameter()] + [System.Collections.Hashtable] + $Body + ) + + $headers = @{ + Authorization = $Global:MSCloudLoginConnectionProfile.AdminAPI.AccessToken + "Content-Type" = "application/json" + } + + if($Method -eq 'PATCH' -or $Method -eq 'POST') + { + $BodyJson = $body | ConvertTo-Json + $response = Invoke-WebRequest -Method $Method -Uri $Uri -Headers $headers -Body $BodyJson + } + else { + $response = Invoke-WebRequest -Method $Method -Uri $Uri -Headers $headers + } + + if($Method -eq 'DELETE') + { + return $null + } + $result = ConvertFrom-Json $response.Content + return $result +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADVerifiedIdAuthority/MSFT_AADVerifiedIdAuthority.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADVerifiedIdAuthority/MSFT_AADVerifiedIdAuthority.schema.mof new file mode 100644 index 0000000000..f22542ecdd --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADVerifiedIdAuthority/MSFT_AADVerifiedIdAuthority.schema.mof @@ -0,0 +1,28 @@ +[ClassVersion("1.0.0")] +class MSFT_AADVerifiedIdAuthorityKeyVaultMetadata +{ + [Write, Description("Subscription ID of the Key Vault.")] String SubscriptionId; + [Write, Description("Resource group of the Key Vault.")] String ResourceGroup; + [Write, Description("Resource name of the Key Vault.")] String ResourceName; + [Write, Description("Resource URL of the Key Vault.")] String ResourceUrl; +}; + + +[ClassVersion("1.0.0.0"), FriendlyName("AADVerifiedIdAuthority")] +class MSFT_AADVerifiedIdAuthority : OMI_BaseResource +{ + [Write, Description("Name of the Verified ID Authority.")] String Name; + [Write, Description("Id of the Verified ID Authority.")] String Id; + [Key, Description("URL of the linked domain.")] String LinkedDomainUrl; + [Write, Description("DID method used by the Verified ID Authority.")] String DidMethod; + [Write, Description("Key Vault metadata for the Verified ID Authority."), EmbeddedInstance("MSFT_AADVerifiedIdAuthorityKeyVaultMetadata")] String KeyVaultMetadata; + [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_AADVerifiedIdAuthority/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_AADVerifiedIdAuthority/readme.md new file mode 100644 index 0000000000..b68d06b45e --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADVerifiedIdAuthority/readme.md @@ -0,0 +1,8 @@ + +# AADVerifiedIdAuthority + +## Description + +Azure AD Verified Identity Authority +Use the VerifiableCredential.Authority.ReadWrite permission to read and write the authority. +Documentation Link: https://learn.microsoft.com/en-us/entra/verified-id/admin-api#authorities diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADVerifiedIdAuthority/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADVerifiedIdAuthority/settings.json new file mode 100644 index 0000000000..cf3ac1ac16 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADVerifiedIdAuthority/settings.json @@ -0,0 +1,17 @@ +{ + "resourceName": "AADVerifiedIdAuthority", + "description": "This resource configures an Azure AD Verified Identity Authority.", + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + } +} + +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADVerifiedIdAuthority/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADVerifiedIdAuthority/1-Create.ps1 new file mode 100644 index 0000000000..33858258a7 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADVerifiedIdAuthority/1-Create.ps1 @@ -0,0 +1,42 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + AADVerifiedIdAuthority 'AADVerifiedIdAuthority-Contoso' + { + DidMethod = "web"; + Ensure = "Present"; + KeyVaultMetadata = MSFT_AADVerifiedIdAuthorityKeyVaultMetadata{ + SubscriptionId = '2ff65b89-ab22-4489-b84d-e60d1dc30a62' + ResourceName = 'xtakeyvault' + ResourceUrl = 'https://xtakeyvault.vault.azure.net/' + ResourceGroup = 'TBD' + }; + LinkedDomainUrl = "https://nik-charlebois.com/"; + Name = "Contoso"; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADVerifiedIdAuthority/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADVerifiedIdAuthority/2-Update.ps1 new file mode 100644 index 0000000000..8bbd4acd39 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADVerifiedIdAuthority/2-Update.ps1 @@ -0,0 +1,42 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + AADVerifiedIdAuthority 'AADVerifiedIdAuthority-Contoso' + { + DidMethod = "web"; + Ensure = "Present"; + KeyVaultMetadata = MSFT_AADVerifiedIdAuthorityKeyVaultMetadata{ + SubscriptionId = '2ff65b89-ab22-4489-b84d-e60d1dc30a62' + ResourceName = 'xtakeyvault' + ResourceUrl = 'https://xtakeyvault.vault.azure.net/' + ResourceGroup = 'TBD' + }; + LinkedDomainUrl = "https://nik-charlebois.com/"; + Name = "Contoso 2"; # drift + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADVerifiedIdAuthority/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADVerifiedIdAuthority/3-Remove.ps1 new file mode 100644 index 0000000000..9de3d21339 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADVerifiedIdAuthority/3-Remove.ps1 @@ -0,0 +1,42 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + AADVerifiedIdAuthority 'AADVerifiedIdAuthority-Contoso' + { + DidMethod = "web"; + Ensure = "Absent"; + KeyVaultMetadata = MSFT_AADVerifiedIdAuthorityKeyVaultMetadata{ + SubscriptionId = '2ff65b89-ab22-4489-b84d-e60d1dc30a62' + ResourceName = 'xtakeyvault' + ResourceUrl = 'https://xtakeyvault.vault.azure.net/' + ResourceGroup = 'TBD' + }; + LinkedDomainUrl = "https://nik-charlebois.com/"; + Name = "Contoso"; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 467979eece..551c1e7f87 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -1831,7 +1831,7 @@ function New-M365DSCConnection [Parameter(Mandatory = $true)] [ValidateSet('AdminAPI', 'Azure', 'AzureDevOPS', 'Defender', 'ExchangeOnline', 'Fabric', 'Intune', ` 'SecurityComplianceCenter', 'PnP', 'PowerPlatforms', ` - 'MicrosoftTeams', 'MicrosoftGraph', 'SharePointOnlineREST', 'Tasks')] + 'MicrosoftTeams', 'MicrosoftGraph', 'SharePointOnlineREST', 'Tasks', 'AdminAPI')] [System.String] $Workload, diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADVerifiedIdAuthority.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADVerifiedIdAuthority.Tests.ps1 new file mode 100644 index 0000000000..95be94a0da --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADVerifiedIdAuthority.Tests.ps1 @@ -0,0 +1,250 @@ +[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 "AADVerifiedIdAuthority" -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + Mock -CommandName Invoke-WebRequest -MockWith { + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + Context -Name "The AADVerifiedIdAuthority should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + Id = "FakeStringValue" + Name = "FakeStringValue" + LinkedDomainUrl = "FakeStringValue" + DidMethod = "FakeStringValue" + KeyVaultMetadata = (New-CimInstance -ClassName MSFT_AADVerifiedIdAuthorityKeyVaultMetadata -Property @{ + SubscriptionId = "FakeStringValue" + ResourceGroup = "FakeStringValue" + ResourceName = "FakeStringValue" + ResourceUrl = "FakeStringValue" + } -ClientOnly) + Ensure = 'Present' + } + + Mock -CommandName Invoke-M365DSCVerifiedIdWebRequest -MockWith { + return @() + } + + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams -Verbose).Ensure | Should -Be 'Absent' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + It 'Should Create the id from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Invoke-M365DSCVerifiedIdWebRequest -Exactly 2 + } + } + + Context -Name "The AADVerifiedIdAuthority exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + Id = "FakeStringValue" + Name = "FakeStringValue" + LinkedDomainUrl = "FakeStringValue" + DidMethod = "FakeStringValue" + KeyVaultMetadata = (New-CimInstance -ClassName MSFT_AADVerifiedIdAuthorityKeyVaultMetadata -Property @{ + SubscriptionId = "FakeStringValue" + ResourceGroup = "FakeStringValue" + ResourceName = "FakeStringValue" + ResourceUrl = "FakeStringValue" + } -ClientOnly) + Ensure = 'Absent' + } + + Mock -CommandName Invoke-M365DSCVerifiedIdWebRequest -MockWith { + return @{ + value = @( + @{ + id = "FakeStringValue" + name = "FakeStringValue" + didModel = @{ + linkedDomainUrls = @("FakeStringValue") + did = "did: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 Invoke-M365DSCVerifiedIdWebRequest -Exactly 2 + } + } + Context -Name "The AADVerifiedIdAuthority Exists and Values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Id = "FakeStringValue" + Name = "FakeStringValue" + LinkedDomainUrl = "FakeStringValue" + DidMethod = "FakeStringValue" + Ensure = 'Present' + } + + Mock -CommandName Invoke-M365DSCVerifiedIdWebRequest -MockWith { + return @{ + value = @( + @{ + id = "FakeStringValue" + name = "FakeStringValue" + didModel = @{ + linkedDomainUrls = @("FakeStringValue") + did = "did:FakeStringValue" + } + } + ) + } + } + } + + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The AADVerifiedIdAuthority exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Id = "FakeStringValue" + Name = "FakeStringValue2" + LinkedDomainUrl = "FakeStringValue" + DidMethod = "FakeStringValue" + KeyVaultMetadata = (New-CimInstance -ClassName MSFT_AADVerifiedIdAuthorityKeyVaultMetadata -Property @{ + SubscriptionId = "FakeStringValue" + ResourceGroup = "FakeStringValue" + ResourceName = "FakeStringValue" + ResourceUrl = "FakeStringValue" + } -ClientOnly) + Ensure = 'Present' + } + + Mock -CommandName Invoke-M365DSCVerifiedIdWebRequest -MockWith { + return @{ + value = @( + @{ + id = "FakeStringValue" + name = "FakeStringValue" + didModel = @{ + linkedDomainUrls = @("FakeStringValue") + did = "did:FakeStringValue" + } + keyVaultMetadata = @{ + subscriptionId = "FakeStringValue" + resourceGroup = "FakeStringValue" + resourceName = "FakeStringValue" + resourceUrl = "FakeStringValue" + } + } + ) + } + } + } + + 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 Invoke-M365DSCVerifiedIdWebRequest -Exactly 2 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + + Mock -CommandName Invoke-M365DSCVerifiedIdWebRequest -MockWith { + return @{ + value = @( + @{ + id = "FakeStringValue" + name = "FakeStringValue" + didModel = @{ + linkedDomainUrls = @("FakeStringValue") + did = "did:FakeStringValue" + } + keyVaultMetadata = @{ + subscriptionId = "FakeStringValue" + resourceGroup = "FakeStringValue" + resourceName = "FakeStringValue" + resourceUrl = "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