Skip to content

Instantly share code, notes, and snippets.

@infamousjoeg
Created January 24, 2023 16:34
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save infamousjoeg/dacb398c4f9944df4baf29a58c87542a to your computer and use it in GitHub Desktop.
Save infamousjoeg/dacb398c4f9944df4baf29a58c87542a to your computer and use it in GitHub Desktop.
Cache MFA for SSH Connections via PSM for SSH Proxy
############
# This PowerShell script was translated using OpenAI's code-davinci-002 model
# against the original Python source code. https://beta.openai.com/playground?model=code-davinci-002
#
# https://github.com/vinceblake/cyberark-mfa-no-gui-example/blob/master/SAML-Get-MFA-Caching-Key.py
############
# SET THESE VARIABLES
$ispss_subdomain = "example"
$username = "user@example.com"
$key_path = "C:\Users\user\Downloads"
$key_format = "PPK" # PEM, PPK or OPENSSH
# MFA MECHANISM OBJECT
class Mechanism {
[string]$name
[string]$id
}
# STEP 1: START AUTH
$password = Read-Host -Prompt "Enter the password for $username" -AsSecureString
$url = "https://$ispss_subdomain.cyberark.cloud/api/idadmin/Security/StartAuthentication"
$payload = @{
"User" = $username
"Version" = "1.0"
} | ConvertTo-Json
$headers = @{
'Content-Type' = 'application/json'
}
$response = Invoke-RestMethod -Method POST -Uri $url -Headers $headers -Body $payload
$json_object = $response | ConvertFrom-Json
# Parse response for important variables
$session_id = $json_object.Result.SessionId
$tenant_id = $json_object.Result.TenantId
$pwd_mechanism_id = $json_object.Result.Challenges[0].Mechanisms[0].MechanismId
$mechanisms = $json_object.Result.Challenges[1].Mechanisms
# Create list of MFA Mechanisms
$options = @()
foreach ($mechanism in $mechanisms) {
$name = $mechanism.Name
$id = $mechanism.MechanismId
$obj = [Mechanism]::new($name,$id)
$options += $obj
}
# Let user choose their MFA modality
$i = 0
foreach ($option in $options) {
$i = $i + 1
Write-Host "$i. $($option.name)"
}
while ($true) {
$choice = Read-Host -Prompt "Please choose an MFA mechanism"
$error = "ERROR: Your response must be an integer between 1 and $($options.Count)."
try {
$choice = [int]$choice
} catch {
Write-Host $error
continue
}
if (0 -lt $choice -and $choice -le $options.Count) {
$choice = $choice - 1
break
}
Write-Host $error
}
$mfa_mechanism_id = $options[$choice].id
# STEP 2: ADVANCE AUTH WITH USERNAME AND PASSWORD
$url = "https://$ispss_subdomain.cyberark.cloud/api/idadmin/Security/AdvanceAuthentication"
$payload = @{
"SessionId" = $session_id
"MechanismId" = $pwd_mechanism_id
"Action" = "Answer"
"Answer" = $password
} | ConvertTo-Json
$headers = @{
'X-IDAP-NATIVE-CLIENT' = 'true'
'Content-Type' = 'application/json'
}
$response = Invoke-RestMethod -Method POST -Uri $url -Headers $headers -Body $payload
# STEP 3: ADVANCE AUTH WITH SELECTED MFA MODALITY
$payload = @{
"SessionId" = $session_id
"MechanismId" = $mfa_mechanism_id
"Action" = "StartOOB"
} | ConvertTo-Json
$headers = @{
'X-IDAP-NATIVE-CLIENT' = 'true'
'Content-Type' = 'application/json'
}
# Give user a chance to respond to their MFA challenge.
Write-Host "Please wait..."
$response = Invoke-RestMethod -Method POST -Uri $url -Headers $headers -Body $payload
Read-Host -Prompt "Press enter once you have completed your MFA challenge."
# STEP 4: POLL FOR TOKEN ONCE MFA CHALLENGE HAS BEEN COMPLETED
$payload = @{
"TenantId" = $tenant_id
"SessionId" = $session_id
"MechanismId" = $mfa_mechanism_id
"Action" = "Poll"
} | ConvertTo-Json
$headers = @{
'X-IDAP-NATIVE-CLIENT' = 'true'
'Content-Type' = 'application/json'
}
$response = Invoke-RestMethod -Method POST -Uri $url -Headers $headers -Body $payload
$json_object = $response | ConvertFrom-Json
$token = $json_object.Result.Token
# STEP 5: GENERATE MFA CACHING KEY HAVING SUCCESSFULLY AUTHENTICATED
$url = "https://$ispss_subdomain.privilegecloud.cyberark.cloud/passwordvault/api/users/secret/sshkeys/cache"
$payload = @{
"formats" = @($key_format)
} | ConvertTo-Json
$headers = @{
'Authorization' = "Bearer $token"
'Content-Type' = 'application/json'
}
$response = Invoke-RestMethod -Method POST -Uri $url -Headers $headers -Body $payload
$json_object = $response | ConvertFrom-Json
try {
$key = $json_object.value[0].privateKey
$file = "$key_path\mfa_caching_key.$key_format"
$key | Out-File -FilePath $file
Write-Host "Key successfully downloaded to $key_path."
} catch {
Write-Host "Sorry, an error occurred. Please check your settings and try again."
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment