Skip to content

Commit e22be1d

Browse files
authored
feat: Add SAML metadata preview cmdlet for applications (#96)
1 parent 4de7f44 commit e22be1d

File tree

8 files changed

+281
-28
lines changed

8 files changed

+281
-28
lines changed

API_README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ Class | Method | HTTP request | Description
5454
*OktaApplicationApi* | [**Invoke-OktaListFeaturesForApplication**](docs/OktaApplicationApi.md#Invoke-OktaListFeaturesForApplication) | **GET** /api/v1/apps/{appId}/features | List all Features
5555
*OktaApplicationApi* | [**Invoke-OktaListOAuth2TokensForApplication**](docs/OktaApplicationApi.md#Invoke-OktaListOAuth2TokensForApplication) | **GET** /api/v1/apps/{appId}/tokens | List all OAuth 2.0 Tokens
5656
*OktaApplicationApi* | [**Invoke-OktaListScopeConsentGrants**](docs/OktaApplicationApi.md#Invoke-OktaListScopeConsentGrants) | **GET** /api/v1/apps/{appId}/grants | List all Scope Consent Grants
57+
*OktaApplicationApi* | [**Invoke-OktaPreviewSAMLMetadataForApplication**](docs/OktaApplicationApi.md#Invoke-OktaPreviewSAMLMetadataForApplication) | **GET** /api/v1/apps/{appId}/sso/saml/metadata | Preview SAML Metadata
5758
*OktaApplicationApi* | [**Publish-OktaCsrFromApplication**](docs/OktaApplicationApi.md#Publish-OktaCsrFromApplication) | **POST** /api/v1/apps/{appId}/credentials/csrs/{csrId}/lifecycle/publish | Publish a Certificate Signing Request
5859
*OktaApplicationApi* | [**Revoke-OktaCsrFromApplication**](docs/OktaApplicationApi.md#Revoke-OktaCsrFromApplication) | **DELETE** /api/v1/apps/{appId}/credentials/csrs/{csrId} | Revoke a Certificate Signing Request
5960
*OktaApplicationApi* | [**Revoke-OktaOAuth2TokenForApplication**](docs/OktaApplicationApi.md#Revoke-OktaOAuth2TokenForApplication) | **DELETE** /api/v1/apps/{appId}/tokens/{tokenId} | Revoke an OAuth 2.0 Token

docs/OktaApplicationApi.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Method | HTTP request | Description
3636
[**Invoke-OktaListFeaturesForApplication**](OktaApplicationApi.md#Invoke-OktaListFeaturesForApplication) | **GET** /api/v1/apps/{appId}/features | List all Features
3737
[**Invoke-OktaListOAuth2TokensForApplication**](OktaApplicationApi.md#Invoke-OktaListOAuth2TokensForApplication) | **GET** /api/v1/apps/{appId}/tokens | List all OAuth 2.0 Tokens
3838
[**Invoke-OktaListScopeConsentGrants**](OktaApplicationApi.md#Invoke-OktaListScopeConsentGrants) | **GET** /api/v1/apps/{appId}/grants | List all Scope Consent Grants
39+
[**Invoke-OktaPreviewSAMLMetadataForApplication**](OktaApplicationApi.md#Invoke-OktaPreviewSAMLMetadataForApplication) | **GET** /api/v1/apps/{appId}/sso/saml/metadata | Preview SAML Metadata
3940
[**Publish-OktaCsrFromApplication**](OktaApplicationApi.md#Publish-OktaCsrFromApplication) | **POST** /api/v1/apps/{appId}/credentials/csrs/{csrId}/lifecycle/publish | Publish a Certificate Signing Request
4041
[**Revoke-OktaCsrFromApplication**](OktaApplicationApi.md#Revoke-OktaCsrFromApplication) | **DELETE** /api/v1/apps/{appId}/credentials/csrs/{csrId} | Revoke a Certificate Signing Request
4142
[**Revoke-OktaOAuth2TokenForApplication**](OktaApplicationApi.md#Revoke-OktaOAuth2TokenForApplication) | **DELETE** /api/v1/apps/{appId}/tokens/{tokenId} | Revoke an OAuth 2.0 Token
@@ -1783,6 +1784,59 @@ Name | Type | Description | Notes
17831784

17841785
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
17851786

1787+
<a id="Invoke-OktaPreviewSAMLMetadataForApplication"></a>
1788+
# **Invoke-OktaPreviewSAMLMetadataForApplication**
1789+
> String Invoke-OktaPreviewSAMLMetadataForApplication<br>
1790+
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[-AppId] <String><br>
1791+
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[-KeyId] <String><br>
1792+
1793+
Preview SAML Metadata
1794+
1795+
Previews SAML metadata based on a specific key credential for an application
1796+
1797+
### Example
1798+
```powershell
1799+
# general setting of the PowerShell module, e.g. base URL, authentication, etc
1800+
$Configuration = Get-OktaConfiguration
1801+
1802+
# Configure your client ID and scope for authorization
1803+
$Configuration.ClientId = "YOUR_CLIENT_ID"
1804+
$Configuration.Scope = "OKTA_SCOPES" # for example okta.users.read
1805+
1806+
$AppId = "MyAppId" # String | Application ID
1807+
$KeyId = "MyKeyId" # String | Application key credential ID (optional)
1808+
1809+
# Preview SAML Metadata
1810+
try {
1811+
$Result = Invoke-OktaPreviewSAMLMetadataForApplication -AppId $AppId -KeyId $KeyId
1812+
} catch {
1813+
Write-Host ("Exception occurred when calling Invoke-OktaPreviewSAMLMetadataForApplication: {0}" -f ($_.ErrorDetails | ConvertFrom-Json))
1814+
Write-Host ("Response headers: {0}" -f ($_.Exception.Response.Headers | ConvertTo-Json))
1815+
}
1816+
```
1817+
1818+
### Parameters
1819+
1820+
Name | Type | Description | Notes
1821+
------------- | ------------- | ------------- | -------------
1822+
**AppId** | **String**| Application ID |
1823+
**KeyId** | **String**| Application key credential ID | [optional]
1824+
1825+
### Return type
1826+
1827+
**String**
1828+
1829+
### Authorization
1830+
1831+
[apiToken](../README.md#apiToken), [oauth2](../README.md#oauth2)
1832+
1833+
### HTTP request headers
1834+
1835+
- **Content-Type**: Not defined
1836+
- **Accept**: application/xml, application/json
1837+
1838+
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
1839+
17861840
<a id="Publish-OktaCsrFromApplication"></a>
17871841
# **Publish-OktaCsrFromApplication**
17881842
> JsonWebKey Publish-OktaCsrFromApplication<br>

openapi3/README.md

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -43,31 +43,7 @@ For troubleshooting, please run `$DebugPreference = 'Continue'` to turn on debug
4343

4444
## Getting Started
4545

46-
### Regenerating the SDK
47-
48-
To regenerate the SDK from the OpenAPI specification:
49-
50-
1. Install the [OpenAPI generator CLI](https://www.npmjs.com/package/@openapitools/openapi-generator-cli)
51-
2. Navigate to the `openapi3` directory
52-
3. Run the automated generation script:
53-
```powershell
54-
.\generate.ps1
55-
```
56-
57-
This script will:
58-
- Generate code using `openapi-generator-cli` with the configuration in `config.json`
59-
- Automatically fix documentation to include the `Okta` prefix in `Initialize-` functions
46+
- Install the [OpenAPI generator CLI](https://www.npmjs.com/package/@openapitools/openapi-generator-cli)
47+
- Run `openapi-generator-cli generate -g powershell -c config.json --skip-validate-spec`
6048

6149
> Note that `config.json` contains all the configuration required (templates, supporting files, global configuration, etc) to generate the Okta SDK. For more details about the generator's customization visit [this link](https://openapi-generator.tech/docs/customization).
62-
63-
### Manual Generation (Advanced)
64-
65-
If you need to run the steps manually:
66-
67-
```powershell
68-
# Step 1: Generate code
69-
openapi-generator-cli generate -g powershell -c config.json --skip-validate-spec
70-
71-
# Step 2: Fix documentation
72-
.\fix-docs.ps1
73-
```

openapi3/management.yaml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2373,6 +2373,43 @@ paths:
23732373
- okta.apps.manage
23742374
tags:
23752375
- Application
2376+
/api/v1/apps/{appId}/sso/saml/metadata:
2377+
get:
2378+
summary: Preview SAML Metadata
2379+
description: Previews SAML metadata based on a specific key credential for an application
2380+
operationId: previewSAMLMetadataForApplication
2381+
parameters:
2382+
- name: appId
2383+
in: path
2384+
description: Application ID
2385+
required: true
2386+
schema:
2387+
type: string
2388+
- name: keyId
2389+
in: query
2390+
description: Application key credential ID
2391+
required: false
2392+
schema:
2393+
type: string
2394+
responses:
2395+
'200':
2396+
description: Success
2397+
content:
2398+
application/xml:
2399+
schema:
2400+
type: string
2401+
'403':
2402+
$ref: '#/components/responses/ErrorAccessDenied403'
2403+
'404':
2404+
$ref: '#/components/responses/ErrorResourceNotFound404'
2405+
'429':
2406+
$ref: '#/components/responses/ErrorTooManyRequests429'
2407+
security:
2408+
- apiToken: []
2409+
- oauth2:
2410+
- okta.apps.read
2411+
tags:
2412+
- Application
23762413
/api/v1/authenticators:
23772414
get:
23782415
summary: List all Authenticators

src/Okta.PowerShell/Api/OktaApplicationApi.ps1

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4126,6 +4126,141 @@ function Invoke-OktaListScopeConsentGrants {
41264126
<#
41274127
.SYNOPSIS
41284128
4129+
Preview SAML Metadata
4130+
4131+
.DESCRIPTION
4132+
4133+
No description available.
4134+
4135+
.PARAMETER AppId
4136+
Application ID
4137+
4138+
.PARAMETER KeyId
4139+
Application key credential ID
4140+
4141+
.PARAMETER ReturnType
4142+
4143+
Select the return type (optional): application/xml, application/json
4144+
4145+
4146+
.PARAMETER Uri
4147+
4148+
Specifies the absolute Uri to be used when making the request. Recommended for paginated results. Optional.
4149+
4150+
.PARAMETER WithHttpInfo
4151+
4152+
A switch when turned on will return a hash table of Response, StatusCode and Headers instead of just the Response
4153+
4154+
.PARAMETER IncludeNullValues
4155+
4156+
A switch when turned on will include any null values in the payload; Null values are removed by default. Optional.
4157+
4158+
.OUTPUTS
4159+
4160+
String
4161+
#>
4162+
function Invoke-OktaPreviewSAMLMetadataForApplication {
4163+
[CmdletBinding()]
4164+
Param (
4165+
[Parameter(Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Mandatory = $false)]
4166+
[String]
4167+
${AppId},
4168+
[Parameter(Position = 1, ValueFromPipelineByPropertyName = $true, Mandatory = $false)]
4169+
[String]
4170+
${KeyId},
4171+
[String]
4172+
[ValidateSet("application/xml", "application/json")]
4173+
$ReturnType,
4174+
[Parameter(ValueFromPipelineByPropertyName = $true, Mandatory = $false)]
4175+
[String]
4176+
${Uri},
4177+
[Switch]
4178+
$WithHttpInfo,
4179+
[Switch]
4180+
$IncludeNullValues
4181+
)
4182+
4183+
Process {
4184+
'Calling method: Invoke-OktaPreviewSAMLMetadataForApplication' | Write-Debug
4185+
$PSBoundParameters | Out-DebugParameter | Write-Debug
4186+
4187+
$LocalVarAccepts = @()
4188+
$LocalVarContentTypes = @()
4189+
$LocalVarQueryParameters = @{}
4190+
$LocalVarHeaderParameters = @{}
4191+
$LocalVarFormParameters = @{}
4192+
$LocalVarPathParameters = @{}
4193+
$LocalVarCookieParameters = @{}
4194+
$LocalVarBodyParameter = $null
4195+
4196+
$Configuration = Get-OktaConfiguration
4197+
# HTTP header 'Accept' (if needed)
4198+
$LocalVarAccepts = @('application/xml', 'application/json')
4199+
4200+
if ($ReturnType) {
4201+
# use the return type (MIME) provided by the user
4202+
$LocalVarAccepts = @($ReturnType)
4203+
}
4204+
4205+
$LocalVarUri = '/api/v1/apps/{appId}/sso/saml/metadata'
4206+
if (!$PSCmdlet.MyInvocation.BoundParameters.ContainsKey("AppId") -or $null -eq $AppId) {
4207+
throw "Error! The required parameter `AppId` missing when calling previewSAMLMetadataForApplication."
4208+
}
4209+
$LocalVarUri = $LocalVarUri.replace('{appId}', [System.Web.HTTPUtility]::UrlEncode($AppId))
4210+
4211+
if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey("Uri")) {
4212+
$ParsedUri = Invoke-ParseAbsoluteUri -Uri $Uri
4213+
$LocalVarUri = $ParsedUri["RelativeUri"]
4214+
$LocalVarQueryParameters = $ParsedUri["QueryParameters"]
4215+
}
4216+
4217+
if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey("KeyId")) {
4218+
$LocalVarQueryParameters['keyId'] = $KeyId
4219+
}
4220+
4221+
if ($Configuration["ApiKey"] -and $Configuration["ApiKey"]["apiToken"]) {
4222+
$LocalVarHeaderParameters['apiToken'] = $Configuration["ApiKey"]["apiToken"]
4223+
Write-Verbose ("Using API key 'apiToken' in the header for authentication in {0}" -f $MyInvocation.MyCommand)
4224+
}
4225+
4226+
4227+
if ($Configuration["AccessToken"]) {
4228+
$LocalVarHeaderParameters['Authorization'] = "Bearer " + $Configuration["AccessToken"]
4229+
Write-Verbose ("Using Bearer authentication in {0}" -f $MyInvocation.MyCommand)
4230+
}
4231+
4232+
$LocalVarResult = Invoke-OktaApiClient -Method 'GET' `
4233+
-Uri $LocalVarUri `
4234+
-Accepts $LocalVarAccepts `
4235+
-ContentTypes $LocalVarContentTypes `
4236+
-Body $LocalVarBodyParameter `
4237+
-HeaderParameters $LocalVarHeaderParameters `
4238+
-QueryParameters $LocalVarQueryParameters `
4239+
-FormParameters $LocalVarFormParameters `
4240+
-CookieParameters $LocalVarCookieParameters `
4241+
-ReturnType "String" `
4242+
-IsBodyNullable $false
4243+
4244+
if ($WithHttpInfo.IsPresent) {
4245+
if ($null -ne $LocalVarResult.Headers.Link) {
4246+
foreach($Link in $LocalVarResult.Headers.Link) {
4247+
# Link looks like '<https://myorg.okta.com/api/v1/groups?after=00g9erhe4rJGXhdYs5d7&limit=1>;rel="next"
4248+
if ($Link.Contains('rel="next"', 'InvariantCultureIgnoreCase')) {
4249+
$LinkValue = $Link.split(";")[0].ToString()
4250+
$LocalVarResult.NextPageUri = $LinkValue -replace '[<>]',''
4251+
}
4252+
}
4253+
}
4254+
return $LocalVarResult
4255+
} else {
4256+
return $LocalVarResult["Response"]
4257+
}
4258+
}
4259+
}
4260+
4261+
<#
4262+
.SYNOPSIS
4263+
41294264
Publish a Certificate Signing Request
41304265
41314266
.DESCRIPTION

src/Okta.PowerShell/Okta.PowerShell.PrivateFunctions.psd1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#
44
# Generated by: Okta, Inc.
55
#
6-
# Generated on: 11/6/2025
6+
# Generated on: 11/7/2025
77
#
88

99
@{

src/Okta.PowerShell/Okta.PowerShell.psd1

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#
44
# Generated by: Okta, Inc.
55
#
6-
# Generated on: 11/6/2025
6+
# Generated on: 11/7/2025
77
#
88

99
@{
@@ -102,6 +102,7 @@ FunctionsToExport = 'Invoke-OktaActivateAgentPoolsUpdate', 'New-OktaAgentPoolsUp
102102
'Invoke-OktaListFeaturesForApplication',
103103
'Invoke-OktaListOAuth2TokensForApplication',
104104
'Invoke-OktaListScopeConsentGrants',
105+
'Invoke-OktaPreviewSAMLMetadataForApplication',
105106
'Publish-OktaCsrFromApplication', 'Revoke-OktaCsrFromApplication',
106107
'Revoke-OktaOAuth2TokenForApplication',
107108
'Revoke-OktaOAuth2TokensForApplication',

tests/Api/OktaApplicationApi.Tests.ps1

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,4 +369,53 @@ Describe -tag 'Okta.PowerShell' -name 'OktaOktaApplicationApi' {
369369
$TestResult.Status | Should -Be "ACTIVE"
370370
}
371371
}
372+
373+
Context 'Invoke-OktaPreviewSAMLMetadataForApplication' {
374+
It 'Should call the correct endpoint for SAML metadata preview' {
375+
# Arrange
376+
$AppId = "0oa1gjh63g214q0Hq0g4"
377+
$ExpectedXml = '<?xml version="1.0" encoding="UTF-8"?><md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="http://www.okta.com/exk1234567890"><md:IDPSSODescriptor WantAuthnRequestsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"></md:IDPSSODescriptor></md:EntityDescriptor>'
378+
379+
$Response = @{
380+
Response = $ExpectedXml
381+
StatusCode = 200
382+
Headers = @{ "Content-Type" = @("application/xml")}
383+
}
384+
385+
Mock -ModuleName Okta.PowerShell Invoke-OktaApiClient { return $Response } -Verifiable
386+
387+
# Act
388+
$Result = Invoke-OktaPreviewSAMLMetadataForApplication -AppId $AppId
389+
390+
# Assert
391+
Assert-MockCalled -ModuleName Okta.PowerShell Invoke-OktaApiClient -Exactly -Times 1 -Scope It -ParameterFilter {
392+
$Uri -like "*/api/v1/apps/$AppId/sso/saml/metadata" -and
393+
$Method -eq 'GET'
394+
}
395+
$Result | Should -Be $ExpectedXml
396+
}
397+
398+
It 'Should include keyId query parameter when provided' {
399+
# Arrange
400+
$AppId = "0oa1gjh63g214q0Hq0g4"
401+
$KeyId = "SIMcCQNY3uwXoW3y0g3"
402+
403+
$Response = @{
404+
Response = '<?xml version="1.0"?><metadata></metadata>'
405+
StatusCode = 200
406+
Headers = @{ "Content-Type" = @("application/xml")}
407+
}
408+
409+
Mock -ModuleName Okta.PowerShell Invoke-OktaApiClient { return $Response } -Verifiable
410+
411+
# Act
412+
$Result = Invoke-OktaPreviewSAMLMetadataForApplication -AppId $AppId -KeyId $KeyId
413+
414+
# Assert
415+
Assert-MockCalled -ModuleName Okta.PowerShell Invoke-OktaApiClient -Exactly -Times 1 -Scope It -ParameterFilter {
416+
$QueryParameters.ContainsKey('keyId') -and
417+
$QueryParameters['keyId'] -eq $KeyId
418+
}
419+
}
420+
}
372421
}

0 commit comments

Comments
 (0)