-
Notifications
You must be signed in to change notification settings - Fork 0
Feat/Management API #18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
d22ff2b
Implement Revoke-SCEPmanCertificate
cheinzler-gk cbc2c0e
Improve error handling by parsing internal error codes
cheinzler-gk b9e6f6e
Implement Find-SCEPmanCertificate
cheinzler-gk 23b6977
Add tests
cheinzler-gk d4593ac
Add manage API to readme
cheinzler-gk ea9dcbf
Remove unnecessary output
cheinzler-gk 59353db
Remove unnecessary output
cheinzler-gk 2a51239
Don't force import in tests
cheinzler-gk a4b6f05
Merge branch 'feat/RevocationAPI' of https://github.com/scepman/scepm…
cheinzler-gk 81ed063
fix: null-check HTTP response in find certificate error handling
Copilot 760244e
Remove tertiary operator for PS5 compatability
cheinzler-gk 85605c0
Add simpler error handling for PS5
cheinzler-gk 1289b9a
Merge branch 'feat/RevocationAPI' of https://github.com/scepman/scepm…
cheinzler-gk 1f45dff
Remove possible return value from result
cheinzler-gk c93a1ba
Process Url and header in Begin scope
cheinzler-gk f96ecbd
Remove initial error logging
cheinzler-gk 6915b9a
Remove default parameter values from query
cheinzler-gk 5eb1982
Context is already used by SCEPman. No need to duplicate it.
cheinzler-gk 80efc0f
Prepare for direct token auth for SCEPman SaaS
cheinzler-gk f487f92
Simplify error handling
cheinzler-gk 730d5b2
Remove obsolete test
cheinzler-gk b461242
Adjust synopsis
cheinzler-gk File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,198 @@ | ||
| <# | ||
| .SYNOPSIS | ||
| Search certificates issued by SCEPman. | ||
|
|
||
| .DESCRIPTION | ||
| This function searches certificates via the SCEPman management search API. | ||
|
|
||
| .PARAMETER Url | ||
| The URL of the SCEPman App Service. | ||
|
|
||
| .PARAMETER SearchText | ||
| Search text used by the SCEPman API (for example an email, subject, or serial fragment). | ||
|
|
||
| .PARAMETER PageSize | ||
| Number of results to return per request. | ||
|
|
||
| .PARAMETER CertValidity | ||
| Certificate validity filter value expected by your SCEPman API (for example 'Any' or a numeric enum value). | ||
|
|
||
| .PARAMETER CertType | ||
| Certificate type filter value expected by your SCEPman API (for example 'Any' or a numeric enum value). | ||
|
|
||
| .PARAMETER ContinuationToken | ||
| Continuation token from a previous search response. | ||
|
|
||
| .PARAMETER ResourceUrl | ||
| The resource URL of the SCEPman service. If not provided, the function will try to find the Enterprise Application for the URL. | ||
|
|
||
| .PARAMETER IgnoreExistingSession | ||
| Ignore existing Azure session. | ||
|
|
||
| .PARAMETER DeviceCode | ||
| Use device code authentication. | ||
|
|
||
| .PARAMETER Identity | ||
| Use the managed identity for authentication. | ||
|
|
||
| .PARAMETER ClientId | ||
| The client ID for service principal authentication. | ||
|
|
||
| .PARAMETER TenantId | ||
| The tenant ID for service principal authentication. | ||
|
|
||
| .PARAMETER ClientSecret | ||
| The client secret for service principal authentication. | ||
|
|
||
| .PARAMETER AccessToken | ||
| An access token for authentication. If not provided, the function will authenticate using Azure PowerShell | ||
|
|
||
| .EXAMPLE | ||
| Find-SCEPmanCertificate -Url "https://scepman.contoso.com" -SearchText "alice@contoso.com" -PageSize 50 -CertValidity Any -CertType Any | ||
|
|
||
| .EXAMPLE | ||
| Find-SCEPmanCertificate -Url "https://scepman.contoso.com" -SearchText "alice" -ContinuationToken "next-page-token" | ||
| #> | ||
|
|
||
| Function Find-SCEPmanCertificate { | ||
| [CmdletBinding(DefaultParameterSetName='AzAuth')] | ||
| [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingUsernameAndPasswordParams", "", Justification="Service principal authentication requires username and password.")] | ||
| Param( | ||
| [Parameter(Mandatory, Position=0)] | ||
| [Alias('AppServiceUrl')] | ||
| [String]$Url, | ||
|
|
||
| [String]$SearchText, | ||
|
|
||
| [ValidateRange(1, 500)] | ||
| [Int]$PageSize = 50, | ||
|
|
||
| [CertValidityType]$CertValidity, | ||
|
|
||
| [CertType]$CertType, | ||
|
|
||
| [String]$ContinuationToken, | ||
|
|
||
| [Parameter(ParameterSetName='AzAuth')] | ||
| [String]$ResourceUrl, | ||
|
|
||
| [Parameter(ParameterSetName='AzAuth')] | ||
| [Switch]$IgnoreExistingSession, | ||
| [Parameter(ParameterSetName='AzAuth')] | ||
| [Switch]$DeviceCode, | ||
| [Parameter(ParameterSetName='AzAuth')] | ||
| [Switch]$Identity, | ||
| [Parameter(ParameterSetName='AzAuth')] | ||
| [String]$ClientId, | ||
| [Parameter(ParameterSetName='AzAuth')] | ||
| [String]$TenantId, | ||
| [Parameter(ParameterSetName='AzAuth')] | ||
| [String]$ClientSecret, | ||
|
|
||
| [Parameter(ParameterSetName='DirectTokenAuth')] | ||
| [String]$AccessToken | ||
| ) | ||
|
|
||
| Begin { | ||
| $ErrorActionPreference = 'Stop' | ||
|
|
||
| If($PSCmdlet.ParameterSetName -eq 'DirectTokenAuth') { | ||
| Write-Verbose "$($MyInvocation.MyCommand): Using direct token authentication" | ||
|
|
||
| If (-not $AccessToken) { | ||
| throw "$($MyInvocation.MyCommand): AccessToken is required for direct token authentication" | ||
| } | ||
| } Else { | ||
| Set-AzConfig -Scope Process -LoginExperienceV2 Off -DisplaySurveyMessage $false | Out-Null | ||
|
|
||
| $Connect_Params = @{} | ||
|
|
||
| If ($PSBoundParameters.ContainsKey('IgnoreExistingSession')) { $Connect_Params['IgnoreExistingSession'] = $true } | ||
| If ($PSBoundParameters.ContainsKey('DeviceCode')) { $Connect_Params['DeviceCode'] = $true } | ||
| If ($PSBoundParameters.ContainsKey('Identity')) { $Connect_Params['Identity'] = $true } | ||
| If ($PSBoundParameters.ContainsKey('ClientId')) { $Connect_Params['ClientId'] = $ClientId } | ||
| If ($PSBoundParameters.ContainsKey('TenantId')) { $Connect_Params['TenantId'] = $TenantId } | ||
| If ($PSBoundParameters.ContainsKey('ClientSecret')) { $Connect_Params['ClientSecret'] = $ClientSecret } | ||
|
|
||
| Connect-SCEPmanAzAccount @Connect_Params | ||
|
|
||
| If (-not $PSBoundParameters.ContainsKey('ResourceUrl')) { | ||
| Write-Verbose "$($MyInvocation.MyCommand): No resource URL provided. Trying to find Enterprise Application for URL: $Url" | ||
| $ResourceUrl = Get-SCEPmanResourceUrl -AppServiceUrl $Url | ||
| } | ||
|
|
||
| $AccessToken = Get-SCEPmanAccessToken -ResourceUrl $ResourceUrl | ||
| } | ||
| } | ||
|
|
||
| Process { | ||
| $BaseUrl = $Url.TrimEnd('/') | ||
|
|
||
| $Headers = @{ | ||
| 'Authorization' = "Bearer $AccessToken" | ||
| } | ||
|
|
||
| $Query = [ordered]@{ | ||
| SearchText = $SearchText | ||
| PageSize = $PageSize | ||
| CertValidity = $CertValidity | ||
| CertType = $CertType | ||
| ContinuationToken = $ContinuationToken | ||
| } | ||
|
|
||
| $QueryString = ($Query.GetEnumerator() | | ||
| Where-Object { -not [string]::IsNullOrWhiteSpace([string]$_.Value) } | | ||
| ForEach-Object { | ||
| '{0}={1}' -f [uri]::EscapeDataString($_.Key), [uri]::EscapeDataString([string]$_.Value) | ||
| }) -join '&' | ||
|
cheinzler-gk marked this conversation as resolved.
|
||
|
|
||
| $RequestUrl = "$BaseUrl/api/manage/search" | ||
| If (-not [string]::IsNullOrWhiteSpace($QueryString)) { | ||
| $RequestUrl = "{0}?{1}" -f $RequestUrl, $QueryString | ||
| } | ||
|
|
||
| Write-Verbose "$($MyInvocation.MyCommand): Sending search request to $RequestUrl" | ||
|
|
||
| try { | ||
| $Response = Invoke-RestMethod -Uri $RequestUrl -Method Get -Headers $Headers | ||
| Write-Verbose "$($MyInvocation.MyCommand): Search request successful. Found $($Response.items.count) certificate$(if($Response.items.count -ne 1) { 's' })" | ||
|
|
||
| Return $Response | ||
|
|
||
| } catch { | ||
| $StatusCode = if ($_.Exception.Response) { [int]$_.Exception.Response.StatusCode } else { $null } | ||
| $RawErrorBody = $_.ErrorDetails.Message | ||
|
|
||
|
cheinzler-gk marked this conversation as resolved.
|
||
| $ApiErrorCode = $null | ||
| $ApiErrorMessage = $null | ||
|
|
||
| if ($RawErrorBody) { | ||
| try { | ||
| $ParsedError = $RawErrorBody | ConvertFrom-Json | ||
| $ApiErrorCode = $ParsedError.ErrorCode | ||
| $ApiErrorMessage = $ParsedError.ErrorMessage | ||
| } | ||
| catch { | ||
| $ApiErrorMessage = $RawErrorBody | ||
| } | ||
| } | ||
|
|
||
| Write-Verbose "$($MyInvocation.MyCommand): Failed to search certificates. Status code: $StatusCode. ApiErrorCode: $ApiErrorCode. ApiErrorMessage: $ApiErrorMessage" | ||
|
|
||
| switch ($ApiErrorCode) { | ||
| 4711 { throw "$($MyInvocation.MyCommand): SCEPman Enterprise is required for the manage search API." } | ||
| default { | ||
| switch ($StatusCode) { | ||
| 400 { throw "$($MyInvocation.MyCommand): Bad request. Check the request parameters for errors. $ApiErrorMessage" } | ||
| 401 { throw "$($MyInvocation.MyCommand): Unauthorized. Authentication failed." } | ||
| 403 { throw "$($MyInvocation.MyCommand): Forbidden. Access denied or license revoked." } | ||
| 404 { throw "$($MyInvocation.MyCommand): Endpoint not found. Verify the URL and that the manage API endpoint exists." } | ||
| 409 { throw "$($MyInvocation.MyCommand): Conflict. $(if ($ApiErrorMessage) { $ApiErrorMessage } else { 'Request could not be completed.' })" } | ||
| 500 { throw "$($MyInvocation.MyCommand): Server error while searching certificates. $ApiErrorMessage" } | ||
| default { throw $_ } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.