diff --git a/readme.md b/.github/readme.md similarity index 75% rename from readme.md rename to .github/readme.md index 67d7052..bb80d4b 100644 --- a/readme.md +++ b/.github/readme.md @@ -1,9 +1,12 @@ # PSIdentityNow [![PSIdentityNow](https://img.shields.io/powershellgallery/v/PSIdentityNow.svg?style=flat-square&label=Powershell%20Gallery)](https://www.powershellgallery.com/packages/PSIdentityNow/) ![powershell gallery](https://img.shields.io/powershellgallery/dt/PSIdentityNow) -[![License](https://img.shields.io/badge/license-GPL–3.0-blue.svg)](https://github.com/EUCTechTopics/PSIdentityNow/blob/main/LICENSE) +[![License](https://img.shields.io/badge/license-GPL–3.0-blue.svg)](/LICENSE) +[![Pester Tests](https://github.com/EUCTechTopics/PSIdentityNow/actions/workflows/run-pester.yml/badge.svg?branch=next)](https://github.com/EUCTechTopics/PSIdentityNow/actions/workflows/run-pester.yml) +[![PSScriptAnalyzer](https://github.com/EUCTechTopics/PSIdentityNow/actions/workflows/run-psscriptanalyzer.yml/badge.svg)](https://github.com/EUCTechTopics/PSIdentityNow/actions/workflows/run-psscriptanalyzer.yml) + ## Summary A PowerShell module to interact with the IdentityNow REST API. @@ -55,6 +58,12 @@ To use the SDK with your IdentityNow tenant, you must configure authentication b Alternatively, you can use instance specific environment variables. If these variables are set, you have to specify the `-Instance` parameter when running `Connect-IDNW`: ```powershell + $env:IDNW_DEV_BASE_URL=https://[tenant]-dev.api.identitynow.com + $env:IDNW_DEV_CLIENT_ID=[clientID] + $env:IDNW_DEV_CLIENT_SECRET=[clientSecret] + $env:IDNW_TST_BASE_URL=https://[tenant]-tst.api.identitynow.com + $env:IDNW_TST_CLIENT_ID=[clientID] + $env:IDNW_TST_CLIENT_SECRET=[clientSecret] $env:IDNW_ACC_BASE_URL=https://[tenant]-sb.api.identitynow.com $env:IDNW_ACC_CLIENT_ID=[clientID] $env:IDNW_ACC_CLIENT_SECRET=[clientSecret] @@ -65,13 +74,19 @@ To use the SDK with your IdentityNow tenant, you must configure authentication b 2. **Connect to IdentityNow** - Use the `Connect-IDNW` command to authenticate using secrets from the registered Key Vault. Specify the `-Instance` parameter (e.g., `ACC` or `PRD`) as needed: + Use the `Connect-IDNW` command to authenticate using secrets from the registered Key Vault. Specify the `-Instance` parameter (e.g., `DEV`, `TST`, `ACC` or `PRD`) as needed: ```powershell # Using generic environment variables Connect-IDNW + # Using instance specific environment variables (DEV) + Connect-IDNW -Instance DEV + + # Using instance specific environment variables (TST) + Connect-IDNW -Instance TST + # Using instance specific environment variables (ACC) Connect-IDNW -Instance ACC @@ -95,6 +110,12 @@ You can securely store and manage the required credentials in Azure Key Vault an Alternatively, you can use instance specific environment variables. If these variables are set, you have to specify the `-Instance` parameter when running `Connect-IDNW`: ``` yaml + IDNW-DEV-BASE-URL + IDNW-DEV-CLIENT-ID + IDNW-DEV-CLIENT-SECRET + IDNW-TST-BASE-URL + IDNW-TST-CLIENT-ID + IDNW-TST-CLIENT-SECRET IDNW-ACC-BASE-URL IDNW-ACC-CLIENT-ID IDNW-ACC-CLIENT-SECRET @@ -120,13 +141,19 @@ You can securely store and manage the required credentials in Azure Key Vault an 3. **Connect to IdentityNow using SecretManagement** - Use the `Connect-IDNW` command with the `-UseSecretManagement` parameter to authenticate using secrets from the registered Key Vault. Specify the `-Instance` parameter (e.g., `ACC` or `PRD`) as needed: + Use the `Connect-IDNW` command with the `-UseSecretManagement` parameter to authenticate using secrets from the registered Key Vault. Specify the `-Instance` parameter (e.g., `DEV`, `TST`, `ACC` or `PRD`) as needed: ```powershell # Using generic secrets Connect-IDNW -UseSecretManagement + # Using instance specific secrets (DEV) + Connect-IDNW -Instance DEV -UseSecretManagement + + # Using instance specific secrets (TST) + Connect-IDNW -Instance TST -UseSecretManagement + # Using instance specific secrets (ACC) Connect-IDNW -Instance ACC -UseSecretManagement @@ -142,21 +169,21 @@ You can securely store and manage the required credentials in Azure Key Vault an ## Functions -#### [Connect-IDNW](Documentation/Connect-IDNW.md) +#### [Connect-IDNW](/Documentation/Connect-IDNW.md) Connects to IdentityNow. -#### [Disconnect-IDNW](Documentation/Disconnect-IDNW.md) +#### [Disconnect-IDNW](/Documentation/Disconnect-IDNW.md) Disconnects from IdentityNow. -#### [Get-IDNWObject](Documentation/Get-IDNWObject.md) +#### [Get-IDNWObject](/Documentation/Get-IDNWObject.md) Get the specified objects from IdentityNow. -#### [Get-IDNWOrg](Documentation/Get-IDNWOrg.md) +#### [Get-IDNWOrg](/Documentation/Get-IDNWOrg.md) Get the IdentityNow Organisation. -#### [Invoke-IDNWRestMethod](Documentation/Invoke-IDNWRestMethod.md) +#### [Invoke-IDNWRestMethod](/Documentation/Invoke-IDNWRestMethod.md) Invoke the IdentityNow REST API. -#### [New-IDNWObject](Documentation/New-IDNWObject.md) +#### [New-IDNWObject](/Documentation/New-IDNWObject.md) Create a new object in IdentityNow. -#### [Remove-IDNWObject](Documentation/Remove-IDNWObject.md) +#### [Remove-IDNWObject](/Documentation/Remove-IDNWObject.md) Delete an object in IdentityNow. -#### [Set-IDNWObject](Documentation/Set-IDNWObject.md) +#### [Set-IDNWObject](/Documentation/Set-IDNWObject.md) Update an object in IdentityNow. ## Reporting Issues and Feedback diff --git a/CHANGELOG.md b/CHANGELOG.md index f9d2150..4f8950c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) +## [0.5.2] - 2025-09-08 + +### Fixed + +- Added 'post' to methods for pagination in Invoke-IDNWRestMethod ([#45](https://github.com/EUCTechTopics/PSIdentityNow/pull/45)) + +[0.5.2]: https://github.com/EUCTechTopics/PSIdentityNow/releases/tag/v0.5.2 + +## [0.5.1] - 2025-04-10 + +### Fixed + +- Added 'present' to noValueOperators in Test-IDNWFilter ([#40](https://github.com/EUCTechTopics/PSIdentityNow/pull/40)) + +[0.5.1]: https://github.com/EUCTechTopics/PSIdentityNow/releases/tag/v0.5.1 + +## [0.5.0] - 2025-03-12 + +### Changed + +- Changed possible Instance values to DEV, TST, ACC, PRD ([#35](https://github.com/EUCTechTopics/PSIdentityNow/pull/35)) + +[0.5.0]: https://github.com/EUCTechTopics/PSIdentityNow/releases/tag/v0.5.0 + ## [0.4.0] - 2025-02-27 ### Changed @@ -61,4 +85,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Initial Version \ No newline at end of file +- Initial Version diff --git a/Documentation/Connect-IDNW.md b/Documentation/Connect-IDNW.md index 156572a..9a41ee3 100644 --- a/Documentation/Connect-IDNW.md +++ b/Documentation/Connect-IDNW.md @@ -14,7 +14,23 @@ This function connects to IdentityNow and sets the environment variables for the ## EXAMPLES ```powershell -------------------------- EXAMPLE 1 -------------------------- -Connect-IDNW -Instance "Sandbox" +Connect-IDNW -Instance "DEV" -APIVersion "beta" +Connects to the DEV instance using the beta API version. + + +-------------------------- EXAMPLE 2 -------------------------- +Connect-IDNW -Instance "TST" -APIVersion "v3" +Connects to the TST instance using the v3 API version. + + +-------------------------- EXAMPLE 3 -------------------------- +Connect-IDNW -Instance "ACC" -APIVersion "v3" +Connects to the ACC instance using the v3 API version. + + +-------------------------- EXAMPLE 4 -------------------------- +Connect-IDNW -Instance "PRD" -APIVersion "v3" -UseSecretManagement +Connects to the PRD instance using the v3 API version and retrieves secrets using Microsoft.PowerShell.SecretManagement. ``` diff --git a/PSIdentityNow/PSIdentityNow.psd1 b/PSIdentityNow/PSIdentityNow.psd1 index 6937976..770a4f3 100644 --- a/PSIdentityNow/PSIdentityNow.psd1 +++ b/PSIdentityNow/PSIdentityNow.psd1 @@ -12,7 +12,7 @@ RootModule = 'PSIdentityNow.psm1' # Version number of this module. - ModuleVersion = '0.4.0' + ModuleVersion = '0.5.2' # Supported PSEditions CompatiblePSEditions = 'Core' @@ -128,4 +128,4 @@ # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. # DefaultCommandPrefix = '' -} \ No newline at end of file +} diff --git a/PSIdentityNow/Private/Get-IDNWEnvironment.ps1 b/PSIdentityNow/Private/Get-IDNWEnvironment.ps1 index 3603007..c4e584d 100644 --- a/PSIdentityNow/Private/Get-IDNWEnvironment.ps1 +++ b/PSIdentityNow/Private/Get-IDNWEnvironment.ps1 @@ -6,7 +6,7 @@ This function gets the environment details for the specified IdentityNow instance. The function will return the base URL, the base API URL, the session token data, the session token, and the API version. .EXAMPLE - Get-IDNWEnvironment -Instance "Sandbox" + Get-IDNWEnvironment .PARAMETER Instance The IdentityNow instance to get the environment details for. @@ -28,7 +28,7 @@ function Get-IDNWEnvironment { param ( [Parameter(Mandatory = $false)] [Alias("Environment")] - [ValidateSet("Sandbox", "ACC", "PRD")] + [ValidateSet("DEV", "TST", "ACC", "PRD")] [String] $Instance, @@ -55,22 +55,14 @@ function Get-IDNWEnvironment { } # Determine correct set of secrets for session - switch ($Instance.ToLower()) { - { "sandbox", "acc" -contains $_ } { - $sail_base_url = Get-IDNWSecret -Name 'IDNW-ACC-BASE-URL' -AsPlainText -UseSecretManagement:$UseSecretManagement - $sail_client_id = Get-IDNWSecret -Name 'IDNW-ACC-CLIENT-ID' -AsPlainText -UseSecretManagement:$UseSecretManagement - $sail_client_secret = Get-IDNWSecret -Name 'IDNW-ACC-CLIENT-SECRET'-UseSecretManagement:$UseSecretManagement - } - "prd" { - $sail_base_url = Get-IDNWSecret -Name 'IDNW-PRD-BASE-URL' -AsPlainText -UseSecretManagement:$UseSecretManagement - $sail_client_id = Get-IDNWSecret -Name 'IDNW-PRD-CLIENT-ID' -AsPlainText -UseSecretManagement:$UseSecretManagement - $sail_client_secret = Get-IDNWSecret -Name 'IDNW-PRD-CLIENT-SECRET'-UseSecretManagement:$UseSecretManagement - } - default { - $sail_base_url = Get-IDNWSecret -Name 'IDNW-BASE-URL' -AsPlainText -UseSecretManagement:$UseSecretManagement - $sail_client_id = Get-IDNWSecret -Name 'IDNW-CLIENT-ID' -AsPlainText -UseSecretManagement:$UseSecretManagement - $sail_client_secret = Get-IDNWSecret -Name 'IDNW-CLIENT-SECRET'-UseSecretManagement:$UseSecretManagement - } + if($Instance) { + $sail_base_url = Get-IDNWSecret -Name "IDNW-$($Instance.ToUpper())-BASE-URL" -AsPlainText -UseSecretManagement:$UseSecretManagement + $sail_client_id = Get-IDNWSecret -Name "IDNW-$($Instance.ToUpper())-CLIENT-ID" -AsPlainText -UseSecretManagement:$UseSecretManagement + $sail_client_secret = Get-IDNWSecret -Name "IDNW-$($Instance.ToUpper())-CLIENT-SECRET" -UseSecretManagement:$UseSecretManagement + } else { + $sail_base_url = Get-IDNWSecret -Name 'IDNW-BASE-URL' -AsPlainText -UseSecretManagement:$UseSecretManagement + $sail_client_id = Get-IDNWSecret -Name 'IDNW-CLIENT-ID' -AsPlainText -UseSecretManagement:$UseSecretManagement + $sail_client_secret = Get-IDNWSecret -Name 'IDNW-CLIENT-SECRET' -UseSecretManagement:$UseSecretManagement } $sessiontokendata = @{ diff --git a/PSIdentityNow/Private/Test-IDNWFilter.ps1 b/PSIdentityNow/Private/Test-IDNWFilter.ps1 index f5e2d29..2710d5b 100644 --- a/PSIdentityNow/Private/Test-IDNWFilter.ps1 +++ b/PSIdentityNow/Private/Test-IDNWFilter.ps1 @@ -29,7 +29,7 @@ function Test-IDNWFilter { $operator = $Filter['operator'].ToLower() # Operators that don't require a 'value' - $noValueOperators = @('pr', 'isnull') + $noValueOperators = @('pr', 'present', 'isnull') if ($operator -in $noValueOperators) { if ($Filter.ContainsKey('value') -and $null -ne $Filter['value']) { diff --git a/PSIdentityNow/Public/Connect-IDNW.ps1 b/PSIdentityNow/Public/Connect-IDNW.ps1 index 24b32c1..12d01de 100644 --- a/PSIdentityNow/Public/Connect-IDNW.ps1 +++ b/PSIdentityNow/Public/Connect-IDNW.ps1 @@ -6,7 +6,20 @@ This function connects to IdentityNow and sets the environment variables for the specified instance. .EXAMPLE - Connect-IDNW -Instance "Sandbox" + Connect-IDNW -Instance "DEV" -APIVersion "beta" + Connects to the DEV instance using the beta API version. + + .EXAMPLE + Connect-IDNW -Instance "TST" -APIVersion "v3" + Connects to the TST instance using the v3 API version. + + .EXAMPLE + Connect-IDNW -Instance "ACC" -APIVersion "v3" + Connects to the ACC instance using the v3 API version. + + .EXAMPLE + Connect-IDNW -Instance "PRD" -APIVersion "v3" -UseSecretManagement + Connects to the PRD instance using the v3 API version and retrieves secrets using Microsoft.PowerShell.SecretManagement. .PARAMETER Instance The IdentityNow instance to connect to. @@ -35,7 +48,7 @@ function Connect-IDNW { param ( [Parameter(Mandatory = $false)] [Alias("Environment")] - [ValidateSet("Sandbox", "ACC", "PRD")] + [ValidateSet("DEV", "TST", "ACC", "PRD")] [String] $Instance, @@ -49,15 +62,6 @@ function Connect-IDNW { $UseSecretManagement = $false ) - switch ($Instance.ToLower()) { - { "sandbox" } { - $Instance = "Sandbox" - } - { "prd", "acc" -contains $_ } { - $Instance = $_.ToUpper() - } - } - $Parameters = @{ APIVersion = $APIVersion UseSecretManagement = $UseSecretManagement @@ -97,6 +101,7 @@ function Connect-IDNW { Instance: $Instance Tenant ID: $($script:IDNWEnv.SessionTokenDetails.tenant_id) +User: $($script:IDNWEnv.SessionTokenDetails.user_name) Pod: $($script:IDNWEnv.SessionTokenDetails.pod) Org: $($script:IDNWEnv.SessionTokenDetails.org) Authorities: $($script:IDNWEnv.SessionTokenDetails.Authorities -join ', ') diff --git a/PSIdentityNow/Public/Invoke-IDNWRestMethod.ps1 b/PSIdentityNow/Public/Invoke-IDNWRestMethod.ps1 index 8f32410..b77b600 100644 --- a/PSIdentityNow/Public/Invoke-IDNWRestMethod.ps1 +++ b/PSIdentityNow/Public/Invoke-IDNWRestMethod.ps1 @@ -112,7 +112,7 @@ function Invoke-IDNWRestMethod { # Pagination loop do { # Combine parameters into query string - if ($Method -eq "GET") { + if ($Method -in @("GET","POST")) { $queryString = ($UrlParams.GetEnumerator() | ForEach-Object { [string]::Format("{0}={1}", $_.Key, [uri]::EscapeUriString($_.Value)) }) -join "&" @@ -226,4 +226,4 @@ function Invoke-IDNWRestMethod { # Return all results Remove-Variable -Name Headers -Force Write-Output $AllResults -} \ No newline at end of file +} diff --git a/Tests/Get-IDNWEnvironment.Tests.ps1 b/Tests/Get-IDNWEnvironment.Tests.ps1 new file mode 100644 index 0000000..03fd7ce --- /dev/null +++ b/Tests/Get-IDNWEnvironment.Tests.ps1 @@ -0,0 +1,17 @@ +# Requires -Module Pester +Describe "Get-IDNWEnvironment" { + + BeforeAll { + . "../PSIdentityNow/Private/Get-IDNWEnvironment.ps1" + . "../PSIdentityNow/Private/Get-IDNWSecret.ps1" + . "../PSIdentityNow/Private/Get-IDNWSessionToken.ps1" + . "../PSIdentityNow/Private/Get-IDNWTokenDetail.ps1" + } + + It "Should return a valid token" { + $Environment = Get-IDNWEnvironment -ApiVersion "v3" -UseSecretManagement:$false + $Environment.SessionToken | Should -BeOfType "System.Security.SecureString" + [guid]$Environment.SessionTokenDetails.tenant_id | Should -BeOfType "System.Guid" + } + +} diff --git a/Tests/Get-IDNWFilterString.Tests.ps1 b/Tests/Get-IDNWFilterString.Tests.ps1 new file mode 100644 index 0000000..fbfccd3 --- /dev/null +++ b/Tests/Get-IDNWFilterString.Tests.ps1 @@ -0,0 +1,89 @@ +# Requires -Module Pester +Describe "Get-IDNWFilterString" { + + BeforeAll { + . "../PSIdentityNow/Private/Get-IDNWFilterString.ps1" + . "../PSIdentityNow/Private/Test-IDNWFilter.ps1" + } + + It "should handle string values correctly" { + $filters = @(@{ field = "name"; operator = "eq"; value = "test" }) + $result = Get-IDNWFilterString -Filters $filters + $result | Should -Be 'name eq "test"' + } + + It "should handle integer values correctly" { + $filters = @(@{ field = "count"; operator = "eq"; value = 5 }) + $result = Get-IDNWFilterString -Filters $filters + $result | Should -Be 'count eq 5' + } + + It "should handle boolean values correctly" { + $filters = @(@{ field = "enabled"; operator = "eq"; value = $true }) + $result = Get-IDNWFilterString -Filters $filters + $result | Should -Be 'enabled eq true' + } + + It "should handle 'present' operator correctly" { + $filters = @(@{ field = "email"; operator = "present"; value = $null }) + $result = Get-IDNWFilterString -Filters $filters + $result | Should -Be 'pr email' + } + + It "should handle 'isnull' operator correctly" { + $filters = @(@{ field = "lastLogin"; operator = "isnull"; value = $null }) + $result = Get-IDNWFilterString -Filters $filters + $result | Should -Be 'lastLogin isnull' + } + + It "should handle array values with 'in' operator correctly" { + $filters = @(@{ field = "id"; operator = "in"; value = @("one", "two") }) + $result = Get-IDNWFilterString -Filters $filters + $result | Should -Be 'id in ("one","two")' + } + + It "should handle 'containsall' operator and arrays correctly" { + $filters = @(@{ field = "tags"; operator = "containsall"; value = @("foo", "bar") }) + $result = Get-IDNWFilterString -Filters $filters + $result | Should -Be 'tags ca ("foo","bar")' + } + + It "should handle 'contains' operator and string values correctly" { + $filters = @(@{ field = "description"; operator = "contains"; value = "admin" }) + $result = Get-IDNWFilterString -Filters $filters + $result | Should -Be 'description co "admin"' + } + + It "should handle 'startswith' operator correctly" { + $filters = @(@{ field = "username"; operator = "startswith"; value = "dev" }) + $result = Get-IDNWFilterString -Filters $filters + $result | Should -Be 'username sw "dev"' + } + + It "should handle DateTime values correctly" { + $dt = Get-Date -Date "2024-01-01T12:00:00" + $filters = @(@{ field = "created"; operator = "ge"; value = $dt }) + $result = Get-IDNWFilterString -Filters $filters + $result | Should -Be 'created ge 2024-01-01T12:00:00Z' + } + + It "should handle multiple filters combined with 'and'" { + $filters = @( + @{ field = "name"; operator = "eq"; value = "admin" }, + @{ field = "enabled"; operator = "eq"; value = $true } + ) + $result = Get-IDNWFilterString -Filters $filters + $result | Should -Be 'name eq "admin" and enabled eq true' + } + + It "should escape double quotes in string values" { + $filters = @(@{ field = "comment"; operator = "eq"; value = 'He said "hello"' }) + $result = Get-IDNWFilterString -Filters $filters + $result | Should -Be 'comment eq "He said \"hello\""' + } + + It "should throw on unsupported value types" { + $filters = @(@{ field = "bad"; operator = "eq"; value = @{ unexpected = "type" } }) + { Get-IDNWFilterString -Filters $filters } | Should -Throw + } +}