CyberArk PSM can be used to log in web site using Chrome or IE. I was working on this kind of requirements a lot recently. It usually needs some work to figure out login form’s Username, Password, Click or Button’s ID then create a new connection component for it.  CyberArk MarketPlace has a Office 365 connection component which can reduce lots of this kind of effort.

This post is to record the process I took to get Office 365 log in through PSM working.

Install and Configure Chrome for PSM

Download Office 365 Connection Component from MarketPlace

It can be searched and downloaded from CyberArk MarketPlace. Please make sure read following two documentations:

1KB zip file with a xml file inside. XML file content:

<?xml version="1.0"?>
-<ConnectionComponent DisplayName="Office 365" Type="CyberArk.PasswordVault.TransparentConnection.PSM.PSMConnectionComponent, CyberArk.PasswordVault.TransparentConnection.PSM" Id="PSM-Office-365">
<ComponentParameters/>
-<UserParameters>
<Parameter Type="CyberArk.TransparentConnection.BooleanUserParameter, CyberArk.PasswordVault.TransparentConnection" EnforceInDualControlRequest="No" Required="Yes" Visible="No" Value="No" Name="AllowMappingLocalDrives"/>
</UserParameters>

-<TargetSettings ClientInvokeType="WebForm" ClientDispatcher=""{PSMComponentsFolder}CyberArk.PSM.WebAppDispatcher.exe" "{PSMComponentsFolder}"" ClientApp="Chrome" Protocol="HTTP">
-<ClientSpecific>
<Parameter Value="10" Name="ActionTimeout"/>
<Parameter Value="30" Name="PageLoadTimeout"/>
<Parameter Value="No" Name="RunValidations"/>
</ClientSpecific>

<LockAppWindow SearchWindowWaitTimeout="30" Timeout="2000" MainWindowClass="Chrome_WidgetWin_1" Enable="Yes"/>
<WebFormSettings EnforceCertificateValidation="Yes" WebFormFields="i0116>{Username}(searchby=id) idSIButton9>(Button)(searchby=id) i0118>{Password}(searchby=id) idSIButton9>(Button)(searchby=id) idBtn_Back>(Button) meInitialsButton>(Validation) notificationBellControl_container>(Validation) " SubmitButton="" FormName="login" LogonURL="https://login.microsoftonline.com/"/>
-<Capabilities>
<Capability Id="KeystrokesAudit"/>
<Capability Id="KeystrokesTextRecorder"/>
</Capabilities>

</TargetSettings>
</ConnectionComponent>

Download Importing Script from CyberArk Github


GitHub repository: https://github.com/cyberark/epv-api-scripts/tree/master/Platforms
Download script : Import-ConnectionComponents.ps1

Copy the script to notepad and save it as a ps1 script file.

###########################################################################
#
# NAME: Import Connection Components
#
# AUTHOR:  Assaf Miron
#
# COMMENT: 
# This script will Import a single or multiple connection components using REST API
#
# SUPPORTED VERSIONS:
# CyberArk PVWA v10.4 and above
#
#
###########################################################################

param
(
 [Parameter(Mandatory=$true,HelpMessage="Please enter your PVWA address (For example: https://pvwa.mydomain.com/PasswordVault)")]
 #[ValidateScript({Invoke-WebRequest -UseBasicParsing -DisableKeepAlive -Uri $_ -Method 'Head' -ErrorAction 'stop' -TimeoutSec 30})]
 [Alias("url")]
 [String]$PVWAURL,
 
 # Use this switch to Disable SSL verification (NOT RECOMMENDED)
 [Parameter(Mandatory=$false)]
 [Switch]$DisableSSLVerify,
 
 [Parameter(Mandatory=$false,HelpMessage="Enter the Connection Component Zip path to import")]
 [Alias("ConnectionComponent")]
 [string]$ConnectionComponentZipPath,
 
 [Parameter(Mandatory=$false,HelpMessage="Enter a folder path for Connection Components Zip files to import")]
 [Alias("Folder")]
 [string]$ConnectionComponentFolderPath
)

# Global URLS
# -----------
$URL_PVWAAPI = $PVWAURL+"/api"
$URL_Authentication = $URL_PVWAAPI+"/auth"
$URL_CyberArkLogon = $URL_Authentication+"/cyberark/Logon"
$URL_CyberArkLogoff = $URL_Authentication+"/Logoff"

# URL Methods
# -----------
$URL_ImportConnectionComponent = $URL_PVWAAPI+"/ConnectionComponents/Import"

# Initialize Script Variables
# ---------------------------
$rstusername = $rstpassword = ""
$logonToken  = ""

Function Disable-SSLVerification
{
<# 
.SYNOPSIS 
 Bypass SSL certificate validations
.DESCRIPTION
 Disables the SSL Verification (bypass self signed SSL certificates)
#>
 # Using Proxy Default credentials if the Server needs Proxy credentials
 [System.Net.WebRequest]::DefaultWebProxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials
 # Using TLS 1.2 as security protocol verification
 [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
 # Disable SSL Verification
 if (-not("DisableCertValidationCallback" -as [type])) {
    add-type -TypeDefinition @"
using System;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

public static class DisableCertValidationCallback {
    public static bool ReturnTrue(object sender,
        X509Certificate certificate,
        X509Chain chain,
        SslPolicyErrors sslPolicyErrors) { return true; }

    public static RemoteCertificateValidationCallback GetDelegate() {
        return new RemoteCertificateValidationCallback(DisableCertValidationCallback.ReturnTrue);
    }
}
"@ }

 [System.Net.ServicePointManager]::ServerCertificateValidationCallback = [DisableCertValidationCallback]::GetDelegate()
}

Function Get-ZipContent
{
 Param($zipPath)
 
 $zipContent = $null
 try{
  If(Test-Path $zipPath)
  {
   $zipContent = [System.IO.File]::ReadAllBytes($(Resolve-Path $zipPath))
  }
 } catch {
  throw "Error while reading ZIP file: $($_.Exception.Message)"
 }
 
 return $zipContent
}

If ($($PSVersionTable.PSVersion.Major) -lt 3)
{
 Write-Error "This script requires PowerShell version 3 or above"
 return
}

# Check that the PVWA URL is OK
If ($PVWAURL -ne "")
{
 If ($PVWAURL.Substring($PVWAURL.Length-1) -eq "/")
 {
  $PVWAURL = $PVWAURL.Substring(0,$PVWAURL.Length-1)
 }
}
else
{
 Write-Host -ForegroundColor Red "PVWA URL can not be empty"
 return
}

Write-Host "Import Connection Component: Script Started" -ForegroundColor Cyan
# Disable SSL Verification to contact PVWA
If($DisableSSLVerify)
{
 Disable-SSLVerification
}

#region [Logon]
# Get Credentials to Login
# ------------------------
$caption = "Import Connection Component"
$msg = "Enter your User name and Password"; 
$creds = $Host.UI.PromptForCredential($caption,$msg,"","")
if ($creds -ne $null)
{
 $rstusername = $creds.username.Replace('\','');    
 $rstpassword = $creds.GetNetworkCredential().password
}
else { return }

# Create the POST Body for the Logon
# ----------------------------------
$logonBody = @{ username=$rstusername;password=$rstpassword }
$logonBody = $logonBody | ConvertTo-Json
try{
 # Logon
 $logonToken = Invoke-RestMethod -Method Post -Uri $URL_CyberArkLogon -Body $logonBody -ContentType "application/json"
}
catch
{
 Write-Host -ForegroundColor Red $_.Exception.Response.StatusDescription
 $logonToken = ""
}
If ($logonToken -eq "")
{
 Write-Host -ForegroundColor Red "Logon Token is Empty - Cannot login"
 return
}
# Create a Logon Token Header (This will be used through out all the script)
# ---------------------------
$logonHeader =  New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$logonHeader.Add("Authorization", $logonToken)
#endregion

$arrConCompToImport = @()

If (([string]::IsNullOrEmpty($ConnectionComponentZipPath)) -and (![string]::IsNullOrEmpty($ConnectionComponentFolderPath)))
{
 # Get all Connection Components from a folder
 $arrConCompToImport += (Get-ChildItem -Path $ConnectionComponentFolderPath -Filter "*.zip")
}
ElseIf ((![string]::IsNullOrEmpty($ConnectionComponentZipPath)) -and ([string]::IsNullOrEmpty($ConnectionComponentFolderPath)))
{
 # Get the entered Connection Component ZIP
 $arrConCompToImport = $ConnectionComponentZipPath
}
Else
{
 Write-Host -ForegroundColor Red "No Connection Component path was entered."
 $arrConCompToImport = Read-Host "Please enter a Connection Component ZIP path"
}

ForEach($connCompItem in $arrConCompToImport)
{
 If (Test-Path $connCompItem)
 {
  $importBody = @{ ImportFile=$(Get-ZipContent $connCompItem); } | ConvertTo-Json -Depth 3 -Compress
  try{
   $ImportCCResponse = Invoke-RestMethod -Method POST -Uri $URL_ImportConnectionComponent -Headers $logonHeader -ContentType "application/json" -TimeoutSec 3600000 -Body $importBody
   $connectionComponentID = ($ImportCCResponse.ConnectionComponentID)
   Write-Host "Connection Component ID imported: $connectionComponentID"
  } catch {
   if($_.Exception.Response.StatusDescription -like "*Conflict*")
   {
    Write-Host "The requested connection component already exists" -ForegroundColor Yellow
   }
   Else{
    Write-Error "Error importing the connection ID, Error: $($_.Exception.Response.StatusDescription)"
   }
  }
 }
}

# Logoff the session
# ------------------
if($null -ne $logonHeader)
{
 Write-Host "Logoff Session..."
 Invoke-RestMethod -Method Post -Uri $URL_CyberArkLogoff -Headers $logonHeader -ContentType "application/json" | Out-Null
}

Write-Host "Import Connection Component: Script Ended" -ForegroundColor Cyan

Importing O365 Connection Component into CyberArk

Put Import-ConnectionComponents.ps1 and “Office-365 1.1.zip” into one fold (E.g. c:\Temp) and run following command:

Import-ConnectionComponents.ps1 -PVWAURL https://pvwacpm1.51sectest.dev/PasswordVault -ConnectionComponentZipPath "C:\Temp\Office-365 1.1.zip"

If there is error message relating token, deny access, etc, you can replace url with ip address, such as : https://192.168.2.23/PasswordVault

Another common error is “Logon Tokern is Empty – Cannot Login”. Usually it caused by selfsigned certificate. We can use a switch to bypass this certificate verification.

Import-ConnectionComponents.ps1 -PVWAURL https://pvwacpm1.51sectest.dev/PasswordVault -ConnectionComponentZipPath "C:\Temp\Office-365 1.1.zip" -DisableSSLVerify
PS C:\temp> .\Import-ConnectionComponents.ps1 -pvwaurl https://172.23.1.25/PasswordVault/ -ConnectionComponentzippath "C:\temp\Office-365 1.1.zip"
Import Connection Component: Script Started
Logon Token is Empty - Cannot login
PS C:\temp> .\Import-ConnectionComponents.ps1 -pvwaurl https://172.23.1.25/PasswordVault/ -ConnectionComponentzippath "C:\temp\Office-365 1.1.zip" -DisableSSLVerify
Import Connection Component: Script Started
Connection Component ID imported: PSM-Office-365
Logoff Session...
Import Connection Component: Script Ended
PS C:\temp>

More details can be found from following YouTube Video:

Modify Connection Component and Add it into Platform

If you are using default Generic Web App as your platform, you will need to change LogonURL from https://login.microsoftonline.com/ to https://{address}

After this Logon URL change, you will need assign this new Connection Components to your Generic Web App platform as show below, also do not forget attach PSM to your platform:

Connect

Create your O365 admin account under Website system type,  your Generic Web App Platform and your own safe in PVWA, and you will need to enter username, address and password:

Select right connection component to do connect:

References

By Jon

Leave a Reply