Get-PC/Private/Connect-ISM.ps1

207 lines
8.3 KiB
PowerShell

Function Connect-ISM {
<#
.SYNOPSIS
Primary authentication function leveraged by the module to connect to the Ivanti Service Manager API.
.DESCRIPTION
rimary authentication function leveraged by the module to connect to the Ivanti Service Manager API. Supports use of an API Key or SessionID authentication.
PRD = Production
STG = Staging
UAT = User Acceptance Testing
.PARAMETER -Environment
The ISM Environment you wish to connect to. This is a validate set containing "PRD", "UAT", "STG" environments.
.PARAMETER -TenantPrefix
The ISM URL prefix for the Tenant.
.PARAMETER -AuthType
Parameter that defines what type of authentication to use. APIKey requires procuring an API Key from the ITSM Admins and is primarily relegated for use by administrators and unattended scripts.
SessionID will prompt the user for Spark credentials and attempt to authenticate them directly. The default Role in the module is set for "ISAnalyst" but can be adjusted in the function.
.PARAMETER -ConnectionTest
Switch that when included will Invoke a WebRequest against the URL of the environment chosen. StatusDescription = OK will be returned on success.
.PARAMETER -AuthTypeCheck
Hidden parameter primarily intended for use internally by the module. This simply returns the value of AuthType and doesn't output any headers or make any API calls at all.
.INPUTS
A valid string.
.OUTPUTS
Returns the Tenant URI and the authorization headers necessary to make REST API calls to Ivanti Service Manager.
.NOTES
Version: 1.2
Author: Sean Carlton
Creation Date: 04/26/2023
Purpose/Change: Added AA_API_Key variable and check to leverage Get-AutomationPSCredential when $PSPrivateMetaData is not null. This variable is populated when a script is executing from Azure Automation (Cloud and Hybrid Worker), but otherwise is null.
Version: 1.1
Author: Sean Carlton
Creation Date: 10/06/2022
Purpose/Change: Added initial SessionID support. To leverage this option requires a local login in Spark which most users do not have. A request has been submitted with Ivanti to determine if we can leverage OIDC auth instead. If so, the code will be in place to allow use of ISMTools without an API Key, using your own credentials for authentication to the API. Added the hidden -ConfigCheck switch which will return the Connect-ISM configuration currently in use.
Version: 1.0
Author: Sean Carlton
Creation Date: 08/16/2022
Purpose/Change: Initial script development
.EXAMPLE
The below example demonstrates how to define the ISM/Spark environment you wish to connect to upon initial import. If the -ArgumentList parameter is not provided when Import-Module is ran, then the $Environment variable configured in Connect-ISM will be used to determine which environment to connect to.
Import-Module 'ISMTools' -ArgumentList 'PRD'
.EXAMPLE
(Connect-ISM)[0] will return the authorization headers.
(Connect-ISM)[1] will return the Tenant URL.
(Connect-ISM)[2] will return the Authentication Type.
.EXAMPLE
The -ConnectionTest switch will invoke a WebRequest against the Tenant URL the function is configured to connect to. It can be leveraged to check that your connection to ISM/Spark is valid. It returns all of the other properties but includes the StatusDescription of the Invoke-WebRequest call as well.
Connect-ISM -ConnectionTest
If Statement example to confirm you're connected to Spark before continuing:
if ((Connect-ISM -ConnectionTest)[-1].StatusDescription -eq "OK"){
Write-Host "Connected to Spark!"
} else {
Write-Warning "Failed to connect to Spark!"
Exit
}
.EXAMPLE
The -ConfigCheck switch will return the current configuration of the module for reference.
Connect-ISM -ConfigCheck
#>
[CmdletBinding()]
param (
[Parameter()]
[ValidateSet("STG", "UAT", "PRD")]
$Environment = $(if ($Module_Environment){
$Module_Environment
}else{
## Define the Default Environment here. This will be used when no environment is passed by Import-Module
"PRD"
}),
[Parameter()]
[ValidateSet("APIKey", "SessionID")]
[string]$AuthType = "APIKey",
[Parameter()]
## ServiceDeskAnalyst
## ISAnalyst
## Admin
## DesktopTechnician
[string]$Role = "ISAnalyst",
[Parameter()]
[string]$TenantPrefix = "samaritanhealth-amc",
[Parameter()]
[switch]$ConnectionTest,
[Parameter(DontShow)]
[switch]$ConfigCheck
)
BEGIN {
##Initialize the Headers Hashtable.
$Headers = @{
"Content-Type" = "application/json"
"Authorization" = $null
"Accept" = "*/*"
"Accept-Encoding" = "gzip, deflate, br"
}
## If $PSPrivateMetaData is NOT null then this is running from an Azure Runbook/via Hybrid Worker. We'll attempt to pull the API key from the Credential Store of the automation account directly in that scenario.
$Azure_Execution = ($null -ne $PSPrivateMetadata)
if ($Azure_Execution){
$Cred_Obj = Get-AutomationPSCredential -Name "ISM $Environment API Key"
if ($Cred_Obj){
$AA_API_Key = (New-Object PSCredential $Cred_Obj.Username,$Cred_Obj.Password).GetNetworkCredential().Password;
}
}
## Initialize the URL and API_Key based on $Environment selection.
## If you don't have acess to the API Key for the environment you need, please reach out to the ITSM Team to request access.
Switch ($Environment){
"STG" {
$API_Key = if($AA_API_Key){$AA_API_Key}else{''};
$URL = "https://$TenantPrefix-$Environment.ivanticloud.com"
}
"UAT" {
$API_Key = if($AA_API_Key){$AA_API_Key}else{''};
$URL = "https://$TenantPrefix-$Environment.ivanticloud.com"
}
"PRD" {
$API_Key = if($AA_API_Key){$AA_API_Key}else{'EB68123D62F8489295C807353C92D75B'};
$URL = "https://$TenantPrefix.ivanticloud.com"
}
}#END $ENVIRONMENT SWITCH
}#END BEGIN BLOCK
PROCESS {
Switch ($AuthType){
"APIKey" {
## Add the API_Key to the Headers
$Headers["Authorization"] = "rest_api_key=$API_Key"
}
"SessionID" {
## Prompt for Network Credentials if we don't have a valid SessionID/Token already stored.
if (!$ISMToolsModuleSessionID.SessionID){
$SessionIDCreds = Get-Credential -User $ENV:Username -Message "Enter your network password to authenticate into Spark with the $Role role."
$Body = @{
"Tenant" = $URL.Split('/')[-1]
"Username" = $SessionIDCreds.Username
"Password" = $SessionIDCreds.GetNetworkCredential().Password
"Role" = $Role
}
$JSONBody = $Body | ConvertTo-Json
if ($SessionIDCreds.GetNetworkCredential().Password){
try {
$URI = "$URL/api/rest/authentication/login"
$SessionID = Invoke-RestMethod -uri $URI -Method Post -Body $JSONBody -headers $Headers
}
catch {$_.Exception.Message}
}
if ($SessionID -match "#"){
$ISMToolsModuleSessionID.SessionID = $SessionID
} else {
Write-Host "Failed to authenticate with role $($Body.Role) with the provided credentials! Please check the credentials and role configured in the Connect-ISM function and try again." -ForegroundColor yellow
}
$SessionIDCreds = $null
}#End If No ISM_Tools_Module_Session_ID_Token
## Add the SessionID to the Headers
$Headers["Authorization"] = $ISMToolsModuleSessionID.SessionID
}
}#END AUTHTYPE SWITCH
## Run the ConnectionTest if -ConnectionTest was passed.
if ($ConnectionTest){
$TestConnection = Invoke-WebRequest $URL -UseBasicParsing | Select-Object StatusDescription
}
}#END PROCESS BLOCK
END {
if ($ConfigCheck){
return $Environment, $AuthType, $Role, $TenantPrefix, $URL, $API_Key
} else {
return $Headers, $URL, $AuthType, $TestConnection
}
}#END END-BLOCK
}#End Connect-ISM Function