forked from d365collaborative/d365fo.tools
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request d365collaborative#807 from Splaxi/impl-dataverse-t…
…ester Impl dataverse tester
- Loading branch information
Showing
8 changed files
with
385 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
|
||
<# | ||
.SYNOPSIS | ||
Test the dataverse connection | ||
.DESCRIPTION | ||
Invokes the built-in http communication endpount, that validates the connection between the D365FO environment and dataverse | ||
.PARAMETER BinDir | ||
The path to the bin directory for the environment | ||
Default path is the same as the aos service PackagesLocalDirectory\bin | ||
.EXAMPLE | ||
PS C:\> Test-D365DataverseConnection | ||
This will invoke the http communication component, that validates the basic settings between D365FO and Dataverse. | ||
It will output the raw details from the call, to make it easier to troubleshoot the connectivity between D365FO and Dataverse. | ||
.NOTES | ||
General notes | ||
#> | ||
function Test-D365DataverseConnection { | ||
[CmdletBinding(DefaultParameterSetName = 'Default')] | ||
param ( | ||
[string] $BinDir = "$Script:BinDir\bin" | ||
) | ||
|
||
begin { | ||
} | ||
|
||
process { | ||
$cdsApiPath = "sdkmessages"; | ||
$httpCommunicationDllPath = Join-Path -Path $BinDir -ChildPath "Microsoft.Dynamics.HttpCommunication.dll" | ||
|
||
if (-not (Test-PathExists -Path $httpCommunicationDllPath -Type Leaf)) { | ||
return | ||
} | ||
|
||
Write-PSFMessage -Level Verbose -Message "Loading the 'Microsoft.Dynamics.HttpCommunication.dll' file into the current session." | ||
Add-Type -Path $httpCommunicationDllPath | ||
|
||
try { | ||
Write-PSFMessage -Level Verbose -Message "Building the logger object, to handle the output from the test." | ||
$assembly = [System.Reflection.Assembly]::LoadFile($httpCommunicationDllPath) | ||
$loggerType = $assembly.GetType("Microsoft.Dynamics.HttpCommunication.Logging.InMemoryLogger") | ||
$bindingFlags = [System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::Public | ||
$loggerConstructor = $loggerType.GetConstructor($bindingFlags, $null, [System.Type]::EmptyTypes, $null) | ||
$logger = $loggerConstructor.Invoke($null) | ||
|
||
Write-PSFMessage -Level Verbose -Message "Building the client/request object, to execute the test / validation." | ||
$cdsWebApiClient = New-Object Microsoft.Dynamics.HttpCommunication.Cds.CdsWebApiClient $logger; | ||
$bindingFlags = [System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::NonPublic | ||
$method = [Microsoft.Dynamics.HttpCommunication.Cds.CdsWebApiClient].GetMethod("GetWithStringResponse", $bindingFlags, $null, @([string]), $null) | ||
|
||
Write-PSFMessage -Level Verbose -Message "Invoking the test / validation request." | ||
$task = $method.Invoke($cdsWebApiClient, @($cdsApiPath)) | ||
$response = $task.GetAwaiter().GetResult() | ||
|
||
$response | ||
} | ||
catch { | ||
Write-PSFHostColor -String $logger.LogContent.ToString() -DefaultColor Red | ||
|
||
if ($logger.LogContent.ToString() -like '*Cannot Find Thumbprint by Certificatename*') { | ||
Write-PSFMessage -Level Host -Message "The <c='em'>'Cannot Find Thumbprint by Certificatename'</c> indicates that you need to run the <c='em'>'New-D365EntraIntegration'</c> cmdlet." | ||
Write-PSFMessage -Level Host -Message "You should read the following links: <c='em'>https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/dev-tools/secure-developer-vm#external-integrations</c> and <c='em'>https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/business-events/che-be-ve-error</c>." | ||
Stop-PSFFunction -Message "Stopping because the 'Cannot Find Thumbprint by Certificatename' error was encounted" | ||
return | ||
} | ||
elseif ($logger.LogContent.ToString() -like '*Expected aud https://securityservice.operations365.dynamics.com*') { | ||
Write-PSFMessage -Level Host -Message "The <c='em'>'Expected aud https://securityservice.operations365.dynamics.com'</c> indicates that you need to configure Azure Entra (Registered Application) between your <c='em'>D365FO</c> environment and the connected <c='em'>Dataverse</c> environment." | ||
Write-PSFMessage -Level Host -Message "You should read the following link: <c='em'>https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/business-events/che-be-ve-error</c>." | ||
Stop-PSFFunction -Message "Stopping because the 'Cannot Find Thumbprint by Certificatename' error was encounted" | ||
return | ||
} | ||
} | ||
} | ||
|
||
end { | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
|
||
<# | ||
.SYNOPSIS | ||
Test the Entra Id integration | ||
.DESCRIPTION | ||
Validates the configuration of the web.config file and the certificate for the environment | ||
If any of the configuration is missing or in someway incorrect, it will prompt and stating corrective actions needed | ||
.EXAMPLE | ||
PS C:\> Test-D365EntraIntegration | ||
This will validate the settings inside the web.config file. | ||
It will search for Aad.Realm, Infrastructure.S2SCertThumbprint, GraphApi.GraphAPIServicePrincipalCert | ||
It will search for the certificate that matches the thumbprint. | ||
A result set example: | ||
EntraAppId Thumbprint Subject Expiration | ||
---------- ---------- ------- ---------- | ||
e068e004-8bec-48c3-a36f-2ab4982ee738 0768175DF3DFDEA3FA78925ADC1E588707649335 CN=CHEAuth 2/5/2026 8:09:28 AM | ||
.NOTES | ||
Based on: https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/dev-tools/secure-developer-vm#external-integrations | ||
Author: Mötz Jensen (@Splaxi) | ||
#> | ||
function Test-D365EntraIntegration { | ||
param ( | ||
) | ||
|
||
if (-not ($Script:IsAdminRuntime)) { | ||
Write-PSFMessage -Level Critical -Message "It seems that you ran this cmdlet <c='em'>non-elevated</c>. Testing the Entra integration requires you to run this cmdlet from an elevated console. Please exit the current console and start a new with `"Run As Administrator`"" | ||
Stop-PSFFunction -Message "Stopping because the function is not run elevated" | ||
return | ||
} | ||
|
||
$webConfigFile = Join-Path -Path $Script:AOSPath $Script:WebConfig | ||
|
||
if (-not (Test-PathExists -Path $webConfigFile -Type Leaf -ErrorAction SilentlyContinue -WarningAction SilentlyContinue)) { | ||
Write-PSFMessage -Level Host -Message "Unable to find the web.config file." | ||
Stop-PSFFunction -Message "Stopping because the web.config file could not be found" | ||
} | ||
|
||
$config = @{} | ||
|
||
[xml]$xml = Get-Content $webConfigFile | ||
$nodes = ($xml.configuration.appSettings).ChildNodes | ||
|
||
$config.AadRealm = $nodes | Where-Object -Property Key -eq "Aad.Realm" | Select-Object -First 1 -ExpandProperty value | ||
$config.S2SCertThumbprint = $nodes | Where-Object -Property Key -eq "Infrastructure.S2SCertThumbprint" | Select-Object -First 1 -ExpandProperty value | ||
$config.GraphAPIServicePrincipalCert = $nodes | Where-Object -Property Key -eq "GraphApi.GraphAPIServicePrincipalCert" | Select-Object -First 1 -ExpandProperty value | ||
|
||
if ([System.String]::IsNullOrWhiteSpace($config.AadRealm)) { | ||
Write-PSFMessage -Level Host -Message "The <c='em'>'Aad.Realm'</c> value is empty. This indicates that you need to run the <c='em'>'New-D365EntraIntegration'</c> cmdlet." | ||
Stop-PSFFunction -Message "Stopping because the 'Aad.Realm' value is empty" | ||
} | ||
|
||
if ([System.String]::IsNullOrWhiteSpace($config.S2SCertThumbprint)) { | ||
Write-PSFMessage -Level Host -Message "The <c='em'>'Infrastructure.S2SCertThumbprint'</c> value is empty. This indicates that you need to run the <c='em'>'New-D365EntraIntegration'</c> cmdlet." | ||
Stop-PSFFunction -Message "Stopping because the 'Infrastructure.S2SCertThumbprint' value is empty" | ||
} | ||
|
||
if ([System.String]::IsNullOrWhiteSpace($config.GraphAPIServicePrincipalCert)) { | ||
Write-PSFMessage -Level Host -Message "The <c='em'>'GraphApi.GraphAPIServicePrincipalCert'</c> value is empty. This indicates that you need to run the <c='em'>'New-D365EntraIntegration'</c> cmdlet." | ||
Stop-PSFFunction -Message "Stopping because the 'GraphApi.GraphAPIServicePrincipalCert' value is empty" | ||
} | ||
|
||
if ((-not [System.String]::IsNullOrWhiteSpace($config.S2SCertThumbprint)) -and $config.S2SCertThumbprint -ne $config.GraphAPIServicePrincipalCert) { | ||
Write-PSFMessage -Level Host -Message "The <c='em'>'Infrastructure.S2SCertThumbprint'</c> and the <c='em'>'GraphApi.GraphAPIServicePrincipalCert'</c> value doesn't match each other. This indicates that you a <c='em'>corrupted</c> configuration. Running the <c='em'>'New-D365EntraIntegration'</c> cmdlet could assist with fixing the configuration." | ||
Stop-PSFFunction -Message "Stopping because the 'Infrastructure.S2SCertThumbprint' and 'GraphApi.GraphAPIServicePrincipalCert' values doesn't match" | ||
} | ||
|
||
if (Test-PSFFunctionInterrupt) { return } | ||
|
||
$certStoreLocation = "Cert:\LocalMachine\My" | ||
|
||
$certEntra = Get-ChildItem -Path $certStoreLocation -ErrorAction SilentlyContinue | Where-Object { $_.Thumbprint -eq $config.S2SCertThumbprint } | Select-Object -First 1 | ||
|
||
if ($null -eq $certEntra) { | ||
Write-PSFMessage -Level Host -Message "Unable to find any certificate in the certificate store <c='em'>'$certStoreLocation'</c> that matches the thumbprint <c='em'>'$($config.S2SCertThumbprint)'</c>." | ||
Stop-PSFFunction -Message "Stopping because no certificate matching the thumbprint was found" | ||
return | ||
} | ||
|
||
[PSCustomObject][ordered]@{ | ||
EntraAppId = $config.AadRealm.replace("spn:", "") | ||
Thumbprint = $config.S2SCertThumbprint | ||
Subject = $certEntra.Subject | ||
Expiration = $certEntra.NotAfter | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
d365fo.tools/tests/functions/Test-D365DataverseConnection.Tests.ps1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
Describe "Test-D365DataverseConnection Unit Tests" -Tag "Unit" { | ||
BeforeAll { | ||
# Place here all things needed to prepare for the tests | ||
} | ||
AfterAll { | ||
# Here is where all the cleanup tasks go | ||
} | ||
|
||
Describe "Ensuring unchanged command signature" { | ||
It "should have the expected parameter sets" { | ||
(Get-Command Test-D365DataverseConnection).ParameterSets.Name | Should -Be 'Default' | ||
} | ||
|
||
It 'Should have the expected parameter BinDir' { | ||
$parameter = (Get-Command Test-D365DataverseConnection).Parameters['BinDir'] | ||
$parameter.Name | Should -Be 'BinDir' | ||
$parameter.ParameterType.ToString() | Should -Be System.String | ||
$parameter.IsDynamic | Should -Be $False | ||
$parameter.ParameterSets.Keys | Should -Be '__AllParameterSets' | ||
$parameter.ParameterSets.Keys | Should -Contain '__AllParameterSets' | ||
$parameter.ParameterSets['__AllParameterSets'].IsMandatory | Should -Be $False | ||
$parameter.ParameterSets['__AllParameterSets'].Position | Should -Be 0 | ||
$parameter.ParameterSets['__AllParameterSets'].ValueFromPipeline | Should -Be $False | ||
$parameter.ParameterSets['__AllParameterSets'].ValueFromPipelineByPropertyName | Should -Be $False | ||
$parameter.ParameterSets['__AllParameterSets'].ValueFromRemainingArguments | Should -Be $False | ||
} | ||
} | ||
|
||
Describe "Testing parameterset Default" { | ||
<# | ||
Default - | ||
Default -BinDir | ||
#> | ||
} | ||
|
||
} |
24 changes: 24 additions & 0 deletions
24
d365fo.tools/tests/functions/Test-D365EntraIntegration.Tests.ps1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
Describe "Test-D365EntraIntegration Unit Tests" -Tag "Unit" { | ||
BeforeAll { | ||
# Place here all things needed to prepare for the tests | ||
} | ||
AfterAll { | ||
# Here is where all the cleanup tasks go | ||
} | ||
|
||
Describe "Ensuring unchanged command signature" { | ||
It "should have the expected parameter sets" { | ||
(Get-Command Test-D365EntraIntegration).ParameterSets.Name | Should -Be '__AllParameterSets' | ||
} | ||
|
||
|
||
} | ||
|
||
Describe "Testing parameterset __AllParameterSets" { | ||
<# | ||
__AllParameterSets - | ||
__AllParameterSets - | ||
#> | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
--- | ||
external help file: d365fo.tools-help.xml | ||
Module Name: d365fo.tools | ||
online version: | ||
schema: 2.0.0 | ||
--- | ||
|
||
# Test-D365DataverseConnection | ||
|
||
## SYNOPSIS | ||
Test the dataverse connection | ||
|
||
## SYNTAX | ||
|
||
``` | ||
Test-D365DataverseConnection [[-BinDir] <String>] [<CommonParameters>] | ||
``` | ||
|
||
## DESCRIPTION | ||
Invokes the built-in http communication endpount, that validates the connection between the D365FO environment and dataverse | ||
|
||
## EXAMPLES | ||
|
||
### EXAMPLE 1 | ||
``` | ||
Test-D365DataverseConnection | ||
``` | ||
|
||
This will invoke the http communication component, that validates the basic settings between D365FO and Dataverse. | ||
It will output the raw details from the call, to make it easier to troubleshoot the connectivity between D365FO and Dataverse. | ||
|
||
## PARAMETERS | ||
|
||
### -BinDir | ||
The path to the bin directory for the environment | ||
|
||
Default path is the same as the aos service PackagesLocalDirectory\bin | ||
|
||
```yaml | ||
Type: String | ||
Parameter Sets: (All) | ||
Aliases: | ||
|
||
Required: False | ||
Position: 1 | ||
Default value: "$Script:BinDir\bin" | ||
Accept pipeline input: False | ||
Accept wildcard characters: False | ||
``` | ||
### CommonParameters | ||
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). | ||
## INPUTS | ||
## OUTPUTS | ||
## NOTES | ||
General notes | ||
## RELATED LINKS |
Oops, something went wrong.