Public/Authentication/New-SIASession.ps1

function New-SIASession {
    <#
    .SYNOPSIS
        Authenticates to CyberArk Secure Infrastructure Access and starts a psSIA session.
    .DESCRIPTION
        Requests an OAuth2 client-credentials access token from the Idira Identity
        Security Platform token endpoint and stores it in memory for the rest of
        the session. Every other psSIA cmdlet depends on this having been run
        first.

        Use a dedicated service user assigned the DpaAdmin role rather than a
        personal account - this matches CyberArk's own recommendation for API
        automation.
    .PARAMETER Subdomain
        The SIA tenant subdomain, i.e. the "<subdomain>" in
        https://<subdomain>.dpa.cyberark.cloud.
    .PARAMETER IdentityTenantId
        The Identity tenant ID used to reach the token endpoint, i.e. the
        "<IdentityTenantId>" in https://<IdentityTenantId>.id.cyberark.cloud.
        This is usually, but not always, the same value as -Subdomain.
    .PARAMETER Credential
        A PSCredential where the user name is the service account's OAuth
        client ID and the password is its client secret.
    .EXAMPLE
        $cred = Get-Credential -Message 'SIA service account (client ID / secret)'
        New-SIASession -Subdomain 'contoso' -IdentityTenantId 'contoso' -Credential $cred

        Authenticates using a service account and starts a session against
        contoso's SIA tenant.
    .INPUTS
        None.
    .OUTPUTS
        psSIA.Session
    .NOTES
        The access token is valid for 900 seconds. Run New-SIASession again once
        it expires; psSIA does not silently refresh tokens on your behalf.
    .LINK
        https://api-docs.cyberark.com/create-api-token/docs/create-api-token
    #>

    [CmdletBinding()]
    [OutputType('psSIA.Session')]
    [Diagnostics.CodeAnalysis.SuppressMessage('PSUseShouldProcessForStateChangingFunctions', '',
        Justification = 'Authenticates and stores a local, in-memory session; it does not change any state on the SIA tenant, consistent with Connect-* cmdlet conventions.')]
    [Diagnostics.CodeAnalysis.SuppressMessage('PSAvoidUsingConvertToSecureStringWithPlainText', '',
        Justification = 'The access token arrives as plaintext in the platformtoken response body; wrapping it in a SecureString here is how it is protected for the rest of the session, not a hard-coded secret.')]
    param(
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$Subdomain,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$IdentityTenantId,

        [Parameter(Mandatory)]
        [PSCredential]$Credential
    )

    $tokenUri = [uri]"https://$IdentityTenantId.id.cyberark.cloud/oauth2/platformtoken"
    $clientSecret = [System.Net.NetworkCredential]::new('', $Credential.Password).Password

    $body = ConvertTo-SIARequestBody -AsForm -InputObject @{
        grant_type    = 'client_credentials'
        client_id     = $Credential.UserName
        client_secret = $clientSecret
    }

    Write-Verbose (Protect-SIALogValue "POST $tokenUri")

    try {
        $response = Invoke-RestMethod -Method Post -Uri $tokenUri -Body $body `
            -ContentType 'application/x-www-form-urlencoded' `
            -Headers @{ 'User-Agent' = "psSIA/$($script:ModuleVersion)" } `
            -ErrorAction Stop
    } catch {
        throw (Resolve-SIAError -ErrorRecord $_ -Operation 'New-SIASession' -Uri $tokenUri)
    }

    $script:SIASession = [pscustomobject]@{
        PSTypeName       = 'psSIA.Session'
        Subdomain        = $Subdomain
        IdentityTenantId = $IdentityTenantId
        ClientId         = $Credential.UserName
        AccessToken      = (ConvertTo-SecureString -String $response.access_token -AsPlainText -Force)
        TokenType        = $response.token_type
        CreatedAt        = (Get-Date).ToUniversalTime()
        ExpiresAt        = (Get-Date).ToUniversalTime().AddSeconds([int]$response.expires_in)
    }

    Get-SIASession
}