From 504be3d5f2fcb6359b2d87e231af9e42728a3b78 Mon Sep 17 00:00:00 2001 From: ddemeyer Date: Tue, 27 Oct 2026 19:27:37 +0100 Subject: [PATCH 1/3] #282 Implemented, ISHRemote v8.3 will switch to OpenApiWithOpenIdConnect for Tridion Docs 15.0 and up where possible --- Doc/ReleaseNotes-ISHRemote-8.3.md | 1 + .../Cmdlets/Session/NewIshSession.Tests.ps1 | 3 ++- .../Cmdlets/Session/NewIshSession.cs | 14 +++++++------- .../Cmdlets/Session/TestIshSession.cs | 14 +++++++------- .../Trisoft.ISHRemote/Objects/Public/IshSession.cs | 9 ++------- 5 files changed, 19 insertions(+), 22 deletions(-) diff --git a/Doc/ReleaseNotes-ISHRemote-8.3.md b/Doc/ReleaseNotes-ISHRemote-8.3.md index 4a37bf6..ea97608 100644 --- a/Doc/ReleaseNotes-ISHRemote-8.3.md +++ b/Doc/ReleaseNotes-ISHRemote-8.3.md @@ -32,6 +32,7 @@ The below text describes the delta compared to fielded release ISHRemote v8.2. * Migrated all 58 `*.Tests.ps1` files from Pester v5 to Pester v6 (`Should -Be` to `Should-Be`, `Should -BeExactly` to `Should-BeString -CaseSensitive`, `Should -Not -BeNullOrEmpty` to `Should-NotBeNull`, `Should -Throw "msg"` to `Should-Throw -ExceptionMessage "msg"`, etc.). CI install gates updated to `-MinimumVersion 6.0.0`. Classic `Should -Not -Throw` retained as there is no `Should-NotThrow` equivalent in Pester 6. Hardened the library for parallel test execution by replacing the process-wide `TrisoftCmdletLogger` singleton with per-cmdlet `ILogger` routing and adding a double-checked lock on `IshSession._ishTypeFieldSetup` to eliminate Collection was modified races under `Run.Parallel = $true`. CI Pester invocations now use `New-PesterConfiguration` (with `Run.Parallel = $false`) so parallel mode can be toggled in one place when ready. See #242, #265, #266. * Fixed `New-IshSession` (protocol `WcfSoapWithOpenIdConnect`, PowerShell 7.2+/.NET 6.0+) throwing `FileLoadException: Could not load file or assembly 'Microsoft.IdentityModel.Tokens, Version=8.14.0.0, ...'. The located assembly's manifest definition does not match the assembly reference.` on machines where a different build of `Microsoft.IdentityModel.Tokens` (and related `Duende.IdentityModel.OidcClient`) is registered in the Global Assembly Cache (GAC) — observed on machines with Microsoft Intune Management Extension installed. `AppDomainModuleAssemblyInitializer` now force-loads ISHRemote's own bundled copies of `Duende.IdentityModel`, `Duende.IdentityModel.OidcClient`, `Microsoft.IdentityModel.Abstractions/.Logging/.Tokens/.Tokens.Saml/.Xml` as early as possible during module import, and `SessionCmdlet.BeginProcessing` now reports the full forced list over `-Verbose`. Root cause for the `Duende.IdentityModel.OidcClient` variant: `InfoShareOpenIdConnectSystemBrowser` was `public` and implemented `Duende.IdentityModel.OidcClient.Browser.IBrowser`, which put it in `Trisoft.ISHRemote.dll`'s exported types, forcing PowerShell's own binary-module cmdlet discovery (`Assembly.GetExportedTypes()`) to resolve `Duende.IdentityModel.OidcClient` before `IModuleAssemblyInitializer.OnImport()` ever ran — see Breaking Changes - Code. A new `TestPrerequisite.Tests.ps1` check asserts no assembly is ever loaded from the GAC on PowerShell Core. See #272. Thanks @ddemeyer * Fixed cmdlets over protocol `WcfSoapWithOpenIdConnect` occasionally throwing `An unsecured or incorrectly secured fault was received from the other party` on the first SOAP call after a channel fault, requiring the user to re-run the same cmdlet for it to succeed (the existing #201/#219 rebuild-on-next-call logic only kicked in on a second, separate call). Each `Get*25Channel()` method in `InfoShareWcfSoapWithOpenIdConnectConnection` now returns the channel wrapped in a new `RetryOnFaultProxy` (`System.Reflection.DispatchProxy`) that catches `CommunicationException`/`FaultException` on the actual SOAP call, rebuilds the channel via the existing rebuild logic, and retries exactly once within the same cmdlet invocation before propagating any further failure — with the original exception type/stack trace preserved. Requires a new `net48`-only NuGet dependency, `System.Reflection.DispatchProxy` (built into the BCL on `net6.0`/`net10.0`). See #273. Thanks @ddemeyer +* Enhanced `New-IshSession` and `Test-IshSession` protocol `Autodetect` (the default) to select `OpenApiWithOpenIdConnect` on Tridion Docs 15/15.0.0 and later, instead of `WcfSoapWithOpenIdConnect` on earlier ISHRemote versions. Cmdlets already choose between OpenAPI and SOAP per call, so `WcfSoapWithOpenIdConnect` remains the per-cmdlet fallback. An explicit `-Protocol`, including `WcfSoapWithOpenIdConnect`, works as before. See #282. Thanks @ddemeyer * Package bumps, deliberate adding of `System.Security.Cryptography.Xml` to fix vulnerability coming from transitive `System.ServiceModel.Primitives`. See #278 and #279. Thanks @ddemeyer diff --git a/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/Session/NewIshSession.Tests.ps1 b/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/Session/NewIshSession.Tests.ps1 index a94ab98..f5f40e7 100644 --- a/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/Session/NewIshSession.Tests.ps1 +++ b/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/Session/NewIshSession.Tests.ps1 @@ -411,7 +411,8 @@ Describe "New-IshSession" -Tags "Read" { Context "New-IshSession over OpenApiWithOpenIdConnect returns IshSession object" { BeforeAll { if (([Version]$ishSession.ServerVersion).Major -ge 15) { # new service since 15/15.0.0 - $localIShSession = New-IshSession -Protocol OpenApiWithOpenIdConnect -WsBaseUrl $webServicesBaseUrl -ClientId $amClientId -ClientSecret $amClientSecret + # no -Protocol on purpose, so Protocol Autodetect must select OpenApiWithOpenIdConnect on 15/15.0.0 and later + $localIShSession = New-IshSession -WsBaseUrl $webServicesBaseUrl -ClientId $amClientId -ClientSecret $amClientSecret } } It "Local ISHRemoteSessionStateIshSession" { diff --git a/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/Session/NewIshSession.cs b/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/Session/NewIshSession.cs index 345cea4..02a5dfd 100644 --- a/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/Session/NewIshSession.cs +++ b/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/Session/NewIshSession.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2014 All Rights Reserved by the SDL Group. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,7 +29,7 @@ namespace Trisoft.ISHRemote.Cmdlets.Session { /// /// The New-IshSession cmdlet creates a new IshSession object using the parameters that are provided. - /// The communication protocol will be derived from the server-side product version. On 14SP4/14.0.4 plus ISHRemote 7.0 and earlier there is only WcfSoapWithWsTrust. Since 15/15.0.0 ISHRemote prefers Modern Authentication and selects WcfSoapWithOpenIdConnect. Experimental since 15/15.0.0 is OpenApiWithOpenIdConnect, where already possible cmdlets will go over OpenAPI REST calls instead of WcfSoapWithOpenIdConnect calls. + /// The communication protocol will be derived from the server-side product version. On 14SP4/14.0.4 plus ISHRemote 7.0 and earlier there is only WcfSoapWithWsTrust. Since 15/15.0.0 ISHRemote prefers Modern Authentication and selects OpenApiWithOpenIdConnect, where cmdlets with an OpenAPI implementation go over OpenAPI REST calls and all other cmdlets fall back to WcfSoapWithOpenIdConnect calls. /// The New-IshSession cmdlet creates a new IshSession object for usage on any other cmdlet later using the parameters that are provided. /// The object contains the service endpoint proxies, and api contract information like multi-value separator, date format, etc /// @@ -46,7 +46,7 @@ namespace Trisoft.ISHRemote.Cmdlets.Session /// /// Building a session for the chosen service based on implicit authentication. /// Protocol will be WcfSoapWithWsTrust on 14SP4/14.0.4 and earlier systems. An implicit NetworkCredential object will be passed for authentication to the service on PowerShell 5.1 - will throw an error on PowerShell 7.2+. - /// Protocol will be WcfSoapWithOpenIdConnect on 15/15.0.0 and later systems. This will trigger the interactive system browser based flow - so your browser as trusted single sign on client. + /// Protocol will be OpenApiWithOpenIdConnect on 15/15.0.0 and later systems. This will trigger the interactive system browser based flow - so your browser as trusted single sign on client. /// /// /// @@ -60,7 +60,7 @@ namespace Trisoft.ISHRemote.Cmdlets.Session /// $ishSession = New-IshSession -WsBaseUrl "https://example.com/ISHWS/" -PSCredential "Admin" /// /// Protocol will be WcfSoapWithWsTrust on 14SP4/14.0.4 and earlier systems. Iteratively the New-IshSession line with PSCredential parameter holding a string representation will prompt you for a password. - /// Protocol will be WcfSoapWithOpenIdConnect on 15/15.0.0 and later systems. Iteratively the New-IshSession line with PSCredential parameter holding a string representation will prompt you for a ClientSecret. Note that sample 'Admin' as ClientId has to be configured in Access Management (ISHAM), by default ClientId typically is a GUID. + /// Protocol will be OpenApiWithOpenIdConnect on 15/15.0.0 and later systems. Iteratively the New-IshSession line with PSCredential parameter holding a string representation will prompt you for a ClientSecret. Note that sample 'Admin' as ClientId has to be configured in Access Management (ISHAM), by default ClientId typically is a GUID. /// /// /// @@ -77,14 +77,14 @@ namespace Trisoft.ISHRemote.Cmdlets.Session /// /// Extensive automation example based on the PSCredential parameter. Responsibility of the plain text password or client secret is yours. Check Microsoft module https://devblogs.microsoft.com/powershell/secretmanagement-and-secretstore-are-generally-available/ /// Protocol will be WcfSoapWithWsTrust on 14SP4/14.0.4 and earlier systems. - /// Protocol will be WcfSoapWithOpenIdConnect on 15/15.0.0 and later systems. Note that sample 'MYISHUSERNAME' as ClientId has to be configured in Access Management (ISHAM), by default ClientId typically is a GUID. + /// Protocol will be OpenApiWithOpenIdConnect on 15/15.0.0 and later systems. Note that sample 'MYISHUSERNAME' as ClientId has to be configured in Access Management (ISHAM), by default ClientId typically is a GUID. /// /// /// /// $ishSession = New-IshSession -WsBaseUrl "https://example.com/ISHWS/" -ClientId "c826e7e1-c35c-43fe-9756-e1b61f44bb40" -ClientSecret "ziKiGbx6N0G3m69/vWMZUTs2paVO1Mzqt6Y6TX7mnpPJyFVODsI1Vw==" /// /// Building a session for the chosen service based on Client Credentials authentication. - /// Protocol will be WcfSoapWithOpenIdConnect on 15/15.0.0 and later systems. Note that ClientId/ClientSecret has to be configured in Access Management (ISHAM), by default ClientId typically is a GUID. + /// Protocol will be OpenApiWithOpenIdConnect on 15/15.0.0 and later systems. Note that ClientId/ClientSecret has to be configured in Access Management (ISHAM), by default ClientId typically is a GUID. /// /// /// @@ -184,7 +184,7 @@ public SwitchParameter IgnoreSslPolicyErrors } /// - /// IshSession Protocol explicitly selects the communication protocol; either WcfSoapWithWsTrust (legacy option of Tridion Docs 14SP4/14.0.4, in turn ISHRemote 7.0 and earlier), WcfSoapWithOpenIdConnect (since Tridion Docs 15/15.0.0) and OpenApiWithOpenIdConnect (experimental since Tridion Docs 15/15.0.0). If not provided, the CMS version will pick the most optimal support protocol. See also . + /// IshSession Protocol explicitly selects the communication protocol; either WcfSoapWithWsTrust (legacy option of Tridion Docs 14SP4/14.0.4, in turn ISHRemote 7.0 and earlier), WcfSoapWithOpenIdConnect (since Tridion Docs 15/15.0.0) and OpenApiWithOpenIdConnect (since Tridion Docs 15/15.0.0). If not provided, or default value Autodetect, WcfSoapWithWsTrust is picked on Tridion Docs 14SP4/14.0.4 and earlier, and OpenApiWithOpenIdConnect (OpenAPI where available, WcfSoapWithOpenIdConnect as per-cmdlet fallback) since Tridion Docs 15/15.0.0. See also . /// [Parameter(Mandatory = false, ValueFromPipelineByPropertyName = false, ParameterSetName = "Interactive")] [Parameter(Mandatory = false, ValueFromPipelineByPropertyName = false, ParameterSetName = "UserNamePassword")] diff --git a/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/Session/TestIshSession.cs b/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/Session/TestIshSession.cs index 528474f..b406087 100644 --- a/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/Session/TestIshSession.cs +++ b/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/Session/TestIshSession.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2014 All Rights Reserved by the SDL Group. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,7 +28,7 @@ namespace Trisoft.ISHRemote.Cmdlets.Session { /// /// The Test-IshSession cmdlet creates a new IshSession object using the parameters that are provided. - /// The communication protocol will be derived from the server-side product version (AutoDetect). On 14SP4/14.0.4 plus ISHRemote 7.0 and earlier the default is WcfSoapWithWsTrust. Since 15/15.0.0 ISHRemote prefers Modern Authentication and selects WcfSoapWithOpenIdConnect. Experimental since 15/15.0.0 is OpenApiWithOpenIdConnect, where already possible cmdlets will go over OpenAPI REST calls instead of WcfSoapWithOpenIdConnect calls. + /// The communication protocol will be derived from the server-side product version (AutoDetect). On 14SP4/14.0.4 plus ISHRemote 7.0 and earlier the default is WcfSoapWithWsTrust. Since 15/15.0.0 ISHRemote prefers Modern Authentication and selects OpenApiWithOpenIdConnect, where cmdlets with an OpenAPI implementation go over OpenAPI REST calls and all other cmdlets fall back to WcfSoapWithOpenIdConnect calls. /// The Test-IshSession cmdlet internal creates a minimal IshSession object using the parameters that are provided. /// Tests the WebServices (ISHWS-activation) and validates the credentials in the 'InfoShare' database (ConnectionString-activation). /// @@ -45,7 +45,7 @@ namespace Trisoft.ISHRemote.Cmdlets.Session /// /// Building a session for the chosen service. /// Protocol will be WcfSoapWithWsTrust on 14SP4/14.0.4 and earlier systems. An implicit NetworkCredential object will be passed for authentication to the service on PowerShell 5.1 - will throw an error on PowerShell 7.2+. - /// Protocol will be WcfSoapWithOpenIdConnect on 15/15.0.0 and later systems. This will trigger the interactive system browser based flow - so your browser as trusted single sign on client. + /// Protocol will be OpenApiWithOpenIdConnect on 15/15.0.0 and later systems. This will trigger the interactive system browser based flow - so your browser as trusted single sign on client. /// /// /// @@ -60,7 +60,7 @@ namespace Trisoft.ISHRemote.Cmdlets.Session /// /// Iteratively the Test-IshSession line with PSCredential parameter holding a string representation will prompt you for a password. /// Protocol will be WcfSoapWithWsTrust on 14SP4/14.0.4 and earlier systems. - /// Protocol will be WcfSoapWithOpenIdConnect on 15/15.0.0 and later systems. Note that ClientId 'Admin' has to be configured in Access Management (ISHAM), by default ClientId typically is a GUID. + /// Protocol will be OpenApiWithOpenIdConnect on 15/15.0.0 and later systems. Note that ClientId 'Admin' has to be configured in Access Management (ISHAM), by default ClientId typically is a GUID. /// /// /// @@ -77,14 +77,14 @@ namespace Trisoft.ISHRemote.Cmdlets.Session /// /// Extensive automation example based on the PSCredential parameter. Responsibility of the plain text password or client secret is yours. /// Protocol will be WcfSoapWithWsTrust on 14SP4/14.0.4 and earlier systems. - /// Protocol will be WcfSoapWithOpenIdConnect on 15/15.0.0 and later systems. Note that 'Admin' has to be you ClientId as configured in Access Management (ISHAM), by default this typically is a GUID. + /// Protocol will be OpenApiWithOpenIdConnect on 15/15.0.0 and later systems. Note that 'Admin' has to be you ClientId as configured in Access Management (ISHAM), by default this typically is a GUID. /// /// /// /// $ishSession = New-IshSession -WsBaseUrl "https://example.com/ISHWS/" -ClientId "c826e7e1-c35c-43fe-9756-e1b61f44bb40" -ClientSecret "ziKiGbx6N0G3m69/vWMZUTs2paVO1Mzqt6Y6TX7mnpPJyFVODsI1Vw==" /// /// Building a session for the chosen service based on username/password authentication. Parameter Protocol indicates the preferred communication/authentication route. - /// Protocol will be WcfSoapWithOpenIdConnect on 15/15.0.0 and later systems. Note that ClientId/ClientSecret has to be configured in Access Management (ISHAM), by default ClientId typically is a GUID. + /// Protocol will be OpenApiWithOpenIdConnect on 15/15.0.0 and later systems. Note that ClientId/ClientSecret has to be configured in Access Management (ISHAM), by default ClientId typically is a GUID. /// [Cmdlet(VerbsDiagnostic.Test, "IshSession", SupportsShouldProcess = false)] [OutputType(typeof(bool))] @@ -177,7 +177,7 @@ public SwitchParameter IgnoreSslPolicyErrors } /// - /// IshSession Protocol tries to connect the communication protocol like WcfSoapWithWsTrust (legacy option of Tridion Docs 14SP4/14.0.4 and ISHRemote 7.0 and earlier), WcfSoapWithOpenIdConnect (since Tridion Docs 15/15.0.0) and OpenApiWithOpenIdConnect (experimental since Tridion Docs 15/15.0.0). If not provided or default value AutoDetect will pick the most optimal support protocol. See also . + /// IshSession Protocol tries to connect the communication protocol like WcfSoapWithWsTrust (legacy option of Tridion Docs 14SP4/14.0.4 and ISHRemote 7.0 and earlier), WcfSoapWithOpenIdConnect (since Tridion Docs 15/15.0.0) and OpenApiWithOpenIdConnect (since Tridion Docs 15/15.0.0). If not provided or default value Autodetect will pick WcfSoapWithWsTrust on Tridion Docs 14SP4/14.0.4 and earlier, and OpenApiWithOpenIdConnect (OpenAPI where available, WcfSoapWithOpenIdConnect as per-cmdlet fallback) since Tridion Docs 15/15.0.0. See also . /// [Parameter(Mandatory = false, ValueFromPipelineByPropertyName = false, ParameterSetName = "Interactive")] [Parameter(Mandatory = false, ValueFromPipelineByPropertyName = false, ParameterSetName = "UserNamePassword")] diff --git a/Source/ISHRemote/Trisoft.ISHRemote/Objects/Public/IshSession.cs b/Source/ISHRemote/Trisoft.ISHRemote/Objects/Public/IshSession.cs index 03b5eb0..259d714 100644 --- a/Source/ISHRemote/Trisoft.ISHRemote/Objects/Public/IshSession.cs +++ b/Source/ISHRemote/Trisoft.ISHRemote/Objects/Public/IshSession.cs @@ -186,14 +186,9 @@ public IshSession(ILogger logger, string webServicesBaseUrl, string ishUserName, _protocol = Enumerations.Protocol.WcfSoapWithWsTrust; _logger.WriteDebug($"LoadConnectionConfiguration selecting _protocol[{_protocol}] on SoftwareVersion[{ishwsConnectionConfiguration.SoftwareVersion}]"); } - else if (_protocol == Enumerations.Protocol.Autodetect && (new IshVersion(ishwsConnectionConfiguration.SoftwareVersion).MajorVersion == 15)) + else if (_protocol == Enumerations.Protocol.Autodetect && (new IshVersion(ishwsConnectionConfiguration.SoftwareVersion).MajorVersion >= 15)) { - _protocol = Enumerations.Protocol.WcfSoapWithOpenIdConnect; - _logger.WriteDebug($"LoadConnectionConfiguration selecting _protocol[{_protocol}] on SoftwareVersion[{ishwsConnectionConfiguration.SoftwareVersion}]"); - } - else if (_protocol == Enumerations.Protocol.Autodetect && (new IshVersion(ishwsConnectionConfiguration.SoftwareVersion).MajorVersion >= 16)) - { - // >= 16, so predicting public OpenApi + // >= 15, so OpenApi where available; cmdlets without OpenApi implementation fall back to WcfSoapWithOpenIdConnect, which is initialized as well _protocol = Enumerations.Protocol.OpenApiWithOpenIdConnect; _logger.WriteDebug($"LoadConnectionConfiguration selecting _protocol[{_protocol}] on SoftwareVersion[{ishwsConnectionConfiguration.SoftwareVersion}]"); } From 9c2b7ff084ec8498900e85a03d9bfe8c02791d7c Mon Sep 17 00:00:00 2001 From: ddemeyer Date: Tue, 27 Oct 2026 19:41:09 +0100 Subject: [PATCH 2/3] #282 NewIshSession.Tests.ps1 got a 30+ second speed up by removing repeated reflection from the test --- .../Cmdlets/Session/NewIshSession.Tests.ps1 | 35 ++++++++----------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/Session/NewIshSession.Tests.ps1 b/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/Session/NewIshSession.Tests.ps1 index f5f40e7..8b3010a 100644 --- a/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/Session/NewIshSession.Tests.ps1 +++ b/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/Session/NewIshSession.Tests.ps1 @@ -891,6 +891,10 @@ Describe "New-IshSession" -Tags "Read" { $openApiAM10ClientMembers20251210 = @( 'ApiResources_GetAsync','ApiResources_GetByIdAsync','Applications_CreateAsync','Applications_DeleteAsync','Applications_GetAsync','Applications_GetByIdAsync','Applications_UpdateAsync','AuditLogs_GetByFilterAsync','AuditLogs_GetByIdAsync','Equals','GetHashCode','GetType','IdentityProviders_CreateAsync','IdentityProviders_DeleteAsync','IdentityProviders_GetAsync','IdentityProviders_GetAvailableIdpTypesAsync','IdentityProviders_GetByIdAsync','IdentityProviders_GetIconAsync','IdentityProviders_GetLoginOptionsAsync','IdentityProviders_GetParametersForIdentityProviderTypeAsync','IdentityProviders_UpdateAsync','ServiceAccounts_CreateAsync','ServiceAccounts_DeleteAsync','ServiceAccounts_DeleteClientSecretAsync','ServiceAccounts_GenerateClientSecretAsync','ServiceAccounts_GetAsync','ServiceAccounts_GetByIdAsync','ServiceAccounts_UpdateAsync','ServiceAccounts_UpdateClientSecretAsync','System_GetLoginStatusAsync','System_GetSupportedCulturesAsync','System_GetUserInfoAsync','ToString','Users_ActivateUserAsync','Users_DeactivateUserAsync','Users_DeleteAsync','Users_DeleteClientSecretAsync','Users_GenerateClientSecretAsync','Users_GetAsync','Users_GetByIdAsync','Users_UpdateAsync','Users_UpdateClientSecretAsync' ) # Since v8.2 # Up to ISHRemote v8.2 $ishSession.OpenApiAM10Client was CamelCase, chose to break and align to Snake_Case as delivered by Access Management since v2.0.0 so Tridion Docs 15.0.0 $openApiAM10ClientMembers20240404 = $openApiAM10ClientMembers20251210 + # Method names are retrieved once, as repeated PSObject.Methods.Name reflection per member made the OperationIds tests very slow + $openApiISH30ClientActualMembers = @($localIShSession.OpenApiISH30Client.PSObject.Methods.Name) + $openApiAM10ClientActualMembers = @($localIShSession.OpenApiAM10Client.PSObject.Methods.Name) + $openApiClientIgnoredMembers = @('Equals','GetHashCode','GetType','ToString','get_BaseUrl','set_BaseUrl','get_ReadResponseAsString','set_ReadResponseAsString') } } It "IshSession.OpenApiISH30Client" { @@ -901,25 +905,20 @@ Describe "New-IshSession" -Tags "Read" { } It "IshSession.OpenApiISH30Client OperationIds (15.1 20240404 methods exists)" { if (([Version]$ishSession.ServerVersion).Major -ge 15) { # new service since 15/15.0.0 - foreach ($member in $openApiISH30ClientMembers20240404) { - $localIShSession.OpenApiISH30Client.PSObject.Methods.Name | Should-ContainCollection $member - } + $missingMembers = @($openApiISH30ClientMembers20240404 | Where-Object { $_ -notin $openApiISH30ClientActualMembers }) + ("missing[" + ($missingMembers -join ',') + "]") | Should-BeString "missing[]" } } It "IshSession.OpenApiISH30Client OperationIds (15.3 20251210 methods exists)" { - if ((([Version]$ishSession.ServerVersion).Major -ge 15) -and (([Version]$ishSession.ServerVersion).Minor -ge 2)) { # new service since 15.2/15.2.0 - foreach ($member in $openApiISH30ClientMembers20251210) { - $localIShSession.OpenApiISH30Client.PSObject.Methods.Name | Should-ContainCollection $member - } + if ([Version]$ishSession.ServerVersion -ge [Version]"15.2") { # new service since 15.2/15.2.0 + $missingMembers = @($openApiISH30ClientMembers20251210 | Where-Object { $_ -notin $openApiISH30ClientActualMembers }) + ("missing[" + ($missingMembers -join ',') + "]") | Should-BeString "missing[]" } } It "IshSession.OpenApiISH30Client OperationIds (new methods found, adapt this test)" { if (([Version]$ishSession.ServerVersion).Major -ge 15) { # new service since 15/15.0.0 - foreach ($member in $localIShSession.OpenApiISH30Client.PSObject.Methods.Name) { - if ($member -notin @('Equals','GetHashCode','GetType','ToString','get_BaseUrl','set_BaseUrl','get_ReadResponseAsString','set_ReadResponseAsString')) { - $openApiISH30ClientMembers20251210 | Should-ContainCollection $member - } - } + $superfluousMembers = @($openApiISH30ClientActualMembers | Where-Object { ($_ -notin $openApiClientIgnoredMembers) -and ($_ -notin $openApiISH30ClientMembers20251210) }) + ("superfluous[" + ($superfluousMembers -join ',') + "]") | Should-BeString "superfluous[]" } } It "IshSession.OpenApiAM10Client" { @@ -929,16 +928,12 @@ Describe "New-IshSession" -Tags "Read" { } } It "IshSession.OpenApiAM10Client OperationIds (20240404 methods exists)" { - foreach ($member in $openApiAM10ClientMembers20240404) { - $localIShSession.OpenApiAM10Client.PSObject.Methods.Name | Should-ContainCollection $member - } + $missingMembers = @($openApiAM10ClientMembers20240404 | Where-Object { $_ -notin $openApiAM10ClientActualMembers }) + ("missing[" + ($missingMembers -join ',') + "]") | Should-BeString "missing[]" } It "IshSession.OpenApiAM10Client OperationIds (new methods found, adapt this test)" { - foreach ($member in $localIShSession.OpenApiAM10Client.PSObject.Methods.Name) { - if ($member -notin @('Equals','GetHashCode','GetType','ToString','get_BaseUrl','set_BaseUrl','get_ReadResponseAsString','set_ReadResponseAsString')) { - $openApiAM10ClientMembers20240404 | Should-ContainCollection $member - } - } + $superfluousMembers = @($openApiAM10ClientActualMembers | Where-Object { ($_ -notin $openApiClientIgnoredMembers) -and ($_ -notin $openApiAM10ClientMembers20240404) }) + ("superfluous[" + ($superfluousMembers -join ',') + "]") | Should-BeString "superfluous[]" } It "IshSession.Annotation25" { if (([Version]$ishSession.ServerVersion).Major -ge 15) { # new service since 15/15.0.0 From 231339d22ee7ff6c7ed734793516183a60ee5b67 Mon Sep 17 00:00:00 2001 From: ddemeyer Date: Tue, 27 Oct 2026 20:01:10 +0100 Subject: [PATCH 3/3] #282 Correct Prerequisites.Test.ps1 regarding protocol autodetect --- .../Cmdlets/_TestEnvironment/TestPrerequisite.Tests.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/_TestEnvironment/TestPrerequisite.Tests.ps1 b/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/_TestEnvironment/TestPrerequisite.Tests.ps1 index 70838e9..fd0e5d7 100644 --- a/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/_TestEnvironment/TestPrerequisite.Tests.ps1 +++ b/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/_TestEnvironment/TestPrerequisite.Tests.ps1 @@ -100,9 +100,9 @@ Describe "Test-Prerequisite" -Tags "Read" { $ishSession = New-IshSession -WsBaseUrl $webServicesBaseUrl -ClientId $amClientId -ClientSecret $amClientSecret $ishUser = Get-IshUser } - It "IshSession.Protocol WcfSoapWithOpenIdConnect" { - if (([Version]$ishSession.ServerVersion).Major -eq 15) { - $IshSession.Protocol | Should-Be 'WcfSoapWithOpenIdConnect' + It "IshSession.Protocol Autodetect selects OpenApiWithOpenIdConnect" { + if (([Version]$ishSession.ServerVersion).Major -ge 15) { + $IshSession.Protocol | Should-Be 'OpenApiWithOpenIdConnect' } } It "Current IShSession user over ClientId/ClientSecret should match UserName parameter so all tests run under the same account" {