From b138e1e1a59eb4aa0deaffbe53393fe604a79d0f Mon Sep 17 00:00:00 2001 From: ddemeyer Date: Tue, 17 Mar 2026 11:06:54 +0100 Subject: [PATCH 1/3] #229 Get-IShDocumentObj augment by CoPilot --- .../DocumentObj/GetIshDocumentObj.Tests.ps1 | 34 +++++- .../Cmdlets/DocumentObj/GetIshDocumentObj.cs | 103 +++++++++++++++--- .../ExtensionMethods/IshFieldsExtensions.cs | 57 ++++++++++ .../OpenApiISH30EnumerationsExtensions.cs | 19 ++++ 4 files changed, 190 insertions(+), 23 deletions(-) diff --git a/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/DocumentObj/GetIshDocumentObj.Tests.ps1 b/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/DocumentObj/GetIshDocumentObj.Tests.ps1 index 1bb7d1b..086aafe 100644 --- a/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/DocumentObj/GetIshDocumentObj.Tests.ps1 +++ b/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/DocumentObj/GetIshDocumentObj.Tests.ps1 @@ -29,11 +29,11 @@ Describe "Get-IshDocumentObj" { $tempFilePath = (New-TemporaryFile).FullName # amount of test data to generate - $ishDocumentObjTopicsCount = 1000 - $ishDocumentObjMapsCount = 1000 - $ishDocumentObjLibsCount = 1000 - $ishDocumentObjImagesCount = 1000 - $ishDocumentObjOthersCount = 1000 + $ishDocumentObjTopicsCount = 10 + $ishDocumentObjMapsCount = 10 + $ishDocumentObjLibsCount = 10 + $ishDocumentObjImagesCount = 10 + $ishDocumentObjOthersCount = 10 } Context "Get-IshDocumentObj Generate Performance Test Data within the test" { BeforeAll { @@ -102,6 +102,7 @@ Describe "Get-IshDocumentObj" { } } } + <# Context "Get-IshDocumentObj Query 5 times per test" { BeforeAll { $ishDocumentObjTopics = Get-IshFolder -IshFolder $global:ishFolderCmdlet -Recurse -FolderTypeFilter ISHModule | Get-IshFolderContent @@ -287,14 +288,35 @@ Describe "Get-IshDocumentObj" { Get-IshDocumentObj -IshObject ($allIShDocumentObjs | Get-Random -Count 5000) Get-IshDocumentObj -IshObject ($allIShDocumentObjs | Get-Random -Count 5000) } - } + } + #> + Context "Direct OpenAPI calls 5 times per test" { + BeforeAll { + $ishDocumentObjTopics = Get-IshFolder -IshFolder $global:ishFolderCmdlet -Recurse -FolderTypeFilter ISHModule | Get-IshFolderContent + $ishDocumentObjMaps = Get-IshFolder -IshFolder $global:ishFolderCmdlet -Recurse -FolderTypeFilter ISHMasterDoc | Get-IshFolderContent + $ishDocumentObjLibs = Get-IshFolder -IshFolder $global:ishFolderCmdlet -Recurse -FolderTypeFilter ISHLibrary | Get-IshFolderContent + $ishDocumentObjImages = Get-IshFolder -IshFolder $global:ishFolderCmdlet -Recurse -FolderTypeFilter ISHIllustration | Get-IshFolderContent + $ishDocumentObjOthers = Get-IshFolder -IshFolder $global:ishFolderCmdlet -Recurse -FolderTypeFilter ISHTemplate | Get-IshFolderContent + $allIShDocumentObjs = $ishDocumentObjTopics + $ishDocumentObjMaps + $ishDocumentObjLibs + $ishDocumentObjImages + $ishDocumentObjOthers + } + It "Get-IShDocumentObj by LogicalId for 1 (RetrieveMetadata equals API30.GetDocumentObjectListByLogicalId)" { + $ishSession.DefaultRequestedMetadata="All" + Get-IshDocumentObj -LogicalId $ishDocumentObjTopics[0].IshRef + } + It "Get-IShDocumentObj by IshLngref for 1 (RetrieveMetadataByIshLngRefs equals API30.GetDocumentObjectListByLanguageCardId)" { + $ishSession.DefaultRequestedMetadata="All" + Get-IshDocumentObj -IshObject $ishDocumentObjTopics[1] + } + } } AfterAll { + # Write-Host ("Running "+$cmdletName+" Test Data and Variables cleanup") $folderCmdletRootPath = (Join-Path $folderTestRootPath $cmdletName) try { Get-IshFolder -IshSession $ishSession -FolderPath $folderCmdletRootPath -Recurse | Get-IshFolderContent -IshSession $ishSession | Remove-IshDocumentObj -IshSession $ishSession -Force } catch { } try { Remove-IshFolder -IshSession $ishSession -FolderPath $folderCmdletRootPath -Recurse } catch { } try { Remove-Item $tempFilePath -Force } catch { } + #> } diff --git a/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/DocumentObj/GetIshDocumentObj.cs b/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/DocumentObj/GetIshDocumentObj.cs index 4d3766a..dd0a217 100644 --- a/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/DocumentObj/GetIshDocumentObj.cs +++ b/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/DocumentObj/GetIshDocumentObj.cs @@ -19,7 +19,9 @@ using System.Linq; using System.Management.Automation; using System.ServiceModel; +using System.Threading; using Trisoft.ISHRemote.Exceptions; +using Trisoft.ISHRemote.ExtensionMethods; using Trisoft.ISHRemote.HelperClasses; using Trisoft.ISHRemote.Objects; using Trisoft.ISHRemote.Objects.Public; @@ -110,9 +112,15 @@ public SwitchParameter IncludeData [AllowEmptyCollection] public IshObject[] IshObject { get; set; } + /// + /// Switch parameter to use REST API (OpenAPI) instead of SOAP API for retrieval. This is experimental in Phase 1. + /// + [Parameter(Mandatory = false, ParameterSetName = "ParameterGroup")] + public SwitchParameter UseREST { get; set; } + + - #region Private fields @@ -216,24 +224,85 @@ protected override void ProcessRecord() var statusFilter = EnumConverter.ToStatusFilter(StatusFilter); if (!_includeData) { - //RetrieveMetadata - WriteDebug($"Retrieving LogicalId.length[{LogicalId.Length}] StatusFilter[{statusFilter}] MetadataFilter.length[{metadataFilter.ToXml().Length}] RequestedMetadata.length[{requestedMetadata.ToXml().Length}] 0/{LogicalId.Length}"); - // Divides the list of language card ids in different lists that all have maximally MetadataBatchSize elements - List> dividedLogicalIdsList = DivideListInBatches(LogicalId.ToList(), IshSession.MetadataBatchSize); - int currentLogicalIdCount = 0; - foreach (List logicalIdBatch in dividedLogicalIdsList) + if (!UseREST) { - // Process language card ids in batches - string xmlIshObjects = IshSession.DocumentObj25.RetrieveMetadata( - logicalIdBatch.ToArray(), - statusFilter, - metadataFilter.ToXml(), - requestedMetadata.ToXml()); - IshObjects retrievedObjects = new IshObjects(ISHType, xmlIshObjects); - returnIshObjects.AddRange(retrievedObjects.Objects); - currentLogicalIdCount += logicalIdBatch.Count; - WriteDebug($"Retrieving LogicalId.length[{logicalIdBatch.Count}] StatusFilter[{statusFilter}] MetadataFilter.length[{metadataFilter.ToXml().Length}] RequestedMetadata.length[{requestedMetadata.ToXml().Length}] {currentLogicalIdCount}/{LogicalId.Length}"); + //RetrieveMetadata via SOAP (default implementation) + WriteDebug($"[SOAP] Retrieving LogicalId.length[{LogicalId.Length}] StatusFilter[{statusFilter}] MetadataFilter.length[{metadataFilter.ToXml().Length}] RequestedMetadata.length[{requestedMetadata.ToXml().Length}] 0/{LogicalId.Length}"); + // Divides the list of language card ids in different lists that all have maximally MetadataBatchSize elements + List> dividedLogicalIdsList = DivideListInBatches(LogicalId.ToList(), IshSession.MetadataBatchSize); + int currentLogicalIdCount = 0; + foreach (List logicalIdBatch in dividedLogicalIdsList) + { + // Process language card ids in batches + string xmlIshObjects = IshSession.DocumentObj25.RetrieveMetadata( + logicalIdBatch.ToArray(), + statusFilter, + metadataFilter.ToXml(), + requestedMetadata.ToXml()); + IshObjects retrievedObjects = new IshObjects(ISHType, xmlIshObjects); + returnIshObjects.AddRange(retrievedObjects.Objects); + currentLogicalIdCount += logicalIdBatch.Count; + WriteDebug($"[SOAP] Retrieving LogicalId.length[{logicalIdBatch.Count}] StatusFilter[{statusFilter}] MetadataFilter.length[{metadataFilter.ToXml().Length}] RequestedMetadata.length[{requestedMetadata.ToXml().Length}] {currentLogicalIdCount}/{LogicalId.Length}"); + } } + else + { + //RetrieveMetadata via REST/OpenAPI (experimental Phase 1 implementation) + WriteDebug($"[REST] Retrieving LogicalId.length[{LogicalId.Length}] StatusFilter[{StatusFilter}] MetadataFilter fields[{metadataFilter.Fields().Length}] RequestedMetadata fields[{requestedMetadata.Fields().Length}]"); + + // Convert ISHRemote types to OpenAPI types + var openApiStatusFilter = StatusFilter.ToOpenApiISH30StatusFilter(); + var filterFields = metadataFilter.ToOpenApiISH30FilterFieldValues(); + var requestedFields = requestedMetadata.ToOpenApiISH30RequestedFields(); + + // Divide logical IDs into batches (same batch size as SOAP for consistency) + List> dividedLogicalIdsList = DivideListInBatches(LogicalId.ToList(), IshSession.MetadataBatchSize); + int currentLogicalIdCount = 0; + + foreach (List logicalIdBatch in dividedLogicalIdsList) + { + // Build the request object for this batch + var getDocumentObjectRequest = new OpenApiISH30.GetDocumentObjectListByLogicalId + { + LogicalIds = logicalIdBatch, + StatusFilter = openApiStatusFilter, + FilterFields = filterFields, + Fields = requestedFields, + SelectedProperties = OpenApiISH30.SelectedProperties.Id, + FieldGroup = requestedMetadata.Fields().Length > 0 ? OpenApiISH30.FieldGroup.None : OpenApiISH30.FieldGroup.Basic, + IncludeLinks = false, + IncludePartialItems = false + }; + + WriteDebug($"[REST] Calling GetDocumentObjectListByLogicalIdAsync for batch {currentLogicalIdCount}/{LogicalId.Length}"); + + // Make the async call synchronously (using GetAwaiter().GetResult() for PowerShell compatibility) + var documentObjects = IshSession.OpenApiISH30Client.GetDocumentObjectListByLogicalIdAsync( + getDocumentObjectRequest, + CancellationToken.None) + .GetAwaiter() + .GetResult(); + + WriteDebug($"[REST] Retrieved {documentObjects.Count} document objects from OpenAPI"); + + // TODO [Phase 2]: Convert OpenApiISH30.DocumentObject collection to IshObjects + // For Phase 1, we log that REST API was called successfully but cannot yet process results + WriteWarning($"[REST Phase 1] Successfully retrieved {documentObjects.Count} objects via REST API, but conversion to IshObjects not yet implemented. Falling back to SOAP for this batch."); + + // Fallback to SOAP for actual data retrieval in Phase 1 + string xmlIshObjects = IshSession.DocumentObj25.RetrieveMetadata( + logicalIdBatch.ToArray(), + statusFilter, + metadataFilter.ToXml(), + requestedMetadata.ToXml()); + IshObjects retrievedObjects = new IshObjects(ISHType, xmlIshObjects); + returnIshObjects.AddRange(retrievedObjects.Objects); + + currentLogicalIdCount += logicalIdBatch.Count; + WriteDebug($"[REST] Processed batch {currentLogicalIdCount}/{LogicalId.Length}"); + } + } + } else { diff --git a/Source/ISHRemote/Trisoft.ISHRemote/ExtensionMethods/IshFieldsExtensions.cs b/Source/ISHRemote/Trisoft.ISHRemote/ExtensionMethods/IshFieldsExtensions.cs index 81c8ed5..2879e65 100644 --- a/Source/ISHRemote/Trisoft.ISHRemote/ExtensionMethods/IshFieldsExtensions.cs +++ b/Source/ISHRemote/Trisoft.ISHRemote/ExtensionMethods/IshFieldsExtensions.cs @@ -219,5 +219,62 @@ private static ICollection GetSetBaseObjectFromReferenceType(stri return setBaseObjects; } + + /// + /// Converts IshFields to OpenAPI FilterFieldValue collection for metadata filtering + /// + internal static ICollection ToOpenApiISH30FilterFieldValues(this IshFields ishFields) + { + ICollection filterFields = new List(); + + foreach (Objects.Public.IshField ishField in ishFields.Fields()) + { + var ishMetadataFilterField = ishField.ToMetadataFilterField() as IshMetadataFilterField; + if (ishMetadataFilterField != null) + { + // Create a StringFilterFieldValue for string-based filters + StringFilterFieldValue filterField = new StringFilterFieldValue + { + IshField = new OpenApiISH30.IshField + { + Level = ishField.Level.ToOpenApiISH30Level(), + Name = ishField.Name + }, + Value = new List { ishMetadataFilterField.Value }, + Operator = OpenApiISH30.MetadataFilterOperator.Like + }; + filterFields.Add(filterField); + } + } + + return filterFields; + } + + /// + /// Converts IshFields to OpenAPI RequestedField collection for requested metadata + /// + internal static ICollection ToOpenApiISH30RequestedFields(this IshFields ishFields) + { + ICollection requestedFields = new List(); + + foreach (Objects.Public.IshField ishField in ishFields.Fields()) + { + var ishRequestedMetadataField = ishField.ToRequestedMetadataField() as IshRequestedMetadataField; + if (ishRequestedMetadataField != null) + { + RequestedField requestedField = new RequestedField + { + IshField = new OpenApiISH30.IshField + { + Level = ishField.Level.ToOpenApiISH30Level(), + Name = ishField.Name + } + }; + requestedFields.Add(requestedField); + } + } + + return requestedFields; + } } } diff --git a/Source/ISHRemote/Trisoft.ISHRemote/ExtensionMethods/OpenApiISH30EnumerationsExtensions.cs b/Source/ISHRemote/Trisoft.ISHRemote/ExtensionMethods/OpenApiISH30EnumerationsExtensions.cs index 4d5ba76..4e843f6 100644 --- a/Source/ISHRemote/Trisoft.ISHRemote/ExtensionMethods/OpenApiISH30EnumerationsExtensions.cs +++ b/Source/ISHRemote/Trisoft.ISHRemote/ExtensionMethods/OpenApiISH30EnumerationsExtensions.cs @@ -43,6 +43,25 @@ internal static OpenApiISH30.FieldGroup ToOpenApiISH30FieldGroup(this RequestedM } + /// + /// Converts ISHRemote StatusFilter to OpenAPI StatusFilter + /// + internal static OpenApiISH30.StatusFilter ToOpenApiISH30StatusFilter(this StatusFilter statusFilter) + { + switch (statusFilter) + { + case StatusFilter.ISHReleasedStates: + return OpenApiISH30.StatusFilter.LatestReleased; + case StatusFilter.ISHReleasedOrDraftStates: + return OpenApiISH30.StatusFilter.DraftOrLatestReleased; + case StatusFilter.ISHOutOfDateOrReleasedStates: + return OpenApiISH30.StatusFilter.AllReleased; + case StatusFilter.ISHNoStatusFilter: + default: + return OpenApiISH30.StatusFilter.All; + } + } + /// /// OpenApi (dd 20211228) implements Field Level, needs mapping to ISHRemote levels /// From 301c395a28b3007935851e43ab56e0a93871f5e6 Mon Sep 17 00:00:00 2001 From: ddemeyer Date: Tue, 17 Mar 2026 12:35:23 +0100 Subject: [PATCH 2/3] #230 Introduced isLinuxContainerized flag to bypass Windows-only tests. Adapted TestPrerequisite, NewIshSession and TestIshSession --- Doc/ReleaseNotes-ISHRemote-8.2.md | 8 +- .../Cmdlets/Session/NewIshSession.Tests.ps1 | 279 ++++++++++++------ .../Cmdlets/Session/TestIshSession.Tests.ps1 | 10 +- .../TestPrerequisite.Tests.ps1 | 54 ++-- .../ISHRemote.PesterSetup.ps1 | 9 +- 5 files changed, 231 insertions(+), 129 deletions(-) diff --git a/Doc/ReleaseNotes-ISHRemote-8.2.md b/Doc/ReleaseNotes-ISHRemote-8.2.md index 3cfddaf..6627dad 100644 --- a/Doc/ReleaseNotes-ISHRemote-8.2.md +++ b/Doc/ReleaseNotes-ISHRemote-8.2.md @@ -23,7 +23,7 @@ The below text describes the delta compared to fielded release ISHRemote v8.1. Every usage of a cmdlet will refresh the security tokens. However, when not using ISHRemote cmdlets or the implicit local or global `$ISHRemoteSessionStateIshSession` or explicit `$ishSession` object, the session expires by default after around 57 minutes when using ISHID or similar on other identity providers. In turn resulting in error `An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail.`. -In this ISHRemote version, the session will attempt to get a new token automatically on every triggererd ISHRemote cmdlet. If you created the IShSession object over an interactive browser, you will see the browser again perhaps with or without a credential challenge in the browser. Change is only for protocols `WcfSoapWithOpenIdConnect` and `OpenApiWithOpenIdConnect`; no change for `WcfSoapWithWsTrust`. +In this ISHRemote version, the session will attempt to get a new token automatically on every triggered ISHRemote cmdlet. If you created the IShSession object over an interactive browser, you will see the browser again perhaps with or without a credential challenge in the browser. Change is only for protocols `WcfSoapWithOpenIdConnect` and `OpenApiWithOpenIdConnect`; no change for `WcfSoapWithWsTrust`. Infamous random annoying error `The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.` should now recover within the cmdlet or worst-case when rerunning the same cmdlet. This without applying the earlier workaround of building a `New-IshSession`. @@ -38,13 +38,13 @@ Model Concept Protocol ([MCP](https://modelcontextprotocol.io/docs/getting-start Combining documented ISHRemote cmdlets with the interaction pattern of MCP Tools to LLMs, we see at least the below purposes... 1. By offering every ISHRemote cmdlet as an MCP Tool to your LLM, it means you can **ask your system questions** like `Create a new ishsession to https://ish.example.com/ISHWS/`. And yes it will create you that `$ishSession` variable in the background that you can use over the other MCP Tools - or I could say cmdlets. This allows you to use natural language to query your specific instance on `How many user roles are there?` or `which status transitions do you have for a module?`. These requests will be executed using your authenticated `$ishSession`. -2. As ISHRemote cmdlets understand the API and many of its concepts, it can **explain system concepts** usage questions. This allows you to query `How many statusses are there?`, `Does the system have any privileges?` which could be followed by `These are labels, any way to use these values in an API?`. +2. As ISHRemote cmdlets understand the API and many of its concepts, it can **explain system concepts** usage questions. This allows you to query `How many statusses are there?`, `Does the system have any privileges?` which could be followed by `These are labels, any way to use these values in an API?`. It can explain existing ISHRemote PowerShell scripts. 3. And because the MCP Tools look a lot like ISHRemote cmdlets, you can reuse your LLM's PowerShell knowledge to **draft PowerShell scripts**. You could query for `can you write me a powershell script to create a user?` or `Can you suggest a rewrite using the faster search cmdlet?`. Although the LLM will not always offer working code, but it does seem to make sure you don't have a blank sheet in front of you. You now have something that you can debug and get to a working state as you can feed it your runtime errors and it will improve the generated code iteratively. ### ISHRemoteMcpServer Setup using Visual Studio Code -Below animation give you an overview on what you need to do to set it up. +Below animation give you an overview on what you need to do to set it up. Important is that your Visual Studio Code Terminal runs a different PowerShell process then the one behind the `ISHRemoteMcpServer` which means that any `$ishSession` is not reused which could lead to initial confusion. ![ISHRemote-8.2--ISHRemoteMcpServerSetupDemo 1024x512](./Images/ISHRemote-8.2--ISHRemoteMcpServerSetupDemo.gif) @@ -104,6 +104,8 @@ A list of reminders and known issues which we noticed while experimenting... * OpenAPI proxies of Access Management and Tridion Docs CMS were refreshed. The Access Management API proxies, accessible over `$ishSession.OpenApiAM10Client`, changed and standardized as all API OperationIds are no longer written in CamelCase but Snake_Case. So for example `$ishhSession.OpenApiAM10Client.IdentityProvidersGetAsync()` becomes `$ishhSession.OpenApiAM10Client.IdentityProviders_GetAsync()` with one extra underscore. #223 * `Remove-IshBaselineItem` used version `999999` when removing an entry from the baseline. Since 15.2.0 this has to be the correct version or an empty version, but not the wrong `999999` version. #205 Thanks @OlegTokar * Rewrite cmdlet `Add-IshBackgroundTask` to not use Microsoft.IdentityModel.Tokens.CollectionUtilities.IsNullOrEmpty extension method which was made `private` (and no longer `public`) in version 8.0.0 of `Microsoft.IdentityModel.Tokens.dll` #216 Thanks @ddemeyer +* Tridion Docs 15.3.0 will be shipped to be running on Windows Server. There is however a parallel track where non-deprecated functionality of 15.3.0 runs in Linux-based containers. Non-deprecated means that the already deprecated features like `AsmxSoapWithAuthenticationContext` and `WcfSoapWithWsTrust` will be removed in next major version 16.0.0. Do note that `WcfSoapWithOpenIdConnect` and `OpenApiWithOpenIdConnect` are predicted to remain working. Refactored the Pester tests to detect this situtation. #230 Thanks @ddemeyer + ## Breaking Changes - Cmdlets diff --git a/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/Session/NewIshSession.Tests.ps1 b/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/Session/NewIshSession.Tests.ps1 index 5acf966..672fc9b 100644 --- a/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/Session/NewIshSession.Tests.ps1 +++ b/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/Session/NewIshSession.Tests.ps1 @@ -73,9 +73,11 @@ Describe "New-IshSession" -Tags "Read" { { New-IshSession -WsBaseUrl $webServicesBaseUrl -PSCredential $mycredentials } | Should -Throw } It "Parameter PSCredential over WcfSoapWithWsTrust" { - $securePassword = ConvertTo-SecureString $ishPassword -AsPlainText -Force - $mycredentials = New-Object System.Management.Automation.PSCredential ($ishUserName, $securePassword) - { New-IshSession -Protocol WcfSoapWithWsTrust -WsBaseUrl $webServicesBaseUrl -PSCredential $mycredentials } | Should -Not -Throw + if (-not $isLinuxContainerized) { + $securePassword = ConvertTo-SecureString $ishPassword -AsPlainText -Force + $mycredentials = New-Object System.Management.Automation.PSCredential ($ishUserName, $securePassword) + { New-IshSession -Protocol WcfSoapWithWsTrust -WsBaseUrl $webServicesBaseUrl -PSCredential $mycredentials } | Should -Not -Throw + } } It "Parameter PSCredential over WcfSoapWithOpenIdConnect" { if (([Version]$ishSession.ServerVersion).Major -ge 15) { # new service since 15/15.0.0 @@ -88,105 +90,163 @@ Describe "New-IshSession" -Tags "Read" { Context "New-IshSession over WcfSoapWithWsTrust returns IshSession object" { BeforeAll { - $localIShSession = New-IshSession -Protocol WcfSoapWithWsTrust -WsBaseUrl $webServicesBaseUrl -IshUserName $ishUserName -IshPassword $ishPassword + if (-not $isLinuxContainerized) { + $localIShSession = New-IshSession -Protocol WcfSoapWithWsTrust -WsBaseUrl $webServicesBaseUrl -IshUserName $ishUserName -IshPassword $ishPassword + } } It "Local ISHRemoteSessionStateIshSession" { - $ishSession=$executioncontext.SessionState.PSVariable.GetValue("ISHRemoteSessionStateIshSession") - $ishSession | Should -Not -BeNullOrEmpty - $ishSession.WebServicesBaseUrl | Should -Be $localIShSession.WebServicesBaseUrl - $ishSession.Protocol | Should -Be $localIShSession.Protocol - $ishSession.ServerVersion | Should -Be $localIShSession.ServerVersion - $ishSession.ClientVersion | Should -Be $localIShSession.ClientVersion + if (-not $isLinuxContainerized) { + $ishSession=$executioncontext.SessionState.PSVariable.GetValue("ISHRemoteSessionStateIshSession") + $ishSession | Should -Not -BeNullOrEmpty + $ishSession.WebServicesBaseUrl | Should -Be $localIShSession.WebServicesBaseUrl + $ishSession.Protocol | Should -Be $localIShSession.Protocol + $ishSession.ServerVersion | Should -Be $localIShSession.ServerVersion + $ishSession.ClientVersion | Should -Be $localIShSession.ClientVersion + } } It "Global ISHRemoteSessionStateIshSession" { - $ishSession=$executioncontext.SessionState.PSVariable.GetValue("global:ISHRemoteSessionStateIshSession") - $ishSession | Should -Not -BeNullOrEmpty - $ishSession.WebServicesBaseUrl | Should -Be $localIShSession.WebServicesBaseUrl - $ishSession.Protocol | Should -Be $localIShSession.Protocol - $ishSession.ServerVersion | Should -Be $localIShSession.ServerVersion - $ishSession.ClientVersion | Should -Be $localIShSession.ClientVersion + if (-not $isLinuxContainerized) { + $ishSession=$executioncontext.SessionState.PSVariable.GetValue("global:ISHRemoteSessionStateIshSession") + $ishSession | Should -Not -BeNullOrEmpty + $ishSession.WebServicesBaseUrl | Should -Be $localIShSession.WebServicesBaseUrl + $ishSession.Protocol | Should -Be $localIShSession.Protocol + $ishSession.ServerVersion | Should -Be $localIShSession.ServerVersion + $ishSession.ClientVersion | Should -Be $localIShSession.ClientVersion + } } It "Protocol" { - $localIShSession.Protocol | Should -BeExactly "WcfSoapWithWsTrust" + if (-not $isLinuxContainerized) { + $localIShSession.Protocol | Should -BeExactly "WcfSoapWithWsTrust" + } } It "GetType()" { - $localIShSession.GetType().Name | Should -BeExactly "IshSession" + if (-not $isLinuxContainerized) { + $localIShSession.GetType().Name | Should -BeExactly "IshSession" + } } It "IshSession.AuthenticationContext" { - $localIShSession.AuthenticationContext | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.AuthenticationContext | Should -Not -BeNullOrEmpty + } } It "IshSession.BlobBatchSize" { - $localIShSession.BlobBatchSize -gt 0 | Should -Be $true + if (-not $isLinuxContainerized) { + $localIShSession.BlobBatchSize -gt 0 | Should -Be $true + } } It "IshSession.ChunkSize" { - $localIShSession.ChunkSize -gt 0 | Should -Be $true + if (-not $isLinuxContainerized) { + $localIShSession.ChunkSize -gt 0 | Should -Be $true + } } It "IshSession.ClientVersion" { - $localIShSession.ClientVersion | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.ClientVersion | Should -Not -BeNullOrEmpty + } } It "IshSession.ClientVersion not 0.0.0.0" { - $localIShSession.ClientVersion | Should -Not -Be "0.0.0.0" + if (-not $isLinuxContainerized) { + $localIShSession.ClientVersion | Should -Not -Be "0.0.0.0" + } } It "IshSession.FolderPathSeparator" { - $localIShSession.FolderPathSeparator | Should -Be "\" + if (-not $isLinuxContainerized) { + $localIShSession.FolderPathSeparator | Should -Be "\" + } } It "IshSession.IshUserName" { - $localIShSession.IshUserName | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.IshUserName | Should -Not -BeNullOrEmpty + } } It "IshSession.UserName" { - $localIShSession.UserName | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.UserName | Should -Not -BeNullOrEmpty + } } It "IshSession.ClientAppId" { - $localIShSession.ClientAppId | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.ClientAppId | Should -Not -BeNullOrEmpty + } } It "IshSession.ClientId" { - $localIShSession.ClientId | Should -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.ClientId | Should -BeNullOrEmpty + } } It "IshSession.AccessToken" { - $localIShSession.AccessToken | Should -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.AccessToken | Should -BeNullOrEmpty + } } It "IshSession.IshTypeFieldDefinition" { - $localIShSession.IshTypeFieldDefinition | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.IshTypeFieldDefinition | Should -Not -BeNullOrEmpty + } } It "IshSession.IshTypeFieldDefinition.Count" { - $localIShSession.IshTypeFieldDefinition.Count -gt 460 | Should -Be $true + if (-not $isLinuxContainerized) { + $localIShSession.IshTypeFieldDefinition.Count -gt 460 | Should -Be $true + } } It "IshSession.IshTypeFieldDefinition.GetType().Name" { - $localIShSession.IshTypeFieldDefinition[0].GetType().Name | Should -BeExactly "IshTypeFieldDefinition" - $localIShSession.IshTypeFieldDefinition[0].ISHType | Should -Not -BeNullOrEmpty - $localIShSession.IshTypeFieldDefinition[0].Level | Should -Not -BeNullOrEmpty - $localIShSession.IshTypeFieldDefinition[0].Name | Should -Not -BeNullOrEmpty - $localIShSession.IshTypeFieldDefinition[0].DataType | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.IshTypeFieldDefinition[0].GetType().Name | Should -BeExactly "IshTypeFieldDefinition" + $localIShSession.IshTypeFieldDefinition[0].ISHType | Should -Not -BeNullOrEmpty + $localIShSession.IshTypeFieldDefinition[0].Level | Should -Not -BeNullOrEmpty + $localIShSession.IshTypeFieldDefinition[0].Name | Should -Not -BeNullOrEmpty + $localIShSession.IshTypeFieldDefinition[0].DataType | Should -Not -BeNullOrEmpty + } } It "IshSession.MetadataBatchSize" { - $localIShSession.MetadataBatchSize -gt 0 | Should -Be $true + if (-not $isLinuxContainerized) { + $localIShSession.MetadataBatchSize -gt 0 | Should -Be $true + } } It "IshSession.Separator" { - $localIShSession.Separator | Should -Be ", " + if (-not $isLinuxContainerized) { + $localIShSession.Separator | Should -Be ", " + } } It "IshSession.ServerVersion empty (ISHWS down?)" { - $localIShSession.ServerVersion | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.ServerVersion | Should -Not -BeNullOrEmpty + } } It "IshSession.ServerVersion not 0.0.0.0" { - $localIShSession.ServerVersion | Should -Not -Be "0.0.0.0" + if (-not $isLinuxContainerized) { + $localIShSession.ServerVersion | Should -Not -Be "0.0.0.0" + } } It "IshSession.ServerVersion contains 4 dot-seperated parts" { - $localIShSession.ServerVersion.Split(".").Length | Should -Be 4 + if (-not $isLinuxContainerized) { + $localIShSession.ServerVersion.Split(".").Length | Should -Be 4 + } } It "IshSession.Timeout defaults to 30m" { - $localIShSession.Timeout.TotalMinutes | Should -Be 30 + if (-not $isLinuxContainerized) { + $localIShSession.Timeout.TotalMinutes | Should -Be 30 + } } It "IshSession.StrictMetadataPreference" { - $localIShSession.StrictMetadataPreference | Should -Be "Continue" + if (-not $isLinuxContainerized) { + $localIShSession.StrictMetadataPreference | Should -Be "Continue" + } } It "IshSession.PipelineObjectPreference" { - $localIShSession.PipelineObjectPreference | Should -Be "PSObjectNoteProperty" + if (-not $isLinuxContainerized) { + $localIShSession.PipelineObjectPreference | Should -Be "PSObjectNoteProperty" + } } It "IshSession.DefaultRequestedMetadata" { - $localIShSession.DefaultRequestedMetadata | Should -Be "Basic" + if (-not $isLinuxContainerized) { + $localIShSession.DefaultRequestedMetadata | Should -Be "Basic" + } } It "IshSession.WebServicesBaseUrl" { - $localIShSession.WebServicesBaseUrl | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.WebServicesBaseUrl | Should -Not -BeNullOrEmpty + } } } @@ -510,7 +570,7 @@ Describe "New-IshSession" -Tags "Read" { It "WsBaseUrl without ending slash" { # .NET throws unhandy "Reference to undeclared entity 'raquo'." error $webServicesBaseUrlWithoutEndingSlash = $webServicesBaseUrl.Substring(0,$webServicesBaseUrl.Length-1) - { New-IshSession -WsBaseUrl $webServicesBaseUrlWithoutEndingSlash -IshUserName $ishUserName -IshPassword $ishPassword } | Should -Not -Throw + { New-IshSession -WsBaseUrl $webServicesBaseUrlWithoutEndingSlash -ClientId $amClientId -ClientSecret $amClientSecret } | Should -Not -Throw } } @@ -519,42 +579,45 @@ Describe "New-IshSession" -Tags "Read" { { New-IshSession -WsBaseUrl $webServicesBaseUrl -IshUserName $ishUserName -IshPassword $ishPassword -Timeout "INVALIDTIMEOUT" } | Should -Throw } It "IshSession.Timeout set to 30s" { - $localIShSession = New-IshSession -WsBaseUrl $webServicesBaseUrl -IshUserName $ishUserName -IshPassword $ishPassword -Timeout (New-TimeSpan -Seconds 60) -WarningAction Ignore -ErrorAction Ignore + $localIShSession = New-IshSession -WsBaseUrl $webServicesBaseUrl -ClientId $amClientId -ClientSecret $amClientSecret -Timeout (New-TimeSpan -Seconds 60) -WarningAction Ignore -ErrorAction Ignore $localIShSession.Timeout.TotalMilliseconds | Should -Be "60000" } It "IshSession.Timeout on INVALID url set to 1ms execution" { # TaskCanceledException: A task was canceled. { $invalidWebServicesBaseUrl = $webServicesBaseUrl -replace "://", "://INVALID" - New-IshSession -WsBaseUrl $invalidWebServicesBaseUrl -IshUserName $ishUserName -IshPassword $ishPassword -Timeout (New-Object TimeSpan(0,0,0,0,1)) + New-IshSession -WsBaseUrl $invalidWebServicesBaseUrl -ClientId $amClientId -ClientSecret $amClientSecret -Timeout (New-Object TimeSpan(0,0,0,0,1)) } | Should -Throw } } Context "New-IshSession IgnoreSslPolicyErrors" { It "Parameter IgnoreSslPolicyErrors specified positive flow" { - $localIShSession = New-IshSession -WsBaseUrl $webServicesBaseUrl -IshUserName $ishUserName -IshPassword $ishPassword -IgnoreSslPolicyErrors -WarningAction Ignore + $localIShSession = New-IshSession -WsBaseUrl $webServicesBaseUrl -ClientId $amClientId -ClientSecret $amClientSecret -IgnoreSslPolicyErrors -WarningAction Ignore $localIShSession.ServerVersion | Should -Not -BeNullOrEmpty $localIShSession.ServerVersion.Split(".").Length | Should -Be 4 } It "Parameter IgnoreSslPolicyErrors specified negative flow like host IPv4 address" { - # replace hostname like machinename.somedomain.com to ipaddress only as often certificates are valid for machinename/localhost as well - $slash1Position = $webServicesBaseUrl.IndexOf("/") - $slash2Position = $webServicesBaseUrl.IndexOf("/",$slash1Position+1) - $slash3Position = $webServicesBaseUrl.IndexOf("/",$slash2Position+1) - $hostname = $webServicesBaseUrl.Substring($slash2Position+1,$slash3Position-$slash2Position-1) - $ipv4Addresses = [System.Net.Dns]::GetHostAddresses($hostname) | - Where-Object -Property AddressFamily -eq 'InterNetwork' | - Where-Object -Property IsIPv6LinkLocal -ne $true | - Select-Object -Property IPAddressToString # returning @(192.168.1.160,10.100.139.126) - foreach ($ipv4Address in $ipv4Addresses) - { - $webServicesBaseUrlWithIpAddress = $webServicesBaseUrl.Replace($hostname,$ipv4Address.IPAddressToString) - $localIShSession = New-IshSession -WsBaseUrl $webServicesBaseUrlWithIpAddress -IshUserName $ishUserName -IshPassword $ishPassword -IgnoreSslPolicyErrors - $localIShSession.ServerVersion | Should -Not -BeNullOrEmpty - $localIShSession.ServerVersion.Split(".").Length | Should -Be 4 + if (-not $isLinuxContainerized) { + # test only works on Protocol WcfSoapWithWsTrust as WcfSoapWithOpenIdConnect errors out with 'An error occurred when verifying security for the message.' + # replace hostname like machinename.somedomain.com to ipaddress only as often certificates are valid for machinename/localhost as well + $slash1Position = $webServicesBaseUrl.IndexOf("/") + $slash2Position = $webServicesBaseUrl.IndexOf("/",$slash1Position+1) + $slash3Position = $webServicesBaseUrl.IndexOf("/",$slash2Position+1) + $hostname = $webServicesBaseUrl.Substring($slash2Position+1,$slash3Position-$slash2Position-1) + $ipv4Addresses = [System.Net.Dns]::GetHostAddresses($hostname) | + Where-Object -Property AddressFamily -eq 'InterNetwork' | + Where-Object -Property IsIPv6LinkLocal -ne $true | + Select-Object -Property IPAddressToString # returning @(192.168.1.160,10.100.139.126) + foreach ($ipv4Address in $ipv4Addresses) + { + $webServicesBaseUrlWithIpAddress = $webServicesBaseUrl.Replace($hostname,$ipv4Address.IPAddressToString) + $localIShSession = New-IshSession -WsBaseUrl $webServicesBaseUrlWithIpAddress -IshUserName $ishUserName -IshPassword $ishPassword -IgnoreSslPolicyErrors + $localIShSession.ServerVersion | Should -Not -BeNullOrEmpty + $localIShSession.ServerVersion.Split(".").Length | Should -Be 4 + } + # Remember that ipv6 addresses need to go in between square brackets to avoid port confusion } - # Remember that ipv6 addresses need to go in between square brackets to avoid port confusion } It "Parameter IgnoreSslPolicyErrors specified negative flow like hostname (segment-one-url)" -Skip { # replace hostname like machinename.somedomain.com to machinename only, marked as skipped for non-development machines @@ -564,7 +627,7 @@ Describe "New-IshSession" -Tags "Read" { $hostname = $webServicesBaseUrl.Substring($slash2Position+1,$slash3Position-$slash2Position-1) $computername = $hostname.Substring(0,$hostname.IndexOf(".")) $webServicesBaseUrlToComputerName = $webServicesBaseUrl.Replace($hostname,$computername) - $localIShSession = New-IshSession -WsBaseUrl $webServicesBaseUrlToComputerName -IshUserName $ishUserName -IshPassword $ishPassword -IgnoreSslPolicyErrors + $localIShSession = New-IshSession -WsBaseUrl $webServicesBaseUrlToComputerName -ClientId $amClientId -ClientSecret $amClientSecret -IgnoreSslPolicyErrors $localIShSession.ServerVersion | Should -Not -BeNullOrEmpty $localIShSession.ServerVersion.Split(".").Length | Should -Be 4 $localIShSession.Dispose() @@ -577,7 +640,7 @@ Describe "New-IshSession" -Tags "Read" { $hostname = $webServicesBaseUrl.Substring($slash2Position+1,$slash3Position-$slash2Position) $ipAddress = Resolve-DnsName –Name $hostname # only available on Windows Server 2012 R2 and Windows 8.1 $webServicesBaseUrlToIpAddress = $webServicesBaseUrl.Replace($hostname,$ipAddress) - $localIShSession = New-IshSession -WsBaseUrl $webServicesBaseUrlToIpAddress -IshUserName $ishUserName -IshPassword $ishPassword -IgnoreSslPolicyErrors + $localIShSession = New-IshSession -WsBaseUrl $webServicesBaseUrlToIpAddress -ClientId $amClientId -ClientSecret $amClientSecret -IgnoreSslPolicyErrors $localIShSession.ServerVersion | Should -Not -BeNullOrEmpty $localIShSession.ServerVersion.Split(".").Length | Should -Be 4 $localIShSession.Dispose() @@ -586,78 +649,114 @@ Describe "New-IshSession" -Tags "Read" { Context "New-IshSession over WcfSoapWithWsTrust returns IshSession ServiceReferences" { BeforeAll { - $localIShSession = New-IshSession -Protocol WcfSoapWithWsTrust -WsBaseUrl $webServicesBaseUrl -IshUserName $ishUserName -IshPassword $ishPassword + if (-not $isLinuxContainerized) { + $localIShSession = New-IshSession -Protocol WcfSoapWithWsTrust -WsBaseUrl $webServicesBaseUrl -IshUserName $ishUserName -IshPassword $ishPassword + } } It "IshSession.OpenApiISH30Client" { - if (([Version]$ishSession.ServerVersion).Major -ge 15) { # new service since 15/15.0.0 + if ((-not $isLinuxContainerized) -and (([Version]$ishSession.ServerVersion).Major -ge 15)) { # new service since 15/15.0.0 $localIShSession.OpenApiISH30Client | Should -BeNullOrEmpty } } It "IshSession.OpenApiAM10Client" { - if (([Version]$ishSession.ServerVersion).Major -ge 15) { # new service since 15/15.0.0 + if ((-not $isLinuxContainerized) -and (([Version]$ishSession.ServerVersion).Major -ge 15)) { # new service since 15/15.0.0 $localIShSession.OpenApiAM10Client | Should -BeNullOrEmpty } } It "IshSession.Annotation25" { - if (([Version]$ishSession.ServerVersion).Major -ge 14) { # new service since 14/14.0.0 + if ((-not $isLinuxContainerized) -and (([Version]$ishSession.ServerVersion).Major -ge 14)) { # new service since 14/14.0.0 $localIShSession.Annotation25 | Should -Not -BeNullOrEmpty } } It "IshSession.Application25" { - $localIShSession.Application25 | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.Application25 | Should -Not -BeNullOrEmpty + } } It "IshSession.BackgroundTask25" { # new service since 13SP2/13.0.2 - if (([Version]$ishSession.ServerVersion).Major -ge 14 -or (([Version]$ishSession.ServerVersion).Major -ge 13 -and ([Version]$ishSession.ServerVersion).Revision -ge 2)) { + if (((-not $isLinuxContainerized) -and (([Version]$ishSession.ServerVersion).Major -ge 14 -or (([Version]$ishSession.ServerVersion).Major -ge 13 -and ([Version]$ishSession.ServerVersion).Revision -ge 2)))) { $localIShSession.BackgroundTask25 | Should -Not -BeNullOrEmpty } } It "IshSession.Baseline25" { - $localIShSession.Baseline25 | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.Baseline25 | Should -Not -BeNullOrEmpty + } } It "IshSession.DocumentObj25" { - $localIShSession.DocumentObj25 | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.DocumentObj25 | Should -Not -BeNullOrEmpty + } } It "IshSession.EDT25" { - $localIShSession.EDT25 | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.EDT25 | Should -Not -BeNullOrEmpty + } } It "IshSession.EventMonitor25" { - $localIShSession.EventMonitor25 | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.EventMonitor25 | Should -Not -BeNullOrEmpty + } } It "IshSession.Folder25" { - $localIShSession.Folder25 | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.Folder25 | Should -Not -BeNullOrEmpty + } } It "IshSession.ListOfValues25" { - $localIShSession.ListOfValues25 | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.ListOfValues25 | Should -Not -BeNullOrEmpty + } } It "IshSession.MetadataBinding25" { - $localIShSession.MetadataBinding25 | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.MetadataBinding25 | Should -Not -BeNullOrEmpty + } } It "IshSession.OutputFormat25" { - $localIShSession.OutputFormat25 | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.OutputFormat25 | Should -Not -BeNullOrEmpty + } } It "IshSession.PublicationOutput25" { - $localIShSession.PublicationOutput25 | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.PublicationOutput25 | Should -Not -BeNullOrEmpty + } } It "IshSession.Search25" { - $localIShSession.Search25 | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.Search25 | Should -Not -BeNullOrEmpty + } } It "IshSession.Settings25" { - $localIShSession.Settings25 | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.Settings25 | Should -Not -BeNullOrEmpty + } } It "IshSession.TranslationJob25" { - $localIShSession.TranslationJob25 | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.TranslationJob25 | Should -Not -BeNullOrEmpty + } } It "IshSession.TranslationTemplate25" { - $localIShSession.TranslationTemplate25 | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.TranslationTemplate25 | Should -Not -BeNullOrEmpty + } } It "IshSession.User25" { - $localIShSession.User25 | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.User25 | Should -Not -BeNullOrEmpty + } } It "IshSession.UserGroup25" { - $localIShSession.UserGroup25 | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.UserGroup25 | Should -Not -BeNullOrEmpty + } } It "IshSession.UserRole25" { - $localIShSession.UserRole25 | Should -Not -BeNullOrEmpty + if (-not $isLinuxContainerized) { + $localIShSession.UserRole25 | Should -Not -BeNullOrEmpty + } } } diff --git a/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/Session/TestIshSession.Tests.ps1 b/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/Session/TestIshSession.Tests.ps1 index e105061..c8f2653 100644 --- a/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/Session/TestIshSession.Tests.ps1 +++ b/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/Session/TestIshSession.Tests.ps1 @@ -63,9 +63,11 @@ Describe "Test-IshSession" -Tags "Read" { Test-IshSession -WsBaseUrl $webServicesBaseUrl -PSCredential $mycredentials | Should -Be $false } It "Parameter PSCredential over WcfSoapWithWsTrust" { - $securePassword = ConvertTo-SecureString $ishPassword -AsPlainText -Force - $mycredentials = New-Object System.Management.Automation.PSCredential ($ishUserName, $securePassword) - Test-IshSession -Protocol WcfSoapWithWsTrust -WsBaseUrl $webServicesBaseUrl -PSCredential $mycredentials | Should -Be $true + if (-not $isLinuxContainerized) { + $securePassword = ConvertTo-SecureString $ishPassword -AsPlainText -Force + $mycredentials = New-Object System.Management.Automation.PSCredential ($ishUserName, $securePassword) + Test-IshSession -Protocol WcfSoapWithWsTrust -WsBaseUrl $webServicesBaseUrl -PSCredential $mycredentials | Should -Be $true + } } It "Parameter PSCredential over WcfSoapWithOpenIdConnect" { if (([Version]$ishSession.ServerVersion).Major -ge 15) { # new service since 15/15.0.0 @@ -115,7 +117,7 @@ Describe "Test-IshSession" -Tags "Read" { It "WsBaseUrl without ending slash" { # .NET throws unhandy "Reference to undeclared entity 'raquo'." error $webServicesBaseUrlWithoutEndingSlash = $webServicesBaseUrl.Substring(0,$webServicesBaseUrl.Length-1) - Test-IshSession -WsBaseUrl $webServicesBaseUrlWithoutEndingSlash -IshUserName $ishUserName -IshPassword $ishPassword | Should -Be $true + Test-IshSession -WsBaseUrl $webServicesBaseUrlWithoutEndingSlash -ClientId $amClientId -ClientSecret $amClientSecret | Should -Be $true } } diff --git a/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/_TestEnvironment/TestPrerequisite.Tests.ps1 b/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/_TestEnvironment/TestPrerequisite.Tests.ps1 index 0ac5bcf..3c90e18 100644 --- a/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/_TestEnvironment/TestPrerequisite.Tests.ps1 +++ b/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/_TestEnvironment/TestPrerequisite.Tests.ps1 @@ -34,34 +34,6 @@ Describe "Test-Prerequisite" -Tags "Read" { } } - Context "IshSession (-lt 16) - Validating overwrites of ISHRemote.PesterSetup.Debug.ps1" { - BeforeAll { - $ishSession = New-IshSession -Protocol WcfSoapWithWsTrust -WsBaseUrl $webServicesBaseUrl -IshUserName $ishUserName -IshPassword $ishPassword - $ishUser = Get-IshUser - } - It "IshSession.Protocol WcfSoapWithWsTrust" { - $IshSession.Protocol | Should -Be 'WcfSoapWithWsTrust' - } - It "Current IShSession user should be part of VUSERGROUPSYSTEMMANAGEMENT UserGroup" { - $ishUser.fusergroup_none_element -like "*VUSERGROUPSYSTEMMANAGEMENT*" | Should -Be $true - } - It "IshSession.AuthenticationContext" { - $ishSession.AuthenticationContext | Should -Not -BeNullOrEmpty - } - It "IshSession.ClientVersion" { - $ishSession.ClientVersion | Should -Not -BeNullOrEmpty - } - It "IshSession.ClientVersion not 0.0.0.0" { - $ishSession.ClientVersion | Should -Not -Be "0.0.0.0" - } - It "IshSession.ServerVersion empty (ISHWS down?)" { - $ishSession.ServerVersion | Should -Not -BeNullOrEmpty - } - It "IshSession.ServerVersion not 0.0.0.0" { - $ishSession.ServerVersion | Should -Not -Be "0.0.0.0" - } - } - Context "IshSession (-eq 15) - Validating overwrites of ISHRemote.PesterSetup.Debug.ps1" { BeforeAll { $ishSession = New-IshSession -WsBaseUrl $webServicesBaseUrl -ClientId $amClientId -ClientSecret $amClientSecret @@ -87,6 +59,21 @@ Describe "Test-Prerequisite" -Tags "Read" { $ishUser.username | Should -Be $ishUserName } } + It "IshSession.AuthenticationContext" { + $ishSession.AuthenticationContext | Should -Not -BeNullOrEmpty + } + It "IshSession.ClientVersion" { + $ishSession.ClientVersion | Should -Not -BeNullOrEmpty + } + It "IshSession.ClientVersion not 0.0.0.0" { + $ishSession.ClientVersion | Should -Not -Be "0.0.0.0" + } + It "IshSession.ServerVersion empty (ISHWS down?)" { + $ishSession.ServerVersion | Should -Not -BeNullOrEmpty + } + It "IshSession.ServerVersion not 0.0.0.0" { + $ishSession.ServerVersion | Should -Not -Be "0.0.0.0" + } } Context "IshFolder - Manual clean up required, probably a lock blocked the previous test clean-up" { @@ -147,8 +134,15 @@ Describe "Test-Prerequisite" -Tags "Read" { Context "User - Potential overwrite in ISHRemote.PesterSetup.Debug.ps1" { BeforeAll { - $ishSession = New-IshSession -WsBaseUrl $webServicesBaseUrl -IshUserName $ishUserName -IshPassword $ishPassword - $ishUser = Get-IshUser -RequestedMetadata (Set-IshRequestedMetadataField -Level None -Name FUSERGROUP) + if ($isLinuxContainerized) { + # Detecting Containerization; Windows .NET-Framework-based WcfSoapWithWsTrust not supported, so forcing newer route + $ishSession = New-IshSession -Protocol WcfSoapWithOpenIdConnect -WsBaseUrl $webServicesBaseUrl -ClientId $amClientId -ClientSecret $amClientSecret + $ishUser = Get-IshUser -RequestedMetadata (Set-IshRequestedMetadataField -Level None -Name FUSERGROUP) + } + else { + $ishSession = New-IshSession -Protocol WcfSoapWithWsTrust -WsBaseUrl $webServicesBaseUrl -IshUserName $ishUserName -IshPassword $ishPassword + $ishUser = Get-IshUser -RequestedMetadata (Set-IshRequestedMetadataField -Level None -Name FUSERGROUP) + } } It "Current User has UserRole Administrator access" { $ishUser.fishuserroles_none_element -like '*VUSERROLEADMINISTRATOR*' | Should -Be $true diff --git a/Source/ISHRemote/Trisoft.ISHRemote/ISHRemote.PesterSetup.ps1 b/Source/ISHRemote/Trisoft.ISHRemote/ISHRemote.PesterSetup.ps1 index d58407c..348bfd6 100644 --- a/Source/ISHRemote/Trisoft.ISHRemote/ISHRemote.PesterSetup.ps1 +++ b/Source/ISHRemote/Trisoft.ISHRemote/ISHRemote.PesterSetup.ps1 @@ -109,12 +109,16 @@ if (Test-Path -Path $debugPesterSetupFilePath -PathType Leaf) # $ishPassword = 'mypassword' # $amClientId = 'myserviceaccountclientid' # $amClientSecret = 'myserviceaccountclientsecret' + # $isLinuxContainerized = $baseUrl.Contains('.sdldev.net') # $true to indicate containerization skipping Windows-only .NET Framework features like WcfSoapWithWsTrust protocol; version 15.3.0 is insufficient } #endregion $webServicesBaseUrl -match "https://((?.+))+/(.)+/" | Out-Null $hostname=$Matches['hostname'] +#$true to indicate containerization skipping Windows-only .NET Framework features like WcfSoapWithWsTrust protocol; version 15.3.0 is insufficient +$isLinuxContainerized = $baseUrl.Contains('.sdldev.net') + # # Note # * Only variables and generic PowerShell object initialization @@ -124,9 +128,10 @@ $hostname=$Matches['hostname'] #{ $webServicesConnectionConfigurationUrl = $webServicesBaseUrl + "connectionconfiguration.xml" Write-Host "Running ISHRemote.PesterSetup.ps1 Detect version over webServicesConnectionConfigurationUrl[$webServicesConnectionConfigurationUrl] webServicesConnectionConfigurationUrl.Length[$($webServicesConnectionConfigurationUrl.Length)]" - $connectionConfigurationRaw = Invoke-RestMethod -Uri $webServicesConnectionConfigurationUrl #Only PS7#-SkipCertificateCheck + # $connectionConfigurationRaw = Invoke-RestMethod -Uri $webServicesConnectionConfigurationUrl #Only PS7#-SkipCertificateCheck + $connectionConfigurationRaw = (Invoke-WebRequest -Uri $webServicesConnectionConfigurationUrl).Content #as Kestrel/IIS behave differently $connectionConfigurationRaw -match "(?.*)" # Straight string handling avoids UTF8-BOM cross-platform handling - [version]$infosharesoftwareversion = $matches['myversion'] + [version]$infosharesoftwareversion = $matches['myVersion'] if ($infosharesoftwareversion.Major -lt 15) # 14SP4 and earlier, initialize ONE session over -IshUserName/-IshPassword { $global:ishSession = New-IshSession -Protocol WcfSoapWithWsTrust -WsBaseUrl $webServicesBaseUrl -IshUserName $ishUserName -IshPassword $ishPassword -WarningAction SilentlyContinue From e0f3885dcba8edd681cdeca5c8865b17f19b6427 Mon Sep 17 00:00:00 2001 From: ddemeyer Date: Tue, 17 Mar 2026 13:43:46 +0100 Subject: [PATCH 3/3] #230 Invoke-WebRequest needs -UseBasicParsing on Windows PowerShell to comply with security standards --- Source/ISHRemote/Trisoft.ISHRemote/ISHRemote.PesterSetup.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/ISHRemote/Trisoft.ISHRemote/ISHRemote.PesterSetup.ps1 b/Source/ISHRemote/Trisoft.ISHRemote/ISHRemote.PesterSetup.ps1 index 348bfd6..fa75c50 100644 --- a/Source/ISHRemote/Trisoft.ISHRemote/ISHRemote.PesterSetup.ps1 +++ b/Source/ISHRemote/Trisoft.ISHRemote/ISHRemote.PesterSetup.ps1 @@ -129,7 +129,7 @@ $isLinuxContainerized = $baseUrl.Contains('.sdldev.net') $webServicesConnectionConfigurationUrl = $webServicesBaseUrl + "connectionconfiguration.xml" Write-Host "Running ISHRemote.PesterSetup.ps1 Detect version over webServicesConnectionConfigurationUrl[$webServicesConnectionConfigurationUrl] webServicesConnectionConfigurationUrl.Length[$($webServicesConnectionConfigurationUrl.Length)]" # $connectionConfigurationRaw = Invoke-RestMethod -Uri $webServicesConnectionConfigurationUrl #Only PS7#-SkipCertificateCheck - $connectionConfigurationRaw = (Invoke-WebRequest -Uri $webServicesConnectionConfigurationUrl).Content #as Kestrel/IIS behave differently + $connectionConfigurationRaw = (Invoke-WebRequest -Uri $webServicesConnectionConfigurationUrl -UseBasicParsing).Content #as Kestrel/IIS behave differently $connectionConfigurationRaw -match "(?.*)" # Straight string handling avoids UTF8-BOM cross-platform handling [version]$infosharesoftwareversion = $matches['myVersion'] if ($infosharesoftwareversion.Major -lt 15) # 14SP4 and earlier, initialize ONE session over -IshUserName/-IshPassword