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
-
Remove the read-only permission from the PSMConfigureAppLocker.xml file.
-
In the Hardening subfolder of PSM installation folder, open the PSMConfigureAppLocker.xml configuration file and edit the AllowedApplications section:At the beginning of the Google Chrome processes section, remove the following line:
<!– If relevant, uncomment this part to allow Google Chrome webform based connection clients
At the end of the Google Chrome processes section, remove the following line:End of Google Chrome process comment –>
Specifically, make sure that the following lines are uncommented:
<Application Name=”PSM-WebAppDispatcher” Type=”Exe” SessionType=”*” Path=”C:\Program Files (x86)\CyberArk\PSM\Components\CyberArk.PSM.WebAppDispatcher.exe” Method=”Hash” /> - <Application Name=”chromedriver” Type=”Exe” SessionType=”*” Path=”C:\Program Files (x86)\CyberArk\PSM\Components\chromedriver.exe” Method=”Hash” />
- <Application Name=”PSM-ProgressBar” Type=”Exe” SessionType=”*” Path=”C:\Program Files (x86)\CyberArk\PSM\Components\CyberArk.ProgressBar.exe” Method=”Hash” /><Application Name=”GoogleChrome” Type=”Exe” Path=”C:\Program Files (x86)\Google\Chrome\Application\chrome.exe” Method=”Hash” />
- <Application Name=”IExplore32″ Type=”Exe” Path=”c:\Program Files (x86)\Internet Explorer\iexplore.exe” Method=”Publisher” />
- <Application Name=”IExplore64″ Type=”Exe” Path=”c:\Program Files (x86)\Internet Explorer\iexplore.exe” Method=”Publisher” />
Verify that the path specified in the xml matches the browser installation path. -
Save the PSMConfigureAppLocker.xml configuration file and close it.
.\PSMConfigureAppLocker.ps1
-
For version 10.2 or later: Run PSMHardening.ps1 in the PSM\Hardening folder.
-
For versions 9.7 – 10.1: Run the RunGroupPolicyLoader.bat file located in the Hardening folder of the installation package.After running this script, make sure the output logs are empty.
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>
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: