diff --git a/RDP Applications/AutoIt/Deprecated - web_Okta/README.md b/RDP Applications/AutoIt/Deprecated - web_Okta/README.md new file mode 100644 index 0000000..0430e13 --- /dev/null +++ b/RDP Applications/AutoIt/Deprecated - web_Okta/README.md @@ -0,0 +1,6 @@ +# DEPRECATED +For various reasons RDP Application launching for web applications based on AutoIT has been deprecated. + +The primary suggestion is to use the Go-based implementation: https://github.com/OneIdentity/SafeguardAutomation/tree/master/RDP%20Applications/Go%20chromedp + +In case you need to inject credentials into web applications accessed through Firefox, the AutoIT code could be ported e.g. to C# and Selenium, or other preferred method. \ No newline at end of file diff --git a/RDP Applications/AutoIt/web_Okta/web_Okta.au3 b/RDP Applications/AutoIt/Deprecated - web_Okta/web_Okta.au3 similarity index 100% rename from RDP Applications/AutoIt/web_Okta/web_Okta.au3 rename to RDP Applications/AutoIt/Deprecated - web_Okta/web_Okta.au3 diff --git a/RDP Applications/AutoIt/web_SPS/README.md b/RDP Applications/AutoIt/Deprecated - web_SPS/README.md similarity index 80% rename from RDP Applications/AutoIt/web_SPS/README.md rename to RDP Applications/AutoIt/Deprecated - web_SPS/README.md index c07b8ae..89c3050 100644 --- a/RDP Applications/AutoIt/web_SPS/README.md +++ b/RDP Applications/AutoIt/Deprecated - web_SPS/README.md @@ -1,3 +1,10 @@ +# DEPRECATED +For various reasons RDP Application launching for web applications based on AutoIT has been deprecated. + +The primary suggestion is to use the Go-based implementation: https://github.com/OneIdentity/SafeguardAutomation/tree/master/RDP%20Applications/Go%20chromedp + +In case you need to inject credentials into web applications accessed through Firefox, the AutoIT code could be ported e.g. to C# and Selenium, or other preferred method. + # Web Application login for SPS Only for demo use. diff --git a/RDP Applications/AutoIt/web_SPS/web_SPS_local_user.au3 b/RDP Applications/AutoIt/Deprecated - web_SPS/web_SPS_local_user.au3 similarity index 100% rename from RDP Applications/AutoIt/web_SPS/web_SPS_local_user.au3 rename to RDP Applications/AutoIt/Deprecated - web_SPS/web_SPS_local_user.au3 diff --git a/RDP Applications/AutoIt/web_SPS/web_SPS_pre_6.12.au3 b/RDP Applications/AutoIt/Deprecated - web_SPS/web_SPS_pre_6.12.au3 similarity index 100% rename from RDP Applications/AutoIt/web_SPS/web_SPS_pre_6.12.au3 rename to RDP Applications/AutoIt/Deprecated - web_SPS/web_SPS_pre_6.12.au3 diff --git a/RDP Applications/AutoIt/web_SPS/webdriver/BinaryCall.au3 b/RDP Applications/AutoIt/Deprecated - web_SPS/webdriver/BinaryCall.au3 similarity index 100% rename from RDP Applications/AutoIt/web_SPS/webdriver/BinaryCall.au3 rename to RDP Applications/AutoIt/Deprecated - web_SPS/webdriver/BinaryCall.au3 diff --git a/RDP Applications/AutoIt/web_SPS/webdriver/Json.au3 b/RDP Applications/AutoIt/Deprecated - web_SPS/webdriver/Json.au3 similarity index 100% rename from RDP Applications/AutoIt/web_SPS/webdriver/Json.au3 rename to RDP Applications/AutoIt/Deprecated - web_SPS/webdriver/Json.au3 diff --git a/RDP Applications/AutoIt/web_SPS/webdriver/WinHttp.au3 b/RDP Applications/AutoIt/Deprecated - web_SPS/webdriver/WinHttp.au3 similarity index 100% rename from RDP Applications/AutoIt/web_SPS/webdriver/WinHttp.au3 rename to RDP Applications/AutoIt/Deprecated - web_SPS/webdriver/WinHttp.au3 diff --git a/RDP Applications/AutoIt/web_SPS/webdriver/WinHttpConstants.au3 b/RDP Applications/AutoIt/Deprecated - web_SPS/webdriver/WinHttpConstants.au3 similarity index 100% rename from RDP Applications/AutoIt/web_SPS/webdriver/WinHttpConstants.au3 rename to RDP Applications/AutoIt/Deprecated - web_SPS/webdriver/WinHttpConstants.au3 diff --git a/RDP Applications/AutoIt/web_SPS/webdriver/wd_cdp.au3 b/RDP Applications/AutoIt/Deprecated - web_SPS/webdriver/wd_cdp.au3 similarity index 100% rename from RDP Applications/AutoIt/web_SPS/webdriver/wd_cdp.au3 rename to RDP Applications/AutoIt/Deprecated - web_SPS/webdriver/wd_cdp.au3 diff --git a/RDP Applications/AutoIt/web_SPS/webdriver/wd_core.au3 b/RDP Applications/AutoIt/Deprecated - web_SPS/webdriver/wd_core.au3 similarity index 100% rename from RDP Applications/AutoIt/web_SPS/webdriver/wd_core.au3 rename to RDP Applications/AutoIt/Deprecated - web_SPS/webdriver/wd_core.au3 diff --git a/RDP Applications/AutoIt/web_SPS/webdriver/wd_demo.au3 b/RDP Applications/AutoIt/Deprecated - web_SPS/webdriver/wd_demo.au3 similarity index 100% rename from RDP Applications/AutoIt/web_SPS/webdriver/wd_demo.au3 rename to RDP Applications/AutoIt/Deprecated - web_SPS/webdriver/wd_demo.au3 diff --git a/RDP Applications/AutoIt/web_SPS/webdriver/wd_helper.au3 b/RDP Applications/AutoIt/Deprecated - web_SPS/webdriver/wd_helper.au3 similarity index 100% rename from RDP Applications/AutoIt/web_SPS/webdriver/wd_helper.au3 rename to RDP Applications/AutoIt/Deprecated - web_SPS/webdriver/wd_helper.au3 diff --git a/RDP Applications/AutoIt/web_generic/README.md b/RDP Applications/AutoIt/Deprecated - web_generic/README.md similarity index 81% rename from RDP Applications/AutoIt/web_generic/README.md rename to RDP Applications/AutoIt/Deprecated - web_generic/README.md index 045f9d6..5125a60 100644 --- a/RDP Applications/AutoIt/web_generic/README.md +++ b/RDP Applications/AutoIt/Deprecated - web_generic/README.md @@ -1,3 +1,10 @@ +# DEPRECATED +For various reasons RDP Application launching for web applications based on AutoIT has been deprecated. + +The primary suggestion is to use the Go-based implementation: https://github.com/OneIdentity/SafeguardAutomation/tree/master/RDP%20Applications/Go%20chromedp + +In case you need to inject credentials into web applications accessed through Firefox, the AutoIT code could be ported e.g. to C# and Selenium, or other preferred method. + # Web Application login for arbitrary web applications Only for demo use. diff --git a/RDP Applications/AutoIt/Deprecated - web_generic/browser_driver_update.ps1 b/RDP Applications/AutoIt/Deprecated - web_generic/browser_driver_update.ps1 new file mode 100644 index 0000000..f82111f --- /dev/null +++ b/RDP Applications/AutoIt/Deprecated - web_generic/browser_driver_update.ps1 @@ -0,0 +1,295 @@ +################ +# Code is delivered "AS IS". Any issues encountered can be reported on Github and contributors will make a best effort to resolve them. +################ +# +# Update browser driver to the latest stable release +# It does not check what browser version is installed, it just downloads the latest stable driver +# If there is no driver file on the specified path, the script also downloads the latest stable one and copies it to the specified path +# +######### +# USAGE: +# Configure the desired driver path below at VARIABLES per each browser type, then then run the script in PowerShell for the specified browser type +# .\browser_driver_update.ps1 + + +param( + [Parameter(Mandatory=$true)] + [string] $browser +) + + +######### +# VARIABLES +# +# Platform can be: win32, win64 +$platform="win64" +# +# Configure the path for the driver +# The running user must have RW permissions in the folder +# If the file already exits, the script will compare its version to the latest available driver and overwrite the existing one if a newer one is available +# You can define multiple path, one per browser type, and the script will update the one given as argument +switch ($browser) { + "chrome" { + $driverpath="C:\\chromedriver.exe" + } + + "edge" { + $driverpath="C:\\msedgedriver.exe" + } + + "firefox" { + $driverpath="C:\\geckodriver.exe" + } + + default { + Write-Error "Browser parameter must either be 'chrome', 'edge', or 'firefox'" + exit 1 + } +} + +$driverFolder = Split-Path -Parent $driverPath + + +######### +# FUNCTIONS + +function getDriverVersion { + param ( + [Parameter(Mandatory=$true)] + [string] $browser + ) + + Switch ($browser) { + "chrome" { + try { + return Invoke-Expression "& '$driverpath' --version" + } + catch { + return "Can't identify driver version, maybe a wrong file path is given? Let's just download the latest stable driver" + } + } + + "edge" { + try { + return Invoke-Expression "& '$driverpath' --version" + } + catch { + return "Can't identify driver version, maybe a wrong file path is given? Let's just download the latest stable driver" + } + + } + + "firefox" { + try { + return $(Invoke-Expression "& '$driverpath' --version")[0] + } + catch { + return "Can't identify driver version, maybe a wrong file path is given? Let's just download the latest stable driver" + } + } + + + } +} + +#function getBrowserVersion { +# param ( +# [Parameter(Mandatory=$true)] +# [string] $browser +# ) + +# Switch ($browser) { +# "chrome" { +# $installed = gwmi cim_datafile -Filter {Name='C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe'} +# return $installed.Version +# } + +# "edge" { + #TODO +# } + +# "firefox" { + #TODO +# } + + +# } +#} + +function getLatestStableDriverVersion { + param ( + [Parameter(Mandatory=$true)] + [string] $browser + ) + + Switch ($browser) { + "chrome" { + return Invoke-RestMethod -Uri "https://googlechromelabs.github.io/chrome-for-testing/LATEST_RELEASE_STABLE" -Method Get + } + "edge" { + $latestStableVersionFile = $driverFolder + "\msedgedriver_LATEST_STABLE.txt" + Invoke-RestMethod -Uri "https://msedgedriver.azureedge.net/LATEST_STABLE" -Method Get -OutFile $latestStableVersionFile + $stableVersion = Get-Content -Path $latestStableVersionFile -TotalCount 1 + Remove-Item -Force -Path $latestStableVersionFile + return $stableVersion + } + + "firefox" { + $latestGecko = Invoke-RestMethod -Uri "https://api.github.com/repos/mozilla/geckodriver/releases/latest" -Method Get + return $latestGecko.name + } + + + } + +} + +function getDownloadUrl { + param ( + [Parameter(Mandatory=$true)] + [string] $browser, + [Parameter(Mandatory=$true)] + [string] $version + ) + + Switch ($browser) { + "chrome" { + + $uri = "https://googlechromelabs.github.io/chrome-for-testing/"+$version+".json" + $downloads = Invoke-RestMethod -Uri $uri -Method Get + foreach ($_ in $downloads.downloads.chromedriver) { + if ($_.platform -eq $platform) { + return $_.url + } + } + Write-Error "Download URL not found for platform:"$platform + exit 1 + } + + "edge" { + return "https://msedgedriver.azureedge.net/" + $version + "/edgedriver_" + $platform + ".zip" + } + + "firefox" { + return "https://github.com/mozilla/geckodriver/releases/download/v" + $version + "/geckodriver-v" + $version + "-" + $platform + ".zip" + } + + + } + +} + +function updateDriver { + param ( + [Parameter(Mandatory=$true)] + [string] $browser, + [Parameter(Mandatory=$true)] + [string] $url + ) + + + Switch ($browser) { + "chrome" { + $driverFileName = "chromedriver.exe" + $zipPath = $driverFolder + "\chromedriver_tmp.zip" + } + + "edge" { + $driverFileName = "msedgedriver.exe" + $zipPath = $driverFolder + "\msedgedriver_tmp.zip" + } + + "firefox" { + $driverFileName = "geckodriver.exe" + $zipPath = $driverFolder + "\geckodriver_tmp.zip" + } + + + + + } + + try { + Invoke-RestMethod -Uri $url -Method Get -OutFile $zipPath + } catch { + Write-Error "An error occured while downloading the driver package" + exit 1 + } + + try { + + # Load compression methods + Add-Type -AssemblyName System.IO.Compression.FileSystem + + # Open zip file for reading + $driverZip = [System.IO.Compression.ZipFile]::OpenRead($zipPath) + # Copy selected items to the target directory + $driverZip.Entries | + ForEach-Object -Process { + if ($_.Name -eq $driverFileName) { + [System.IO.Compression.ZipFileExtensions]::ExtractToFile($_, $driverPath , $true) + } + } + $driverZip.Dispose() + Remove-Item -Force -Path $zipPath + + + } catch { + Write-Error "An error occured while extracting the driver from the zip file" + exit 1 + } + +} + +function trimDriverVersion { + param ( + [Parameter(Mandatory=$true)] + [string] $browser, + [Parameter(Mandatory=$true)] + [string] $version + ) + + Switch ($browser) { + "chrome" { + return $version.Substring(13) + + } + + "edge" { + return $version.Substring(25) + } + + "firefox" { + return $version.Substring(12) + } + } +} + +######### +# SCRIPT + +$driverversion=getDriverVersion($browser) +Write-Host "Installed driver:"$driverversion + + + +$latestStableDriver=getLatestStableDriverVersion($browser) +Write-Host "Latest stable driver:"$latestStableDriver + +# String comparison does not work, let's trim $driverVersion +$driverVersion = trimDriverVersion -browser $browser -version $driverVersion + +if ($driverversion.StartsWith($latestStableDriver)) { + Write-Host "Installed driver matches latest stable driver. Do nothing" + exit 0 +} else { + $downloadUrl = getDownloadUrl -browser $browser -version $latestStableDriver + updateDriver -browser $browser -url $downloadUrl +} + +$newDriverVersion = getDriverVersion($browser) +Write-Host "New driver installed:"$newDriverVersion + + + + diff --git a/RDP Applications/AutoIt/web_generic/webdriver/BinaryCall.au3 b/RDP Applications/AutoIt/Deprecated - web_generic/lib/BinaryCall.au3 similarity index 100% rename from RDP Applications/AutoIt/web_generic/webdriver/BinaryCall.au3 rename to RDP Applications/AutoIt/Deprecated - web_generic/lib/BinaryCall.au3 diff --git a/RDP Applications/AutoIt/web_generic/webdriver/BlockInputEX.au3 b/RDP Applications/AutoIt/Deprecated - web_generic/lib/BlockInputEX.au3 similarity index 100% rename from RDP Applications/AutoIt/web_generic/webdriver/BlockInputEX.au3 rename to RDP Applications/AutoIt/Deprecated - web_generic/lib/BlockInputEX.au3 diff --git a/RDP Applications/AutoIt/web_generic/webdriver/Json.au3 b/RDP Applications/AutoIt/Deprecated - web_generic/lib/Json.au3 similarity index 100% rename from RDP Applications/AutoIt/web_generic/webdriver/Json.au3 rename to RDP Applications/AutoIt/Deprecated - web_generic/lib/Json.au3 diff --git a/RDP Applications/AutoIt/Deprecated - web_generic/lib/UnixTime.au3 b/RDP Applications/AutoIt/Deprecated - web_generic/lib/UnixTime.au3 new file mode 100644 index 0000000..7944dbf --- /dev/null +++ b/RDP Applications/AutoIt/Deprecated - web_generic/lib/UnixTime.au3 @@ -0,0 +1,60 @@ +#include +#include +#include + +;Local $iUnixTime1 = _GetUnixTime() + +;MsgBox($MB_SYSTEMMODAL, 'Seconds Since Jan, 1st, 1970 00:00:00 GMT', $iUnixTime1) + +;Local $sUnixDate1 = _GetDate_fromUnixTime($iUnixTime1) +;MsgBox($MB_SYSTEMMODAL, "", $sUnixDate1) + +;$sUnixDate1 = _GetDate_fromUnixTime($iUnixTime1, False) +;MsgBox($MB_SYSTEMMODAL, "", $sUnixDate1) + +;$sUnixDate1 = _GetDate_fromUnixTime($iUnixTime1, False, False) +;MsgBox($MB_SYSTEMMODAL, "", $sUnixDate1) + +;Local $iUnixTime2 = _GetUnixTime('2013/01/01 00:00:00') +;MsgBox($MB_SYSTEMMODAL, "", $iUnixTime2) + +; Get timestamp for input datetime (or current datetime). +Func _GetUnixTime($sDate = 0);Date Format: 2013/01/01 00:00:00 ~ Year/Mo/Da Hr:Mi:Se + + Local $aSysTimeInfo = _Date_Time_GetTimeZoneInformation() + Local $utcTime = "" + + If Not $sDate Then $sDate = _NowCalc() + + If Int(StringLeft($sDate, 4)) < 1970 Then Return "" + + If $aSysTimeInfo[0] = 2 Then ; if daylight saving time is active + $utcTime = _DateAdd('n', $aSysTimeInfo[1] + $aSysTimeInfo[7], $sDate) ; account for time zone and daylight saving time + Else + $utcTime = _DateAdd('n', $aSysTimeInfo[1], $sDate) ; account for time zone + EndIf + + Return _DateDiff('s', "1970/01/01 00:00:00", $utcTime) +EndFunc ;==>_GetUnixTime + +;$blTrim: Year in short format and no seconds. +Func _GetDate_fromUnixTime($iUnixTime, $blTrim = True, $iReturnLocal = True) + Local $aRet = 0, $aDate = 0 + Local $aMonthNumberAbbrev[13] = ["", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] + Local $timeAdj = 0 + If Not $iReturnLocal Then + Local $aSysTimeInfo = _Date_Time_GetTimeZoneInformation() + Local $timeAdj = $aSysTimeInfo[1] * 60 + If $aSysTimeInfo[0] = 2 Then $timeAdj += $aSysTimeInfo[7] * 60 + EndIf + + $aRet = DllCall("msvcrt.dll", "str:cdecl", "ctime", "int*", $iUnixTime + $timeAdj ) + + If @error Or Not $aRet[0] Then Return "" + + $aDate = StringSplit(StringTrimRight($aRet[0], 1), " ", 2) + + If $blTrim Then Return StringRight($aDate[4], 2) & "/" & StringFormat("%.2d",_ArraySearch($aMonthNumberAbbrev, $aDate[1])) & "/" & $aDate[2] & " " & StringTrimRight($aDate[3], 3) + + Return $aDate[4] & "/" & StringFormat("%.2d", _ArraySearch($aMonthNumberAbbrev, $aDate[1])) & "/" & $aDate[2] & " " & $aDate[3] +EndFunc ;==>_GetUnixDate \ No newline at end of file diff --git a/RDP Applications/AutoIt/web_generic/webdriver/WinHttp.au3 b/RDP Applications/AutoIt/Deprecated - web_generic/lib/WinHttp.au3 similarity index 100% rename from RDP Applications/AutoIt/web_generic/webdriver/WinHttp.au3 rename to RDP Applications/AutoIt/Deprecated - web_generic/lib/WinHttp.au3 diff --git a/RDP Applications/AutoIt/web_generic/webdriver/WinHttpConstants.au3 b/RDP Applications/AutoIt/Deprecated - web_generic/lib/WinHttpConstants.au3 similarity index 100% rename from RDP Applications/AutoIt/web_generic/webdriver/WinHttpConstants.au3 rename to RDP Applications/AutoIt/Deprecated - web_generic/lib/WinHttpConstants.au3 diff --git a/RDP Applications/AutoIt/web_generic/webdriver/wd_cdp.au3 b/RDP Applications/AutoIt/Deprecated - web_generic/lib/wd_cdp.au3 similarity index 100% rename from RDP Applications/AutoIt/web_generic/webdriver/wd_cdp.au3 rename to RDP Applications/AutoIt/Deprecated - web_generic/lib/wd_cdp.au3 diff --git a/RDP Applications/AutoIt/web_generic/webdriver/wd_core.au3 b/RDP Applications/AutoIt/Deprecated - web_generic/lib/wd_core.au3 similarity index 99% rename from RDP Applications/AutoIt/web_generic/webdriver/wd_core.au3 rename to RDP Applications/AutoIt/Deprecated - web_generic/lib/wd_core.au3 index 7ccb5e6..1dfbfdd 100644 --- a/RDP Applications/AutoIt/web_generic/webdriver/wd_core.au3 +++ b/RDP Applications/AutoIt/Deprecated - web_generic/lib/wd_core.au3 @@ -1227,7 +1227,7 @@ EndFunc ;==>_WD_Option ; Name ..........: _WD_Startup ; Description ...: Launch the designated web driver console app ; Syntax ........: _WD_Startup() -; Parameters ....: None +; Parameters ....: $skipWDVersionCheck -- allows skipping _WD_IsLatestRelease connect to Internet ; Return values .: Success - PID for the WD console ; Failure - 0 ; @ERROR - $_WD_ERROR_Success @@ -1241,7 +1241,7 @@ EndFunc ;==>_WD_Option ; Link ..........: ; Example .......: No ; =============================================================================================================================== -Func _WD_Startup() +Func _WD_Startup($skipWDVersionCheck) Local Const $sFuncName = "_WD_Startup" Local $sFunction, $bLatest, $sUpdate, $sFile, $pid @@ -1254,23 +1254,25 @@ Func _WD_Startup() Local $sCommand = StringFormat('"%s" %s ', $_WD_DRIVER, $_WD_DRIVER_PARAMS) If $_WD_DEBUG = $_WD_DEBUG_Info Then - $sFunction = "_WD_IsLatestRelease" - $bLatest = Call($sFunction) + If $skipWDVersionCheck <> 0 Then + $sFunction = "_WD_IsLatestRelease" + $bLatest = Call($sFunction) - Select - Case @error = 0xDEAD And @extended = 0xBEEF - $sUpdate = "" ; update check not performed + Select + Case @error = 0xDEAD And @extended = 0xBEEF + $sUpdate = "" ; update check not performed - Case @error - $sUpdate = " (Update status unknown [" & @error & "])" + Case @error + $sUpdate = " (Update status unknown [" & @error & "])" - Case $bLatest - $sUpdate = " (Up to date)" + Case $bLatest + $sUpdate = " (Up to date)" - Case Not $bLatest - $sUpdate = " (Update available)" + Case Not $bLatest + $sUpdate = " (Update available)" - EndSelect + EndSelect + EndIf Local $sWinHttpVer = __WinHttpVer() If $sWinHttpVer < "1.6.4.2" Then diff --git a/RDP Applications/AutoIt/web_generic/webdriver/wd_demo.au3 b/RDP Applications/AutoIt/Deprecated - web_generic/lib/wd_demo.au3 similarity index 100% rename from RDP Applications/AutoIt/web_generic/webdriver/wd_demo.au3 rename to RDP Applications/AutoIt/Deprecated - web_generic/lib/wd_demo.au3 diff --git a/RDP Applications/AutoIt/web_generic/webdriver/wd_helper.au3 b/RDP Applications/AutoIt/Deprecated - web_generic/lib/wd_helper.au3 similarity index 100% rename from RDP Applications/AutoIt/web_generic/webdriver/wd_helper.au3 rename to RDP Applications/AutoIt/Deprecated - web_generic/lib/wd_helper.au3 diff --git a/RDP Applications/AutoIt/Deprecated - web_generic/wd.conf b/RDP Applications/AutoIt/Deprecated - web_generic/wd.conf new file mode 100644 index 0000000..c45c12e --- /dev/null +++ b/RDP Applications/AutoIt/Deprecated - web_generic/wd.conf @@ -0,0 +1,13 @@ +## wd_core.au3 default code is changed, skipWDVersionCheck skips the _WD_IsLatestRelease to connect to the Internet +skipWDVersionCheck=1 +## 0 closes the webdriver console once the session is started +WDConsoleVisible=0 +## Chrome capabilities with normal browser, not kiosk mode: +#chromeCapabilities={"capabilities": {"alwaysMatch": {"goog:chromeOptions": {"w3c": true, "excludeSwitches": [ "enable-automation"], "prefs": { "credentials_enable_service": false, "profile": { "password_manager_enabled": false}}} }}} +## Chrome capabilities with kiosk mode: +chromeCapabilities={"capabilities": {"alwaysMatch": {"goog:chromeOptions": {"args": ["--kiosk"], "w3c": true, "excludeSwitches": [ "enable-automation"], "prefs": { "credentials_enable_service": false, "profile": { "password_manager_enabled": false}}} }}} +## Firefox capabilities with normal browser, not kiosk mode: +#firefoxCapabilities={ "capabilities": { "alwaysMatch": { "moz:firefoxOptions": {"prefs": { "devtools.accessibility.enabled": false, "devtools.application.enabled": false, "devtools.chrome.enabled": false, "devtools.command-button-errorcount.enabled": false, "devtools.command-button-frames.enabled": false, "devtools.command-button-measure.enabled": false, "devtools.command-button-noautohide.enabled": false, "devtools.command-button-pick.enabled": false, "devtools.command-button-responsive.enabled": false, "devtools.command-button-rulers.enabled": false, "devtools.command-button-screenshot.enabled": false, "devtools.command-button-splitconsole.enabled": false, "devtools.custom-formatters.enabled": false, "devtools.debugger.enabled": false, "devtools.debugger.map-scopes-enabled": false, "devtools.debugger.pretty-print-enabled": false, "devtools.debugger.remote-enabled": false, "devtools.debugger.ui.variables-sorting-enabled": false, "devtools.dom.enabled": false, "devtools.every-frame-target.enabled": false, "devtools.inspector.chrome.three-pane-enabled": false, "devtools.inspector.compatibility.enabled": false, "devtools.inspector.enabled": false, "devtools.inspector.inactive.css.enabled": false, "devtools.inspector.ruleview.inline-compatibility-warning.enabled": false, "devtools.inspector.three-pane-enabled": false, "devtools.jsonview.enabled": false, "devtools.markup.mutationBreakpoints.enabled": false, "devtools.memory.enabled": false, "devtools.netmonitor.enabled": false, "devtools.overflow.debugging.enabled": false, "devtools.performance.enabled": false, "devtools.performance.recording.active-tab-view.enabled": false, "devtools.responsive.leftAlignViewport.enabled": false, "devtools.responsive.reloadNotification.enabled": false, "devtools.responsive.touchSimulation.enabled": false, "devtools.screenshot.audio.enabled": false, "devtools.screenshot.clipboard.enabled": false, "devtools.serviceWorkers.testing.enabled": false, "devtools.source-map.client-service.enabled": false, "devtools.storage.enabled": false, "devtools.storage.extensionStorage.enabled": false, "devtools.styleeditor.autocompletion-enabled": false, "devtools.styleeditor.enabled": false, "devtools.target-switching.server.enabled": false, "devtools.toolbox.splitconsoleEnabled": false, "devtools.webconsole.enabled": false } }, "browserName": "firefox", "acceptInsecureCerts":true } } } +## Firefox capabilities with kiosk mode: +firefoxCapabilities={ "capabilities": { "alwaysMatch": { "moz:firefoxOptions": { "args": ["-kiosk"], "prefs": { "devtools.accessibility.enabled": false, "devtools.application.enabled": false, "devtools.chrome.enabled": false, "devtools.command-button-errorcount.enabled": false, "devtools.command-button-frames.enabled": false, "devtools.command-button-measure.enabled": false, "devtools.command-button-noautohide.enabled": false, "devtools.command-button-pick.enabled": false, "devtools.command-button-responsive.enabled": false, "devtools.command-button-rulers.enabled": false, "devtools.command-button-screenshot.enabled": false, "devtools.command-button-splitconsole.enabled": false, "devtools.custom-formatters.enabled": false, "devtools.debugger.enabled": false, "devtools.debugger.map-scopes-enabled": false, "devtools.debugger.pretty-print-enabled": false, "devtools.debugger.remote-enabled": false, "devtools.debugger.ui.variables-sorting-enabled": false, "devtools.dom.enabled": false, "devtools.every-frame-target.enabled": false, "devtools.inspector.chrome.three-pane-enabled": false, "devtools.inspector.compatibility.enabled": false, "devtools.inspector.enabled": false, "devtools.inspector.inactive.css.enabled": false, "devtools.inspector.ruleview.inline-compatibility-warning.enabled": false, "devtools.inspector.three-pane-enabled": false, "devtools.jsonview.enabled": false, "devtools.markup.mutationBreakpoints.enabled": false, "devtools.memory.enabled": false, "devtools.netmonitor.enabled": false, "devtools.overflow.debugging.enabled": false, "devtools.performance.enabled": false, "devtools.performance.recording.active-tab-view.enabled": false, "devtools.responsive.leftAlignViewport.enabled": false, "devtools.responsive.reloadNotification.enabled": false, "devtools.responsive.touchSimulation.enabled": false, "devtools.screenshot.audio.enabled": false, "devtools.screenshot.clipboard.enabled": false, "devtools.serviceWorkers.testing.enabled": false, "devtools.source-map.client-service.enabled": false, "devtools.storage.enabled": false, "devtools.storage.extensionStorage.enabled": false, "devtools.styleeditor.autocompletion-enabled": false, "devtools.styleeditor.enabled": false, "devtools.target-switching.server.enabled": false, "devtools.toolbox.splitconsoleEnabled": false, "devtools.webconsole.enabled": false } }, "browserName": "firefox", "acceptInsecureCerts":true } } } +edgeCapabilities={"capabilities": {"alwaysMatch": {"ms:edgeOptions": {"excludeSwitches": [ "enable-automation"]}}}} \ No newline at end of file diff --git a/RDP Applications/AutoIt/Deprecated - web_generic/web_generic.au3 b/RDP Applications/AutoIt/Deprecated - web_generic/web_generic.au3 new file mode 100644 index 0000000..b6e8239 --- /dev/null +++ b/RDP Applications/AutoIt/Deprecated - web_generic/web_generic.au3 @@ -0,0 +1,377 @@ +; NEWS SINCE LAST RELEASE (3.5) +; - Enhanced debugging +; -- if debug=1 the WD console remains open on the screen +; -- few more logs +; - use wd.conf file from webdriver folder +; - modified wd_core.au3, $skipWDVersionCheck -- allows skipping _WD_IsLatestRelease connect to Internet + + +; ONLY FOR DEMO USE +; +; Compile with Aut2exe to ensure the include files are compiled too +; +; cmd line arguments for launcher: OI-SG-RemoteApp-Launcher.exe --cmd \web_generic.exe --args " targetUrl v::css1::{username}||c::css2||c::css3||s::css4::{password}||o::css4::{Target.TotpCodes}::5||c::css5 [optional:{asset}]" + +; +; Altough the code supports Firefox (needs geckodriver.exe) and Edge (needs msedgedriver.exe) too: +; - Edge has not been tested at all +; - It is not reliable with Firefox. Also, it should disable devtools but in the tests not all of them got disabled and users can re-enable them at this point. +; +; Web orchestration parameters: +; If 'basicauth' is given then no orchestration is performed, the browser is just navigating to what is given in --args. +; In such case the targetURL may be given in the following format: {username}:{password}@{Target.AssetNetworkAddress}/optionalPage +; +; The code supports any number of selectors, types of: +; "v" as value +; "c" as click +; "s" as secret which is not logged +; "o" as totp json input, with the minimum number of seconds required to enter the OTP before it expires +; separated by "||". +; +; The actual action is defined with "::" separator. +; Sample: "v::css1::username||c::css2||c::css3||s::css4::password||o::css4::{Target.TotpCodes}::5||c::css5" +; +; The code disables user input and hides the WebDriver console when not running in debug mode + +$web_generic_script = @ScriptName + +Opt("TrayAutoPause", 0) +Opt("TrayIconDebug", 0) + +#include +#include +#include + +#include 'lib\UnixTime.au3' +#include 'lib\json.au3' +#include 'lib\wd_core.au3' +#include 'lib\wd_helper.au3' +#include "lib\BlockInputEX.au3" + +Local $debug = $CmdLine[1] +Local $browser = $CmdLine[2] +Local $target = $CmdLine[3] +Local $input = $CmdLine[4] +If $CmdLine[0] = 5 Then + Local $asset = $CmdLine[5] ; Asset will not be used as cloud targets may be accessible on a different name than the Asset Name / Network Address in SPP, however the {asset} parameter must be given for the Launcher. +EndIf +Local $loglevel = '' +Local $wd_conf_file = @ScriptDir & '\wd.conf' + +If $debug = 1 Then + $loglevel = 'debug' +Else + $loglevel = 'info' +EndIf +$logfile = FileOpen(@UserProfileDir & "\AppData\Roaming\OneIdentity\OI-SG-RemoteApp-Launcher-Orchestration\web_generic_" & @YEAR & @MON & @MDAY & ".log", $FO_APPEND + $FO_CREATEPATH) +Logger('info', "Starting " & $web_generic_script & " with loglevel:" & $loglevel) +Logger('debug', "browser=" & $browser) + +; Read webdriver configuration from webdriver\wd.conf file +Logger('debug', "Reading wd configuration from: " & $wd_conf_file) +Local $hFileOpen = FileOpen($wd_conf_file, $FO_READ) +If $hFileOpen = -1 Then + Logger('info', "An error occurred when reading the wd conf file: " & $wd_conf_file) + Exit +EndIf + +While 1 + Local $sFileRead = FileReadLine($hFileOpen) + ; if reaching EOF + If @error = -1 Then ExitLoop + ; skip comments with parsing + If StringLeft($sFileRead, 1) <> "#" Then + Logger('debug', "wd.conf: " & $sFileRead) + Local $wd_conf = StringSplit ($sFileRead, "=") + Switch $wd_conf[1] + Case "skipWDVersionCheck" + $skipWDVersionCheck=$wd_conf[2] + Case "chromeCapabilities" + $chromeCapabilities=$wd_conf[2] + Case "firefoxCapabilities" + $firefoxCapabilities=$wd_conf[2] + Case "edgeCapabilities" + $edgeCapabilities=$wd_conf[2] + Case "WDConsoleVisible" + $WDConsoleVisible=$wd_conf[2] + Case Else + Logger('info', "Unknown webdriver configuration in wd.conf: " & $wd_conf[1]) + Exit + EndSwitch + EndIf +WEnd +FileClose($hFileOpen) + +Local $sDesiredCapabilities, $sSession + +; Note: Make sure chromedriver is up-to-date. Chrome is updating frequently, chromedriver should have the matching version. +Switch $browser + Case 'chrome' + SetupChrome() + $sDesiredCapabilities = $chromeCapabilities + Case 'c' + SetupChrome() + $sDesiredCapabilities = $chromeCapabilities + Case 'firefox' + SetupGecko() + $sDesiredCapabilities = $firefoxCapabilities + Case 'f' + SetupGecko() + $sDesiredCapabilities = $firefoxCapabilities + Case 'edge' + SetupEdge() + $sDesiredCapabilities = $edgeCapabilities + Case 'e' + SetupEdge() + $sDesiredCapabilities = $edgeCapabilities +EndSwitch + +; Disable user input +If $debug = 0 Then + _BlockInput($BI_DISABLE) +Else + Logger('debug', 'User input is not disabled in debug mode') +EndIf + +;_WD_Startup() in wd_core.au3 connects to the Internet for checking +Logger('debug', 'Starting webdriver with skipWDVersionCheck=' & $skipWDVersionCheck) +_WD_Startup($skipWDVersionCheck) + + +; Create session +Logger('debug', 'Creating session with capabilities: ' & $sDesiredCapabilities) +While $_WD_HTTPRESULT <> 200 + $sSession = _WD_CreateSession($sDesiredCapabilities) + Logger('debug', 'HTTPRESULT: ' & $_WD_HTTPRESULT) +WEnd +$_WD_HTTPRESULT = 0 +Logger('debug', 'Session: ' & $sSession) + +; Hide the WebDriver console +If $WDConsoleVisible = 0 Then + _WD_ConsoleVisible(false) +Else + Logger('debug', 'WDConsoleVisible=1, Keeping WebDriver console visible') +EndIf + +; Navigate to asset website +$url= 'https://' & $target +While $_WD_HTTPRESULT <> 200 + _WD_Navigate($sSession, $url) + Logger('debug', 'Navigate HTTPRESULT: ' & $_WD_HTTPRESULT) +WEnd +$_WD_HTTPRESULT = 0 + +; Execute login workflow +If $input <> "basicauth" Then + $steps = StringSplit($input, '||',$STR_ENTIRESPLIT) + If IsArray($steps) Then + $nrOfSteps = UBound($steps)-1 + Logger('debug', 'Parsed ' & $nrOfSteps & ' steps') + For $i=1 to $nrOfSteps + $step = StringSplit($steps[$i],"::",$STR_ENTIRESPLIT) + If IsArray($step) Then + $action = $step[1] + $css = $step[2] + Logger('debug', 'Action ' & $i & ': ' & $action & ', CSS selector: ' & $css) + While $_WD_HTTPRESULT <> 200 + $element = _WD_WaitElement($sSession, $_WD_LOCATOR_ByCSSSelector,$css, Default,Default, BitOR($_WD_OPTION_Visible, $_WD_OPTION_Enabled)) + Logger('debug', 'Locate element ' & $css & ' -- HTTPRESULT: ' & $_WD_HTTPRESULT) + WEnd + $_WD_HTTPRESULT = 0 + Switch $action + Case 'c' + While $_WD_HTTPRESULT <> 200 + _WD_ElementAction($sSession, $element, 'click') + Logger('debug', 'Clicked element: ' & $css & ' -- HTTPRESULT: ' & $_WD_HTTPRESULT) + WEnd + Case 'v' + While $_WD_HTTPRESULT <> 200 + _WD_ElementAction($sSession, $element, 'value', $step[3]) + Logger('debug', 'Entered value: ' & $step[3] & ' into field: ' & $css & ' -- HTTPRESULT: ' & $_WD_HTTPRESULT) + WEnd + Case 's' + While $_WD_HTTPRESULT <> 200 + _WD_ElementAction($sSession, $element, 'value', $step[3]) + Logger('debug', 'Entered secret into field: ' & $css & ' -- HTTPRESULT: ' & $_WD_HTTPRESULT) + WEnd + Case 'o' + Logger('debug', "Looking up valid TOTP code...") + Logger('debug', "[TOTP_Lookup] Required seconds before TOTP expiry: " & $step[4]) + Logger('debug', "[TOTP_Lookup] TOTP JSON: " & $step[3]) + Logger('debug', "[TOTP_Lookup] Removing escape characters from TOTP JSON") + $j_totp = StringReplace($step[3],"\","") + Logger('debug', "[TOTP_Lookup] New TOTP JSON: " & $j_totp) + $totp = json_decode($j_totp) + Local $j = 0 + Local $totp_Code = 0 + While 1 + $currentUnixTime = _GetUnixTime() + $totp_UnixTime = json_get($totp, '[' & $j & '].UnixTime') + Logger('debug', '[TOTP_Lookup] TOTP [' & $j & '].UnixTime: ' & $totp_UnixTime) + $totp_Period = json_get($totp, '[' & $j & '].Period') + Logger('debug', '[TOTP_Lookup] TOTP [' & $j & '].Period: ' & $totp_Period) + If @error Then + Logger('info', "[TOTP_Lookup] Error during TOTP lookup") + ExitLoop + EndIf + Logger('debug', "[TOTP_Lookup] UTC start time for code as UnixTime: " & $totp_UnixTime & ", Code period: " & $totp_Period & ", current UnixTime: " & $currentUnixTime) + $totp_diff = $totp_UnixTime + $totp_Period - $currentUnixTime + If $totp_diff >= $step[4] Then + $totp_Code = String(json_get($totp, '[' & $j & '].Code')) + $codeLen = StringLen($totp_Code) + If $codeLen <> 6 Then + Logger('debug', 'TOTP with leading zeros parsed as: ' & $totp_Code & '. Adding leading zeros back.') + $zeros = '' + For $s = 1 To (6-$codeLen) + $zeros = $zeros & '0' + Next + $totp_Code = $zeros & $totp_Code + EndIf + Logger('debug', "Found valid TOTP code, expiring in " & $totp_diff & " seconds") + ExitLoop + ElseIf $totp_diff < 0 Then + Logger('debug', "[TOTP_Lookup] TOTP code is already expired. Diff: " & $totp_diff & ". Checking the next code.") + $j += 1 + Else + Logger('debug', "[TOTP_Lookup] TOTP code is closer to expiry than defined minimum " & $step[4] & " seconds. Diff: " & $totp_diff & ". Waiting " & $step[4] & " seconds before checking the next code.") + Sleep($step[4]*1000) + $j += 1 + EndIf + WEnd + + If $totp_Code = 0 Then + Logger('info', "Have not found valid TOTP code, exit.") + Exit + EndIf + + While $_WD_HTTPRESULT <> 200 + _WD_ElementAction($sSession, $element, 'value', $totp_Code) + Logger('debug', 'Entered TOTP code ' & $totp_Code & ' into field: ' & $css & ' -- HTTPRESULT: ' & $_WD_HTTPRESULT) + WEnd + EndSwitch + $_WD_HTTPRESULT = 0 + Else + Logger('info', 'Cannot parse step: ' & $step & ' -- Exit') + Exit + EndIf + Next + Else + Logger('info', 'Cannot parse selectors: ' & $input & ' -- Exit') + Exit + EndIf +EndIf + +; Enable user input +If $debug = 0 Then + _BlockInput($BI_ENABLE, Default) + Logger('debug', 'User input enabled') +EndIf + +FileClose($logfile) + +Func Logger($level, $msg) + $ts = _NowCalc() + if $level == "debug" And $debug = 1 Then + FileWriteLine($logfile, $ts & " -- DEBUG -- " & $msg) + ElseIf $level == "info" Then + FileWriteLine($logfile, $ts & " -- INFO -- " & $msg) + EndIf +EndFunc + +Func SetupGecko() + + _WD_Option('Driver', 'webdriver\geckodriver.exe') + _WD_Option('DriverParams', '--log ' & $loglevel) + _WD_Option('Port', 4444) + + ;this goes into "prefs":{} + ;Logger('debug','Disable devtools in Firefox') + ;Local $ff_preferences='' + + ;$ff_preferences&='"devtools.accessibility.enabled": false,' + ;$ff_preferences&='"devtools.accessibility.enabled": false,' + ;$ff_preferences&='"devtools.application.enabled": false,' + ;$ff_preferences&='"devtools.accessibility.enabled": false,' + ;$ff_preferences&='"devtools.application.enabled": false,' + ;$ff_preferences&='"devtools.chrome.enabled": false,' + ;$ff_preferences&='"devtools.command-button-errorcount.enabled": false,' + ;$ff_preferences&='"devtools.command-button-frames.enabled": false,' + ;$ff_preferences&='"devtools.command-button-measure.enabled": false,' + ;$ff_preferences&='"devtools.command-button-noautohide.enabled": false,' + ;$ff_preferences&='"devtools.command-button-pick.enabled": false,' + ;$ff_preferences&='"devtools.command-button-responsive.enabled": false,' + ;$ff_preferences&='"devtools.command-button-rulers.enabled": false,' + ;$ff_preferences&='"devtools.command-button-screenshot.enabled": false,' + ;$ff_preferences&='"devtools.command-button-splitconsole.enabled": false,' + ;$ff_preferences&='"devtools.custom-formatters.enabled": false,' + ;$ff_preferences&='"devtools.debugger.enabled": false,' + ;$ff_preferences&='"devtools.debugger.map-scopes-enabled": false,' + ;$ff_preferences&='"devtools.debugger.pretty-print-enabled": false,' + ;$ff_preferences&='"devtools.debugger.remote-enabled": false,' + ;$ff_preferences&='"devtools.debugger.ui.variables-sorting-enabled": false,' + ;$ff_preferences&='"devtools.dom.enabled": false,' + ;$ff_preferences&='"devtools.every-frame-target.enabled": false,' + ;$ff_preferences&='"devtools.inspector.chrome.three-pane-enabled": false,' + ;$ff_preferences&='"devtools.inspector.compatibility.enabled": false,' + ;$ff_preferences&='"devtools.inspector.enabled": false,' + ;$ff_preferences&='"devtools.inspector.inactive.css.enabled": false,' + ;$ff_preferences&='"devtools.inspector.ruleview.inline-compatibility-warning.enabled": false,' + ;$ff_preferences&='"devtools.inspector.three-pane-enabled": false,' + ;$ff_preferences&='"devtools.jsonview.enabled": false,' + ;$ff_preferences&='"devtools.markup.mutationBreakpoints.enabled": false,' + ;$ff_preferences&='"devtools.memory.enabled": false,' + ;$ff_preferences&='"devtools.netmonitor.enabled": false,' + ;$ff_preferences&='"devtools.overflow.debugging.enabled": false,' + ;$ff_preferences&='"devtools.performance.enabled": false,' + ;$ff_preferences&='"devtools.performance.recording.active-tab-view.enabled": false,' + ;$ff_preferences&='"devtools.responsive.leftAlignViewport.enabled": false,' + ;$ff_preferences&='"devtools.responsive.reloadNotification.enabled": false,' + ;$ff_preferences&='"devtools.responsive.touchSimulation.enabled": false,' + ;$ff_preferences&='"devtools.screenshot.audio.enabled": false,' + ;$ff_preferences&='"devtools.screenshot.clipboard.enabled": false,' + ;$ff_preferences&='"devtools.serviceWorkers.testing.enabled": false,' + ;$ff_preferences&='"devtools.source-map.client-service.enabled": false,' + ;$ff_preferences&='"devtools.storage.enabled": false,' + ;$ff_preferences&='"devtools.storage.extensionStorage.enabled": false,' + ;$ff_preferences&='"devtools.styleeditor.autocompletion-enabled": false,' + ;$ff_preferences&='"devtools.styleeditor.enabled": false,' + ;$ff_preferences&='"devtools.target-switching.server.enabled": false,' + ;$ff_preferences&='"devtools.toolbox.splitconsoleEnabled": false,' + ;$ff_preferences&='"devtools.webconsole.enabled": false' + + ;$sDesiredCapabilities = '{"capabilities": {"alwaysMatch": {"moz:firefoxOptions":{"args": ["-kiosk"], "prefs": {' & $ff_preferences & '}},"browserName": "firefox", "acceptInsecureCerts":true}}}' + ;ElseIf $mode == "normal" Then + ; $sDesiredCapabilities = '{"capabilities": {"alwaysMatch": {"moz:firefoxOptions":{"prefs": {' & $ff_preferences & '}},"browserName": "firefox", "acceptInsecureCerts":true}}}' + ;EndIf + +EndFunc ;==>SetupGecko + +Func SetupChrome() + _WD_Option('Driver', 'webdriver\chromedriver.exe') + _WD_Option('Port', 9515) + _WD_Option('DriverParams', '--log-path="' & @UserProfileDir & '\AppData\Roaming\OneIdentity\OI-SG-RemoteApp-Launcher-Orchestration\chromedriver.log" --log-level=' & StringUpper($loglevel) & ' --readable-timestamp') + + ; Add chromeOption to not offer saving credentials + + ;if $mode=="kiosk" Then + ; $sDesiredCapabilities = '{"capabilities": {"alwaysMatch": {"goog:chromeOptions": {"args": ["--kiosk"], "w3c": true, "excludeSwitches": [ "enable-automation"], "prefs": { "credentials_enable_service": false, "profile": { "password_manager_enabled": false}}} }}}' + ;ElseIf $mode == "normal" Then + ; $sDesiredCapabilities = '{"capabilities": {"alwaysMatch": {"goog:chromeOptions": {"w3c": true, "excludeSwitches": [ "enable-automation"], "prefs": { "credentials_enable_service": false, "profile": { "password_manager_enabled": false}}} }}}' + ;EndIf + + +EndFunc ;==>SetupChrome + +Func SetupEdge() + _WD_Option('Driver', 'webdriver\msedgedriver.exe') + _WD_Option('Port', 9515) + _WD_Option('DriverParams', '--verbose --log-path="' & @ScriptDir & '\msedge.log"') + + ;$sDesiredCapabilities = '{"capabilities": {"alwaysMatch": {"ms:edgeOptions": {"excludeSwitches": [ "enable-automation"]}}}}' +EndFunc ;==>SetupEdge + + + + + diff --git a/RDP Applications/AutoIt/Microsoft SQL Server Management Studio/sqlstudio.au3 b/RDP Applications/AutoIt/Microsoft SQL Server Management Studio/sqlstudio.au3 index 724adb5..02c97ef 100644 --- a/RDP Applications/AutoIt/Microsoft SQL Server Management Studio/sqlstudio.au3 +++ b/RDP Applications/AutoIt/Microsoft SQL Server Management Studio/sqlstudio.au3 @@ -1,23 +1,55 @@ ; ONLY FOR DEMO USE -; Based on the OI SQL Developer launcher: +; Initial version based on the OI SQL Developer launcher: ; https://github.com/OneIdentity/SafeguardAutomation/blob/master/AutoIt/SQLDeveloper/SQLDeveloper_20.4.1.au3 -; cmd line arguments for lacunher: OI-SG-RemoteApp-Launcher.exe --cmd \sqlstudio.exe --args {username} {password} {asset} +; Safeguard Launcher Application Command Line parameters: --cmd \sqlstudio.exe --args {username} {password} {asset} [sps ip] +; Tested with SSMS v18.4: --cmd "\sqlstudio.exe" --args ssmsfolder {username} {password} {asset} 192.168.1.1 +; Make sure you configure the environment variable on the RDS host, for example C:\Program Files (x86)\Microsoft SQL Server Management Studio 18\Common7\IDE -Global $apppath = "" -Global $appfolder = "" -Global $account = $CmdLine[1] -Global $password = $CmdLine[2] -Global $asset = $CmdLine[3] +#include +#include -$apppath = "C:\Program Files (x86)\Microsoft SQL Server Management Studio 18\Common7\IDE\Ssms.exe" -$appfolder = "C:\Program Files (x86)\Microsoft SQL Server Management Studio 18\Common7\IDE" +Global $debug = $CmdLine[1] +Global $ssms_folder_env_var = $CmdLine[2] +Global $account = $CmdLine[3] +Global $password = $CmdLine[4] +Global $asset = $CmdLine[5] +If $CmdLine[0] = 6 Then + Global $sps = $CmdLine[6] +Else + Global $sps = "" +EndIf +Global $loglevel = '' +If $debug Then + $loglevel = 'debug' +Else + $loglevel = 'info' +EndIf +$logfile = FileOpen(@UserProfileDir & "\AppData\Roaming\OneIdentity\OI-SG-RemoteApp-Launcher-Orchestration\sqlstudio.log", $FO_APPEND + $FO_CREATEPATH) + +Global $ssms_folder = EnvGet($ssms_folder_env_var) +Global $apppath = $ssms_folder & "\Ssms.exe" +Global $appfolder = $ssms_folder Global $loginwintitle = "Connect to Server" +; Define server and login values for direct connection or via SPS +If $sps = "" Then + Global $serverName = $asset + Global $login = $account +Else + Global $serverName = $sps + Global $login = $account & "%" & $asset +EndIf + +Logger('debug', "appath: " & $apppath) +Logger('debug', "appfolder: " & $appfolder) +Logger('debug', "serverName: " & $serverName) +Logger('debug', "login: " & $login) + Start($apppath, $appfolder) -Login($asset, $account, $password) +Login($serverName, $login, $password) -Func Login($asst, $acct, $passwd) +Func Login($serverInstance, $userName, $passwd) ; Wait for login window and get window handle when ready. Local $handle = WinWaitActive($loginwintitle) @@ -38,11 +70,11 @@ Func Login($asst, $acct, $passwd) ; Disable control and set servername ControlDisable($handle, "", "[NAME:serverInstance]") - ControlSetText($handle, "", "[NAME:serverInstance]", $asset) + ControlSetText($handle, "", "[NAME:serverInstance]", $serverInstance) ; Disable control and set username ControlDisable($handle, "", "[NAME:userName]") - ControlSetText($handle, "", "[NAME:userName]", $account) + ControlSetText($handle, "", "[NAME:userName]", $userName) ; Disable control and set password ControlDisable($handle, "", "[NAME:password]") @@ -54,4 +86,13 @@ EndFunc Func Start($path, $folder) Run($path, $folder, @SW_MAXIMIZE) +EndFunc + +Func Logger($level, $msg) + $ts = _NowCalc() + if $level == "debug" And $debug = 1 Then + FileWriteLine($logfile, $ts & " -- " & $msg) + ElseIf $level == "info" Then + FileWriteLine($logfile, $ts & " -- " & $msg) + EndIf EndFunc \ No newline at end of file diff --git a/RDP Applications/AutoIt/web_generic/web_generic.au3 b/RDP Applications/AutoIt/web_generic/web_generic.au3 deleted file mode 100644 index a5644a6..0000000 --- a/RDP Applications/AutoIt/web_generic/web_generic.au3 +++ /dev/null @@ -1,231 +0,0 @@ -; ONLY FOR DEMO USE -; -; Compile with Aut2exe to ensure the include files are compiled too -; -; cmd line arguments for launcher: OI-SG-RemoteApp-Launcher.exe --cmd \web_generic.exe --args " targetUrl v::css1::{username}||c::css2||c::css3||s::css4::{password}||c::css4 {asset}" -; -; Altough the code supports Firefox (needs geckodriver.exe) and Edge (needs msedgedriver.exe) too: -; - Edge has not been tested at all -; - It is not reliable with Firefox. Also, it should disable devtools but in the tests not all of them got disabled and users can re-enable them at this point. -; -; The code supports any number of selectors, types of "v" as value or "c" as click or "s" as secret which is not logged, separated by "||". -; Input parameters: -; The actual action is defined with "::" separator. -; Sample: "v::css1::username||c::css2||c::css3||s::css4::password||c::css4" -; -; The code disables user input when not running in debug mode - - -Opt("TrayAutoPause", 0) -Opt("TrayIconDebug", 0) - -#include -#include - -#include 'webdriver\wd_core.au3' -#include 'webdriver\wd_helper.au3' - -#include "webdriver\BlockInputEX.au3" - -Local $debug = $CmdLine[1] -Local $browser = $CmdLine[2] -Local $target = $CmdLine[3] -Local $input = $CmdLine[4] -Local $asset = $CmdLine[5] ; Asset will not be used as cloud targets may be accessible on a different name than the Asset Name / Network Address in SPP, however the {asset} parameter must be given for the Launcher. -Local $loglevel = '' - -If $debug Then - $loglevel = 'debug' -Else - $loglevel = 'info' -EndIf -$logfile = FileOpen(@UserProfileDir & "\AppData\Roaming\OneIdentity\OI-SG-RemoteApp-Launcher-Orchestration\web_generic.log", $FO_APPEND + $FO_CREATEPATH) -Logger('info', "Starting web orchestration with loglevel:" & $loglevel) -Logger('debug', "browser=" & $browser) - -Local $sDesiredCapabilities, $sSession - -; We use Chrome in this sample. For other browsers lookup the functions at the end of the script. -; Note: Make sure chromedriver is up-to-date. Chrome is updating frequently, chromedriver should have the matching version. -Switch $browser - Case 'chrome' - SetupChrome() - Case 'firefox' - SetupGecko() - Case 'edge' - SetupEdge() -EndSwitch - -; Disable user input -If $debug = 0 Then - _BlockInput($BI_DISABLE) - Logger('debug', 'User input disabled') -EndIf - -_WD_Startup() - -; Create session -Logger('debug', 'Creating session with capabilities: ' & $sDesiredCapabilities) -While $_WD_HTTPRESULT <> 200 - $sSession = _WD_CreateSession($sDesiredCapabilities) - Logger('debug', 'HTTPRESULT: ' & $_WD_HTTPRESULT) -WEnd -$_WD_HTTPRESULT = 0 -Logger('debug', 'Session: ' & $sSession) - -; Hide the WebDriver console -_WD_ConsoleVisible(false) - -; Navigate to asset website -$url= 'https://' & $target -While $_WD_HTTPRESULT <> 200 - _WD_Navigate($sSession, $url) - Logger('debug', 'Navigate HTTPRESULT: ' & $_WD_HTTPRESULT) -WEnd -$_WD_HTTPRESULT = 0 - -; Execute login workflow -$steps = StringSplit($input, '||',$STR_ENTIRESPLIT) -If IsArray($steps) Then - $nrOfSteps = UBound($steps)-1 - Logger('debug', 'Parsed ' & $nrOfSteps & ' steps') - For $i=1 to $nrOfSteps - $step = StringSplit($steps[$i],"::",$STR_ENTIRESPLIT) - If IsArray($step) Then - $action = $step[1] - $css = $step[2] - Logger('debug', 'Action ' & $i & ': ' & $action & ', CSS selector: ' & $css) - While $_WD_HTTPRESULT <> 200 - $element = _WD_WaitElement($sSession, $_WD_LOCATOR_ByCSSSelector,$css, Default,Default, BitOR($_WD_OPTION_Visible, $_WD_OPTION_Enabled)) - Logger('debug', 'Locate element ' & $css & ' -- HTTPRESULT: ' & $_WD_HTTPRESULT) - WEnd - $_WD_HTTPRESULT = 0 - Switch $action - Case 'c' - While $_WD_HTTPRESULT <> 200 - _WD_ElementAction($sSession, $element, 'click') - Logger('debug', 'Clicked element: ' & $css & ' -- HTTPRESULT: ' & $_WD_HTTPRESULT) - WEnd - Case 'v' - While $_WD_HTTPRESULT <> 200 - _WD_ElementAction($sSession, $element, 'value', $step[3]) - Logger('debug', 'Entered value: ' & $step[3] & ' into field: ' & $css & ' -- HTTPRESULT: ' & $_WD_HTTPRESULT) - WEnd - Case 's' - While $_WD_HTTPRESULT <> 200 - _WD_ElementAction($sSession, $element, 'value', $step[3]) - Logger('debug', 'Entered secret into field: ' & $css & ' -- HTTPRESULT: ' & $_WD_HTTPRESULT) - WEnd - EndSwitch - $_WD_HTTPRESULT = 0 - Else - Logger('info', 'Cannot parse step: ' & $step & ' -- Exit') - Exit - EndIf - Next -Else - Logger('info', 'Cannot parse selectors: ' & $input & ' -- Exit') - Exit -EndIf - -_BlockInput($BI_ENABLE, Default) -Logger('debug', 'User input enabled') - -FileClose($logfile) - -Func Logger($level, $msg) - $ts = _NowCalc() - if $level == "debug" And $debug = 1 Then - FileWriteLine($logfile, $ts & " -- " & $msg) - ElseIf $level == "info" Then - FileWriteLine($logfile, $ts & " -- " & $msg) - EndIf -EndFunc - -Func SetupGecko() - - _WD_Option('Driver', 'webdriver\geckodriver.exe') - _WD_Option('DriverParams', '--log ' & $loglevel) - _WD_Option('Port', 4444) - - ;this goes into "prefs":{} - Logger('debug','Disable devtools in Firefox') - Local $ff_preferences='' - - $ff_preferences&='"devtools.accessibility.enabled": false,' - $ff_preferences&='"devtools.accessibility.enabled": false,' - $ff_preferences&='"devtools.application.enabled": false,' - $ff_preferences&='"devtools.accessibility.enabled": false,' - $ff_preferences&='"devtools.application.enabled": false,' - $ff_preferences&='"devtools.chrome.enabled": false,' - $ff_preferences&='"devtools.command-button-errorcount.enabled": false,' - $ff_preferences&='"devtools.command-button-frames.enabled": false,' - $ff_preferences&='"devtools.command-button-measure.enabled": false,' - $ff_preferences&='"devtools.command-button-noautohide.enabled": false,' - $ff_preferences&='"devtools.command-button-pick.enabled": false,' - $ff_preferences&='"devtools.command-button-responsive.enabled": false,' - $ff_preferences&='"devtools.command-button-rulers.enabled": false,' - $ff_preferences&='"devtools.command-button-screenshot.enabled": false,' - $ff_preferences&='"devtools.command-button-splitconsole.enabled": false,' - $ff_preferences&='"devtools.custom-formatters.enabled": false,' - $ff_preferences&='"devtools.debugger.enabled": false,' - $ff_preferences&='"devtools.debugger.map-scopes-enabled": false,' - $ff_preferences&='"devtools.debugger.pretty-print-enabled": false,' - $ff_preferences&='"devtools.debugger.remote-enabled": false,' - $ff_preferences&='"devtools.debugger.ui.variables-sorting-enabled": false,' - $ff_preferences&='"devtools.dom.enabled": false,' - $ff_preferences&='"devtools.every-frame-target.enabled": false,' - $ff_preferences&='"devtools.inspector.chrome.three-pane-enabled": false,' - $ff_preferences&='"devtools.inspector.compatibility.enabled": false,' - $ff_preferences&='"devtools.inspector.enabled": false,' - $ff_preferences&='"devtools.inspector.inactive.css.enabled": false,' - $ff_preferences&='"devtools.inspector.ruleview.inline-compatibility-warning.enabled": false,' - $ff_preferences&='"devtools.inspector.three-pane-enabled": false,' - $ff_preferences&='"devtools.jsonview.enabled": false,' - $ff_preferences&='"devtools.markup.mutationBreakpoints.enabled": false,' - $ff_preferences&='"devtools.memory.enabled": false,' - $ff_preferences&='"devtools.netmonitor.enabled": false,' - $ff_preferences&='"devtools.overflow.debugging.enabled": false,' - $ff_preferences&='"devtools.performance.enabled": false,' - $ff_preferences&='"devtools.performance.recording.active-tab-view.enabled": false,' - $ff_preferences&='"devtools.responsive.leftAlignViewport.enabled": false,' - $ff_preferences&='"devtools.responsive.reloadNotification.enabled": false,' - $ff_preferences&='"devtools.responsive.touchSimulation.enabled": false,' - $ff_preferences&='"devtools.screenshot.audio.enabled": false,' - $ff_preferences&='"devtools.screenshot.clipboard.enabled": false,' - $ff_preferences&='"devtools.serviceWorkers.testing.enabled": false,' - $ff_preferences&='"devtools.source-map.client-service.enabled": false,' - $ff_preferences&='"devtools.storage.enabled": false,' - $ff_preferences&='"devtools.storage.extensionStorage.enabled": false,' - $ff_preferences&='"devtools.styleeditor.autocompletion-enabled": false,' - $ff_preferences&='"devtools.styleeditor.enabled": false,' - $ff_preferences&='"devtools.target-switching.server.enabled": false,' - $ff_preferences&='"devtools.toolbox.splitconsoleEnabled": false,' - $ff_preferences&='"devtools.webconsole.enabled": false' - $sDesiredCapabilities = '{"capabilities": {"alwaysMatch": {"moz:firefoxOptions":{"prefs": {' & $ff_preferences & '}},"browserName": "firefox", "acceptInsecureCerts":true}}}' - Logger('debug',"Capabilities: " &$sDesiredCapabilities) - -EndFunc ;==>SetupGecko - -Func SetupChrome() - _WD_Option('Driver', 'webdriver\chromedriver.exe') - _WD_Option('Port', 9515) - _WD_Option('DriverParams', '--log-path="' & @UserProfileDir & '\AppData\Roaming\OneIdentity\OI-SG-RemoteApp-Launcher-Orchestration\chromedriver.log" --log-level=' & StringUpper($loglevel) & ' --readable-timestamp') - - ; Add chromeOption to not offer saving credentials - $sDesiredCapabilities = '{"capabilities": {"alwaysMatch": {"goog:chromeOptions": {"w3c": true, "excludeSwitches": [ "enable-automation"], "prefs": { "credentials_enable_service": false, "profile": { "password_manager_enabled": false}}} }}}' - -EndFunc ;==>SetupChrome - -Func SetupEdge() - _WD_Option('Driver', 'webdriver\msedgedriver.exe') - _WD_Option('Port', 9515) - _WD_Option('DriverParams', '--verbose --log-path="' & @ScriptDir & '\msedge.log"') - - $sDesiredCapabilities = '{"capabilities": {"alwaysMatch": {"ms:edgeOptions": {"excludeSwitches": [ "enable-automation"]}}}}' -EndFunc ;==>SetupEdge - - - - - diff --git a/RDP Applications/AutoIt/web_generic/webdriver/chromedriver.exe b/RDP Applications/AutoIt/web_generic/webdriver/chromedriver.exe deleted file mode 100644 index 1b006de..0000000 Binary files a/RDP Applications/AutoIt/web_generic/webdriver/chromedriver.exe and /dev/null differ diff --git a/RDP Applications/AutoIt/web_generic/webdriver/geckodriver.exe b/RDP Applications/AutoIt/web_generic/webdriver/geckodriver.exe deleted file mode 100644 index fec8b51..0000000 Binary files a/RDP Applications/AutoIt/web_generic/webdriver/geckodriver.exe and /dev/null differ diff --git a/RDP Applications/Command Line Examples/AppsSample-7.0.csv b/RDP Applications/Command Line Examples/AppsSample-7.0.csv index 3838160..a0ea66f 100644 --- a/RDP Applications/Command Line Examples/AppsSample-7.0.csv +++ b/RDP Applications/Command Line Examples/AppsSample-7.0.csv @@ -1,9 +1,16 @@ Application,Tested Safeguard Version,CMD Executable,Args Parameter SQL Studio,7.0,--cmd "C:\AutoIT\sqlstudio.exe",--args "{username} {password} {asset}" +SQL Studio via SPS,7.1,--cmd "C:\AutoIT\sqlstudio_v2.exe",--args "1 ssmsfolder {username} {password} {asset} 192.168.1.1" DBeaver MySQL,7.0,--cmd "C:\Program Files\DBeaver\dbeaver.exe",--args "-con name=SG-MySQL-autologon|driver=mysql|user={username}|password={password}|host={asset}" DBeaver MSSQL,7.0,--cmd "C:\Program Files\DBeaver\dbeaver.exe",--args "-con name=SG-MSSQL-autologon|driver=mssql_ms|user={username}|password={password}|database=master|host={asset}" DBeaver Oracle,7.0,--cmd "C:\Program Files\DBeaver\dbeaver.exe",--args "con name=SG-Oracle-autologon|driver=oracle_thin|url=jdbc:oracle:thin:@{asset}:1521:oracle|user={username}|password={password}" -Azure Portal,7.0,--cmd "C:\AutoIT\web_generic_3.2.exe",--args "1 chrome portal.azure.com v::#i0116::{username}||c::#idSIButton9||s::#i0118::{password}||c::#idSIButton9||c::#idBtn_Back {asset}" -Splunk,7.0,--cmd "C:\AutoIT\web_generic_2.0.exe",--args "1 {username} {password} {asset} splunk.example.com:8000 #username #password #password input.splButton-primary.btn.btn-primary" -SPS default local user,7.0,--cmd "C:\AutoIT\web_generic_2.0.exe",--args "1 {username} {password} {asset} sps.example.com #local-username #local-password #password button.primary" -AWS non-root,7.0,--cmd "C:\AutoIT\web_generic_2.0.exe",--args "1 {username} {password} {asset} signin.aws.amazon.com/console #resolving_input #password #signin_button #next_button" +[Deprecated] Azure Portal,7.0,--cmd "C:\AutoIT\web_generic_3.2.exe",--args "1 chrome portal.azure.com v::#i0116::{username}||c::#idSIButton9||s::#i0118::{password}||c::#idSIButton9||c::#idBtn_Back {asset}" +[Deprecated] Azure Portal with TOTP,7.2,--cmd "C:\AutoIT\web_generic_3.3.exe" --args "0 c portal.azure.com v::#i0116::{username}||c::#idSIButton9||s::#i0118::{password}||c::#idSIButton9||o::#idTxtBx_SAOTCC_OTC::{Target.TotpCodes}::5||c::#idSubmit_SAOTCC_Continue||c::#idBtn_Back {asset}" +[Deprecated] Splunk,7.0,--cmd "C:\AutoIT\web_generic_2.0.exe",--args "1 {username} {password} {asset} splunk.example.com:8000 #username #password #password input.splButton-primary.btn.btn-primary" +[Deprecated] Splunk,7.0,--cmd "C:\AutoIT\web_generic_3.2.exe",--args "1 chrome splunk.oneidentity.work:443 v::#username::{username}||s::#password::{password}||c::input.splButton-primary.btn.btn-primary {asset}" +[Deprecated] SPS default local user,7.0,--cmd "C:\AutoIT\web_generic_2.0.exe",--args "1 {username} {password} {asset} sps.example.com #local-username #local-password #password button.primary" +[Deprecated] AWS non-root,7.0,--cmd "C:\AutoIT\web_generic_2.0.exe",--args "1 {username} {password} {asset} signin.aws.amazon.com/console #resolving_input #password #signin_button #next_button" +[Deprecated] AWS (via Starling) non-root with TOTP,7.2,--cmd "C:\AutoIT\web_generic_3.4.exe" --args "0 c {asset}.signin.aws.amazon.com/console v::#username::{username}||s::#password::{password}||c::#signin_button||o::#mfacode::{Target.TotpCodes}::3||c::#submitMfa_button" +[Deprecated] AWS root with TOTP,7.2,--cmd "C:\AutoIT\web_generic_3.4.exe" --args "0 c signin.aws.amazon.com/console v::#resolving_input::{username}||c::#next_button||s::#password::{password}||c::#signin_button||o::#mfaCode::{Target.TotpCodes}::3||c::#mfa_submit_button" +signin_button #next_button" +[Deprecated] Active Roles WebAdmin Basic Auth,7.3,--cmd "C:\AutoIT\web_generic_3.5.exe" --args "0 c {username}@{Target.AccountDomainName}:{password}@{Target.AssetNetworkAddress}/ARWebAdmin basicauth" --enable-debug diff --git a/RDP Applications/Go chromedp/webgenericcdp/README.md b/RDP Applications/Go chromedp/webgenericcdp/README.md new file mode 100644 index 0000000..07bfbcb --- /dev/null +++ b/RDP Applications/Go chromedp/webgenericcdp/README.md @@ -0,0 +1,60 @@ +# Webgenericcdp - Generic web automation script for Safeguard based on Go/chromedp + +Webgenericcdp works only with OI-SG-RemoteApp-Launcher version 3.0.1 or later, together with the --use-stdin parameter/ This restriction ensures that no sensitive information is visible in command line parameters. + +## App publishing + +When the --use-stdin parameter is used, the value of the --args parameter is also passed by the RemoteApp-Launcher to the application set in --cmd. + +Webgenericcdp expects the path of its configuration file given in --args, optionally with the -debug switch. + +Sample RemoteApp publishing parameter configuration: + +```--use-stdin --args "C:\_RApp\webgenericcdp_Entra_with_MFA_incognito.conf -debug" --cmd "c:\_RApp\webgenericcdp.exe"``` + +## Configuring webgenericcdp + +Sample configuration file including the configuration parameters' description is shared together with webgenericcdp. + +Settings which are uncommented or shown without a default value in the sample confgiuration are mandatory. + +The ```loginActions``` setting is backwards compatible with the syntax used at [AutoIt/web_generic](https://github.com/OneIdentity/SafeguardAutomation/tree/master/RDP%20Applications/AutoIt/web_generic) + +The ```loginActions``` setting supports concatenated input values, like UPN or down-level logon names, which is built of multiple key-value pairs received from Safeguard. + +Webgenericcdp by default waits for the next element ```loginActions``` being loaded by the browser, however it is not reliable on all websites. To overcome that, ```browserInputDelay``` can be configured which pauses the execution before performing the next action. + +If ```basicAuthUsername``` is configured, ```loginActions``` is ignored and the configured web application is accessed using basic authentication. + +## Troubleshooting + +Logs are written into the following folder of the RDP host account: %AppData%\OneIdentity\OI-SG-RemoteApp-Launcher-Orchestration + +Debug logging for webgenericcdp can be enabled via the app publishing configuration using the -debug switch within --args. + +Debug logging for chromedp can be enabled the ```chromedp_logging``` setting within the configuration file. + +If the RemoteApp-Launcher console window does not close it means that the script did not find all elements on the page and it's still retrying. + +### Other issues + +#### Webgenericcdp detected as trojan + +In case of running lots of tests within a short period of time, Windows Security may flag webgenericcdp as Trojan. Symptom is that the RemoteApp-Launcher window closes and there is no any log from webgenericcdp. The following event is visible in the OI-SG-RemoteApp-Launcher log: ```Error occurred while trying to launch application: Error occurred while trying to launch process. Got error: Operation did not complete successfully because the file contains a virus or potentially unwanted software. (os error 225)``` + +Open ```Windows Security``` and look for ```Virus and threat protection``` + +2025-06-03 09_55_38-winserver oneidentity demo - SPS + +Then Allow webgenericcdp via Windows Security + +2025-06-03 09_56_38-winserver oneidentity demo - SPS + +## Known issues + +* ```browser_incognito=true``` does not work when using Edge +* ```chromedp_logging=info``` does not work + + + + diff --git a/RDP Applications/Go chromedp/webgenericcdp/webgenericcdp.go b/RDP Applications/Go chromedp/webgenericcdp/webgenericcdp.go new file mode 100644 index 0000000..41f0efd --- /dev/null +++ b/RDP Applications/Go chromedp/webgenericcdp/webgenericcdp.go @@ -0,0 +1,579 @@ +// Author: Viktor Varga (One Identity). Certain code snippets are by Ferenc Sipos (One Identity) or Richard Hosgood (One Identity). +// Use with the OI-RemoteDesktopLauncher 3.0.1 or later: --use-stdin --args "\webgenericcdp_webapp.conf -debug" --cmd "\webgenericcdp.exe" + +package main + +// Importing packages needed by the program +import ( + // Standard library packages + "bufio" + "context" + "encoding/json" + "errors" + "fmt" + "log" + "log/slog" + "os" + "regexp" + "strconv" + "strings" + "time" + + "github.com/google/uuid" + + // Driver to talk to Chrome-based browsers leveraging the + // Chrome DevTools protocol + "github.com/chromedp/chromedp" + "github.com/chromedp/chromedp/kb" +) + +type Config struct { + dumpStdinToLog bool + chromedp_logging string + url string + browser string + loginActions string + splitCharacters string + browserInputDelay int + browser_incognito bool + browser_insecure bool + browser_kiosk bool + user_data_dir string + basicAuthUsername string +} + +func defaultConfig() Config { + return Config{ + dumpStdinToLog: false, // WARNING, this contains the clear-text password + chromedp_logging: "error", // error|log|debug + //url //has no default + browser: "chrome", // Must be chrome or edge + //loginActions //has no default + splitCharacters: "\\@", // List of characters which may be used on concatenated values like UPN or down-level logon name + browserInputDelay: 0, // If set (in milliseconds), the code does not wait until the element is presented by the browser, but perfoms the next action when the configured delay passed + browser_incognito: true, + browser_insecure: false, // Ignore certificate errors + browser_kiosk: false, + //user_data_dir //has no default + basicAuthUsername: "false", + } +} + +func main() { + + // Read input from STDIN + scanner := bufio.NewScanner(os.Stdin) + + var launcherStdinJSON string + for scanner.Scan() { + launcherStdinJSON = scanner.Text() + } + + err := scanner.Err() + if err != nil { + fmt.Println(err.Error()) + _, err := fmt.Scanf("%s") + if err != nil { + fmt.Println("Error occured while reading STDIN.") + fmt.Println("The webgenericcdp application will close in 60 seconds..") + time.Sleep(time.Duration(60) * time.Second) + os.Exit(1) + } + } + + // Parse JSON input + var launcherStdin map[string]interface{} + json.Unmarshal([]byte(launcherStdinJSON), &launcherStdin) + + configFile, debug := strings.CutSuffix(launcherStdin["cli_args"].(string), " -debug") + + // Initialize log file + userProfileDir := os.Getenv("USERPROFILE") + logDir := userProfileDir + "\\AppData\\Roaming\\OneIdentity\\OI-SG-RemoteApp-Launcher-Orchestration" + if _, err := os.Stat(logDir); errors.Is(err, os.ErrNotExist) { + err := os.Mkdir(logDir, os.ModePerm) + if err != nil { + fmt.Println("Cannot create log directory: " + logDir) + fmt.Println("The webgenericcdp application will close in 60 seconds..") + time.Sleep(time.Duration(60) * time.Second) + os.Exit(1) + } + } + + f, err := os.OpenFile(logDir+"\\webgenericcdp_"+time.Now().Format(time.DateOnly)+".log", os.O_APPEND|os.O_CREATE, 0600) + if err != nil { + fmt.Println(err) + fmt.Println("Cannot create or open log file.") + fmt.Println("The webgenericcdp application will close in 60 seconds..") + _, err := fmt.Scanf("%s") + if err != nil { + defer f.Close() + time.Sleep(time.Duration(60) * time.Second) + os.Exit(1) + } + } + defer f.Close() + + uuid := uuid.New().String() + var logLevel = new(slog.LevelVar) + logger := slog.NewTextHandler(f, &slog.HandlerOptions{Level: logLevel}) + slog.SetDefault(slog.New(logger)) + + slog.Info("Starting webgenericcdp..", "sessionid", uuid) + if debug { + logLevel.Set(slog.LevelDebug) + slog.Debug("Loglevel set to Debug", "sessionid", uuid) + } else { + logLevel.Set(slog.LevelInfo) + } + + slog.Debug("Config file path: "+configFile, "sessionid", uuid) + + config := defaultConfig() + + // Read configuration from file + readFile, err := os.Open(configFile) + if err != nil { + slog.Error("Error occured while opening config file: "+launcherStdin["cli_args"].(string), "sessionid", uuid) + slog.Error("Error: "+err.Error(), "sessionid", uuid) + os.Exit(1) + } + fileScanner := bufio.NewScanner(readFile) + + fileScanner.Split(bufio.ScanLines) + + for fileScanner.Scan() { + if !strings.HasPrefix(fileScanner.Text(), "#") && fileScanner.Text() != "" && strings.TrimSpace(fileScanner.Text()) != "" { + slog.Debug("Reading configuration file", "config", fileScanner.Text(), "sessionid", uuid) + switch strings.Split(fileScanner.Text(), "=")[0] { + case "dumpStdinToLog": + config.dumpStdinToLog, err = strconv.ParseBool(strings.Split(fileScanner.Text(), "=")[1]) + if err != nil { + slog.Error("Error occured while parsing configuration: "+strings.Split(fileScanner.Text(), "=")[1]+"to boolean. Accepted string values: \"1\", \"t\", \"T\", \"TRUE\", \"true\", \"True\", \"0\", \"f\", \"F\", \"FALSE\", \"false\", \"False\"", "sessionid", uuid) + slog.Error("Error: "+err.Error(), "sessionid", uuid) + os.Exit(1) + } + case "chromedp_logging": + config.chromedp_logging = strings.Split(fileScanner.Text(), "=")[1] + case "url": + config.url = strings.Split(fileScanner.Text(), "=")[1] + case "browser": + config.browser = strings.Split(fileScanner.Text(), "=")[1] + case "loginActions": + config.loginActions = strings.Split(fileScanner.Text(), "=")[1] + case "splitCharacters": + _, splitChars, _ := strings.Cut(fileScanner.Text(), "=") + config.splitCharacters = splitChars + case "browserInputDelay": + config.browserInputDelay, err = strconv.Atoi(strings.Split(fileScanner.Text(), "=")[1]) + if err != nil { + slog.Error("Error occured while parsing configuration: "+strings.Split(fileScanner.Text(), "=")[1]+"to int.", "sessionid", uuid) + slog.Error("Error: "+err.Error(), "sessionid", uuid) + os.Exit(1) + } + case "browser_incognito": + config.browser_incognito, err = strconv.ParseBool(strings.Split(fileScanner.Text(), "=")[1]) + if err != nil { + slog.Error("Error occured while parsing configuration: "+strings.Split(fileScanner.Text(), "=")[1]+"to boolean. Accepted string values: \"1\", \"t\", \"T\", \"TRUE\", \"true\", \"True\", \"0\", \"f\", \"F\", \"FALSE\", \"false\", \"False\"", "sessionid", uuid) + slog.Error("Error: "+err.Error(), "sessionid", uuid) + os.Exit(1) + } + case "browser_insecure": + config.browser_insecure, err = strconv.ParseBool(strings.Split(fileScanner.Text(), "=")[1]) + if err != nil { + slog.Error("Error occured while parsing configuration: "+strings.Split(fileScanner.Text(), "=")[1]+"to boolean. Accepted string values: \"1\", \"t\", \"T\", \"TRUE\", \"true\", \"True\", \"0\", \"f\", \"F\", \"FALSE\", \"false\", \"False\"", "sessionid", uuid) + slog.Error("Error: "+err.Error(), "sessionid", uuid) + os.Exit(1) + } + case "browser_kiosk": + config.browser_kiosk, err = strconv.ParseBool(strings.Split(fileScanner.Text(), "=")[1]) + if err != nil { + slog.Error("Error occured while parsing configuration: "+strings.Split(fileScanner.Text(), "=")[1]+"to boolean. Accepted string values: \"1\", \"t\", \"T\", \"TRUE\", \"true\", \"True\", \"0\", \"f\", \"F\", \"FALSE\", \"false\", \"False\"", "sessionid", uuid) + slog.Error("Error: "+err.Error(), "sessionid", uuid) + os.Exit(1) + } + case "user_data_dir": + config.user_data_dir = strings.Split(fileScanner.Text(), "=")[1] + case "basicAuthUsername": + config.basicAuthUsername = strings.Split(fileScanner.Text(), "=")[1] + default: + slog.Error("Unknown configuration name: "+strings.Split(fileScanner.Text(), "=")[0], "sessionid", uuid) + os.Exit(1) + } + } + } + + readFile.Close() + + // Is there anything missing from config? + if config == (Config{}) { + slog.Error("Something is missing from the configuration. Config (including default values):", "sessionid", uuid) + configDump, err := json.Marshal(config) + if err != nil { + slog.Error("Can't convert config struct into JSON") + os.Exit(1) + } + slog.Error(string(configDump), "sessionid", uuid) + os.Exit(1) + } + + if config.dumpStdinToLog { + slog.Debug("STDIN: "+launcherStdinJSON, "sessionid", uuid) + } + + slog.Debug("Setting up browser options", "sessionid", uuid) + opts := append( + chromedp.DefaultExecAllocatorOptions[:], + chromedp.Flag("headless", false), + chromedp.Flag("enable-automation", false), + chromedp.Flag("hide-scrollbars", false), + chromedp.Flag("mute-audio", false), + chromedp.Flag("disable-infobars", true), + chromedp.Flag("window-size", "1280,800"), + ) + if config.browser == "edge" { + edgePath := "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe" + slog.Debug("Using Edge", "path", edgePath, "sessionid", uuid) + opts = append(opts, + chromedp.ExecPath(edgePath), + ) + } + if config.browser_incognito { + slog.Debug("Using Incognito mode", "sessionid", uuid) + opts = append(opts, + chromedp.Flag("incognito", true), + ) + } + if config.browser_insecure { + slog.Debug("Ignore Certificate Errors", "sessionid", uuid) + opts = append(opts, + chromedp.Flag("ignore-certificate-errors", true), + ) + } + if config.browser_kiosk { + slog.Debug("Using Kiosk mode", "sessionid", uuid) + opts = append(opts, + chromedp.Flag("kiosk", true), + ) + } + + if config.user_data_dir != "" { + slog.Debug("Setting browser profile directory", "UserDataDir", config.user_data_dir, "sessionid", uuid) + profileDir := config.user_data_dir + if strings.Contains(config.user_data_dir, "%AppData%") { + profileDir = strings.Replace(config.user_data_dir, "%AppData%", (userProfileDir + "\\AppData\\Roaming"), 1) + slog.Debug("Replace %AppData%..", "Profile_directory", profileDir, "sessionid", uuid) + } + if _, err := os.Stat(profileDir); errors.Is(err, os.ErrNotExist) { + err := os.Mkdir(profileDir, os.ModePerm) + if err != nil { + fmt.Println("Cannot create profile directory: " + profileDir) + fmt.Println("The webgenericcdp application will close in 60 seconds..") + time.Sleep(time.Duration(60) * time.Second) + os.Exit(1) + } + } + opts = append(opts, + chromedp.UserDataDir(profileDir), + ) + + } + + allocCtx, _ := chromedp.NewExecAllocator(context.Background(), opts...) + var runCtx context.Context + + switch { + case config.chromedp_logging == "error": + runCtx, _ = chromedp.NewContext(allocCtx, chromedp.WithErrorf(slog.Error)) + case config.chromedp_logging == "info": + runCtx, _ = chromedp.NewContext(allocCtx, chromedp.WithBrowserOption(chromedp.WithBrowserLogf(slog.Info))) + case config.chromedp_logging == "debug": + runCtx, _ = chromedp.NewContext(allocCtx, chromedp.WithDebugf(slog.Debug)) + default: + slog.Error("Invalid chromedp logging configuration", "configuration", config.chromedp_logging, "accepted values", "error|info|debug", "sessionid", uuid) + os.Exit(1) + + } + + // Check if URL contains any value from Safeguard + urlmatch, _ := regexp.MatchString((".*{.*}"), config.url) + if urlmatch { + slog.Debug("Safeguard value found in url", "sessionid", uuid) + urlsubs := strings.SplitN(config.url, "{", 2) + urlsubs2 := strings.SplitN(urlsubs[1], "}", 2) + config.url = urlsubs[0] + fmt.Sprint(launcherStdin[urlsubs2[0]]) + urlsubs2[1] + slog.Debug("Safeguard value inserted", "url", config.url, "sessionid", uuid) + } + + // Declare tasklist + taskList := []chromedp.Action{} + if config.basicAuthUsername != "false" { + slog.Debug("Basic Authentication", "username", config.basicAuthUsername, "sessionid", uuid) + slog.Debug("Building chromedp taskList..", "sessionid", uuid) + + var basicAuthUsername string + + if strings.HasPrefix(config.basicAuthUsername, "{") && strings.HasSuffix(config.basicAuthUsername, "}") { + // Trim key names from basicAuthUsername so that we can use them as keys for the values received from Safeguard via STDIN + slog.Debug("[taskList] Trimming starting and trailing {} characters", "sessionid", uuid) + config.basicAuthUsername, _ = strings.CutSuffix(config.basicAuthUsername, "}") + config.basicAuthUsername, _ = strings.CutPrefix(config.basicAuthUsername, "{") + } + + // Check if input contains any of the configured splitCharacters between }{, like username}@{domain + slog.Debug("[taskList] Checking input if username is split by any characters", "username", config.basicAuthUsername, "splitCharacters", config.splitCharacters, "sessionid", uuid) + isComplexInput, inputs := splitComplexInput(config.basicAuthUsername, config.splitCharacters, uuid) + if isComplexInput { + slog.Debug("[taskList] Check if input was received from Safeguard", "key", inputs[0], "sessionid", uuid) + if launcherStdin[inputs[0]] == nil { + slog.Error("[taskList] Object does not exist in STDIN", "object", inputs[0], "sessionid", uuid) + os.Exit(1) + } + slog.Debug("[taskList] Check if input was received from Safeguard", "key", inputs[2], "sessionid", uuid) + if launcherStdin[inputs[2]] == nil { + slog.Error("[taskList] Object does not exist in STDIN", "object", inputs[2], "sessionid", uuid) + os.Exit(1) + } + basicAuthUsername = fmt.Sprint(launcherStdin[inputs[0]]) + inputs[1] + fmt.Sprint(launcherStdin[inputs[2]]) + + } else { + slog.Debug("[taskList] Check if input received from Safeguard", "key", config.basicAuthUsername, "sessionid", uuid) + if launcherStdin[config.basicAuthUsername] == nil { + slog.Error("[taskList] Object does not exist in STDIN", "object", config.basicAuthUsername, "sessionid", uuid) + os.Exit(1) + } + basicAuthUsername = fmt.Sprint(launcherStdin[config.basicAuthUsername]) + + } + if strings.Contains(config.url, "https://") { + config.url, _ = strings.CutPrefix(config.url, "https://") + } + if strings.Contains(config.url, "http://") { + config.url, _ = strings.CutPrefix(config.url, "http://") + } + url := "https://" + basicAuthUsername + ":" + fmt.Sprint(launcherStdin["password"]) + "@" + config.url + urlToLog := "https://" + basicAuthUsername + ":" + "" + "@" + config.url + taskList = append(taskList, chromedp.Action(chromedp.Navigate(url))) + slog.Debug("[taskList] Navigate to target", "url", urlToLog, "sessionid", uuid) + } else { + // Building chromedp taskList from loginActions + actions := strings.Split(config.loginActions, "||") + slog.Debug("Parsed "+strconv.Itoa(len(actions))+" actions", "sessionid", uuid) + slog.Debug("Building chromedp taskList from loginActions..", "sessionid", uuid) + + // Build tasklist + taskList = append(taskList, chromedp.Action(chromedp.Navigate(config.url))) + slog.Debug("[taskList] Navigate to target", "url", config.url, "sessionid", uuid) + for i := 0; i < len(actions); i++ { + + action := strings.Split(actions[i], "::") + + // If browserInputDelay is configured let's pause till that get passed + if !(config.browserInputDelay == 0) { + taskList = append(taskList, chromedp.Sleep(time.Millisecond*time.Duration(config.browserInputDelay))) + slog.Debug("[taskList] Sleep", "sleep_ms", strconv.Itoa(config.browserInputDelay), "sessionid", uuid) + } else { + // Otherwise let's wait until the browser presents the element + taskList = append(taskList, chromedp.WaitReady(action[1])) + //taskList = append(taskList, chromedp.WaitVisible("body")) + slog.Debug("[taskList] Waiting element to be visible: "+action[1], "sessionid", uuid) + } + + keyBoardKey := false + keyBoardString := false + if len(action) >= 3 { + // Is input from Safeguard or a static value? + if strings.HasPrefix(action[2], "{") && strings.HasSuffix(action[2], "}") { + // Trim key names from loginActions so that we can use them as keys for the values received from Safeguard via STDIN + action[2], _ = strings.CutSuffix(action[2], "}") + action[2], _ = strings.CutPrefix(action[2], "{") + } else if strings.HasPrefix(action[2], "kb") { + // Entry will be a keyboard key, not a string or a value from Safeguard + keyBoardKey = true + } else { + // Entry will be a static string from configuration, not a keyboard key or a value from Safeguard + keyBoardString = true + } + + } + + switch { + case action[0] == "c": + if len(action) == 2 { + taskList = append(taskList, chromedp.Click(action[1], chromedp.ByID, chromedp.NodeVisible)) + slog.Debug("[taskList] Click", "selector", action[1], "sessionid", uuid) + } else { + slog.Error("[taskList] Click action with improper number of configuration items. Format: c::", "action", actions[i], "sessionid", uuid) + os.Exit(1) + } + case action[0] == "v": + if len(action) == 3 { + // Enter value from Safeguard + if !keyBoardKey && !keyBoardString { + // Check if input contains any of the configured splitCharacters between }{, like username}@{domain + slog.Debug("[taskList] Checking input if key is split by any characters", "input", action[2], "splitCharacters", config.splitCharacters, "sessionid", uuid) + isComplexInput, inputs := splitComplexInput(action[2], config.splitCharacters, uuid) + if isComplexInput { + slog.Debug("[taskList] Check if input was received from Safeguard", "key", inputs[0], "sessionid", uuid) + if launcherStdin[inputs[0]] == nil { + slog.Error("[taskList] Object does not exist in STDIN", "object", inputs[0], "sessionid", uuid) + os.Exit(1) + } + if launcherStdin[inputs[2]] == nil { + slog.Debug("[taskList] Check if input was received from Safeguard", "key", inputs[2], "sessionid", uuid) + slog.Error("[taskList] Object does not exist in STDIN", "object", inputs[2], "sessionid", uuid) + os.Exit(1) + } + val := fmt.Sprint(launcherStdin[inputs[0]]) + inputs[1] + fmt.Sprint(launcherStdin[inputs[2]]) + taskList = append(taskList, chromedp.SendKeys(action[1], val, chromedp.ByID, chromedp.NodeVisible)) + slog.Debug("[taskList] Enter value", "selector", action[1], "value", val, "sessionid", uuid) + + } else { + slog.Debug("[taskList] Check if input received from Safeguard", "key", action[2], "sessionid", uuid) + if launcherStdin[action[2]] == nil { + slog.Error("[taskList] Object does not exist in STDIN", "object", action[2], "sessionid", uuid) + os.Exit(1) + } + taskList = append(taskList, chromedp.SendKeys(action[1], fmt.Sprint(launcherStdin[action[2]]), chromedp.ByID, chromedp.NodeVisible)) + slog.Debug("[taskList] Enter value", "selector", action[1], "value", fmt.Sprint(launcherStdin[action[2]]), "sessionid", uuid) + } + } else if keyBoardString { + // Enter static string from configuration + taskList = append(taskList, chromedp.SendKeys(action[1], fmt.Sprint(action[2]), chromedp.ByID, chromedp.NodeVisible)) + slog.Debug("[taskList] Enter value", "selector", action[1], "value", fmt.Sprint(action[2]), "sessionid", uuid) + } else if keyBoardKey { + // Enter static keyboard key from configuration + switch { + case action[2] == "kb.Enter": + taskList = append(taskList, chromedp.SendKeys(action[1], kb.Enter, chromedp.ByID, chromedp.NodeVisible)) + slog.Debug("[taskList] Enter keyboard key", "selector", action[1], "key", action[2], "sessionid", uuid) + default: + slog.Error("[taskList] Key not supported", "key", action[2], "sessionid", uuid) + os.Exit(1) + } + } + } else { + slog.Error("[taskList] Enter value action with improper number of configuration items. Format: v::::", "action", actions[i], "sessionid", uuid) + os.Exit(1) + } + case action[0] == "s": + if len(action) == 3 { + if launcherStdin[action[2]] == nil { + slog.Error("[taskList] Object does not exist in STDIN", "object", action[2], "sessionid", uuid) + os.Exit(1) + } + + taskList = append(taskList, chromedp.SendKeys(action[1], fmt.Sprint(launcherStdin[action[2]]), chromedp.ByID, chromedp.NodeVisible)) + slog.Debug("[taskList] Enter secret", "selector", action[1], "value", "", "sessionid", uuid) + } else { + slog.Error("[taskList] Enter secret action with improper number of configuration items. Format: s::::", "action", actions[i], "sessionid", uuid) + os.Exit(1) + } + case action[0] == "o": + if launcherStdin[action[2]] == nil { + slog.Error("Object does not exist in STDIN", "object", action[2], "sessionid", uuid) + os.Exit(1) + } + + t := fmt.Sprint(launcherStdin[action[2]]) + + minTimeBeforeExpiry := 0 + if len(action) != 4 && len(action) != 3 { + slog.Error("[taskList] Enter TOTP code action with improper number of configuration items. Format: o::::::", "action", actions[i], "sessionid", uuid) + os.Exit(1) + } else if len(action) == 4 { + minTimeBeforeExpiry, err = strconv.Atoi(action[3]) + } + + slog.Debug("[taskList] Looking up valid TOTP code...", "sessionid", uuid) + slog.Debug("[taskList][TOTP_Lookup] Required seconds before TOTP expiry: "+strconv.Itoa(minTimeBeforeExpiry), "sessionid", uuid) + slog.Debug("[taskList][TOTP_Lookup] TOTP JSON: "+t, "sessionid", uuid) + + var otps []map[string]interface{} + + if len(t) > 0 { + if err = json.Unmarshal([]byte(t), &otps); err != nil { + slog.Error("[taskList][TOTP_Lookup] Error occured while parsing TOTP JSON", "sessionid", uuid) + slog.Error(err.Error(), "sessionid", uuid) + os.Exit(1) + } + + otp := "" + + for o := 0; o < len(otps); o++ { + currentUnixTime := time.Now().Unix() + + totp_UnixTime := fmt.Sprintf("%.0f", otps[o]["UnixTime"]) + totp_Period := fmt.Sprintf("%.0f", otps[o]["Period"]) + + slog.Debug("[taskList][TOTP_Lookup] Current UnixTime: "+strconv.Itoa(int(currentUnixTime)), "sessionid", uuid) + slog.Debug("[taskList][TOTP_Lookup] Examining TOTP "+strconv.Itoa(o+1), "UnixTime", totp_UnixTime, "sessionid", uuid) + slog.Debug("[taskList][TOTP_Lookup] Examining TOTP "+strconv.Itoa(o+1), "Period", totp_Period, "sessionid", uuid) + + // Check whether the validity of the current TOTP code is within the defined period + // (current time + the minimum number of seconds required to enter the OTP before it expires) + + // Time until expiry of current code + totp_UnixTimeInt, err := strconv.Atoi(totp_UnixTime) + if err != nil { + slog.Debug("Failed converting Unixtime string to int") + } + totp_PeriodInt, err := strconv.Atoi(totp_Period) + if err != nil { + slog.Debug("Failed converting Period string to int") + } + totp_diff := totp_UnixTimeInt + totp_PeriodInt - int(currentUnixTime) + if totp_diff >= minTimeBeforeExpiry { + otp = otps[o]["Code"].(string) + slog.Debug("[taskList][TOTP_Lookup] Found valid TOTP code, expiring in "+strconv.Itoa(totp_diff)+" seconds", "TOTP_code", otp, "sessionid", uuid) + o = len(otps) + } else if totp_diff < 0 { + slog.Error("[taskList][TOTP_Lookup] TOTP code is already expired. Diff: "+strconv.Itoa(totp_diff)+". Checking the next code", "sessionid", uuid) + } else { + slog.Debug("[taskList][TOTP_Lookup] TOTP code is closer to expiry than defined minimum "+strconv.Itoa(minTimeBeforeExpiry)+" seconds. Diff: "+strconv.Itoa(totp_diff)+". Waiting "+strconv.Itoa(minTimeBeforeExpiry)+" seconds before checking the next code.", "sessionid", uuid) + } + + } + if otp == "" { + log.Fatalln("[taskList][TOTP_Lookup] Have not found valid TOTP code, exit.", "sessionid", uuid) + } else { + taskList = append(taskList, chromedp.SendKeys(action[1], otp, chromedp.ByID, chromedp.NodeVisible)) + slog.Debug("[taskList] Enter TOTP code", "selector", action[1], "code", otp, "sessionid", uuid) + } + } + + } + + } + } + + // Running task list (built of login actions) + slog.Debug("Execute taskList", "sessionid", uuid) + cerr := chromedp.Run(runCtx, taskList...) + if cerr != nil { + slog.Error("Error occured while executing taskList", "sessionid", uuid) + slog.Error("Error: "+cerr.Error(), "sessionid", uuid) + os.Exit(1) + } + + os.Exit(0) + +} + +// If }splitCharacter{ is found in the value input, it returns true, and the splitted strings in array together with the found split character. Otherwise it returns false +func splitComplexInput(input string, splitChars string, uuid string) (bool, []string) { + var inputs []string + for i, c := range splitChars { + slog.Debug("[splitComplexInput] Checking split character: "+fmt.Sprint(i+1), "character", fmt.Sprint(string(c)), "sessionid", uuid) + match, _ := regexp.MatchString(("}" + "\\" + string(c) + "{"), input) + if match { + inputs = strings.Split(input, ("}" + string(c) + "{")) + inputs = append(inputs, inputs[1]) + inputs[1] = fmt.Sprint(string(c)) + slog.Debug("[splitComplexInput] Match. Returned split string", "#1", inputs[0], "#2", inputs[1], "#3", inputs[2], "sessionid", uuid) + return true, inputs + } + } + slog.Debug("[splitComplexInput] No any split characters found in key", "key", input, "splitCharacters", splitChars, "sessionid", uuid) + return false, inputs +} diff --git a/RDP Applications/Go chromedp/webgenericcdp/webgenericcdp_sample.conf b/RDP Applications/Go chromedp/webgenericcdp/webgenericcdp_sample.conf new file mode 100644 index 0000000..feb362b --- /dev/null +++ b/RDP Applications/Go chromedp/webgenericcdp/webgenericcdp_sample.conf @@ -0,0 +1,56 @@ +# IMPORTANT: Write permissions of the configuration files, as well as the RemoteApp configuration should be restricted to avoid password leaking. + +##dumpStdinToLog -- WARNING, this contains the clear-text password +#dumpStdinToLog=false + +##chromedp_logging -- error|info|debug (default:error) WARNING, the 'debug' option contains the clear-text password +#chromedp_logging=error + +##url +## Supports adding one dynamic value from Safeguard +## Sample: https://{Target.AssetNetworkAddress}/login +url=https:// + +##browser -- chrome or edge (default: chrome) +#browser=chrome + +##loginActions +## Format: :::: +## Actions: +## v > Enter value into the given element. +## If entry is enclosed between curly brackets {} the script looks up the value in the data received from Safeguard +## Otherwise if the entry starts with kb. then the script is entering the static keyboard key, like kb.Enter +## Otherwise the script enters the static string from the configuration. This may be useful for configuring instance name or tenant id via the login form. +## s > Enter secret into the given element (same as entering value but the the value is not logged - except if chromedp_debug=true +## c > Click the given element +## o > Enter OTP into the given element. Must be used with {Target.TotpCodes}. The numeric value is the minimum nr. of seconds that the current OTP should be valid for. If the current TOTP expires in shorter time, the code waits for the next TOTP. This is useful to increase (e.g. to 5) in case of having TOTP invalidity issues. +## Samples: +## v::::{username}@{Target.AccountDomainName}||c::||s::#i0118::||c::||o::selector_otp_input::{Target.TotpCodes}::3||c:: +## v::::{username}@{Target.AccountDomainName}||v::::kb.Enter||s::#i0118::||v::::kb.Enter +loginActions= + +##basicAuthUsername +## If configured, loginActions is ignored and basic authentication is performed using the configured username and the password received from Safeguard +## splitCharacters are taken into consideration, configure it if the default value is insufficient +## Samples: +## basicAuthUsername={username} +## basicAuthUsername={username}@{Target.AccountDomainName} +## Do _not_ use {Target.AccountDomainName}\{username} +#basicAuthUsername=false + +##splitCharacters +## List of characters which may be used on concatenated values like UPN or down-level logon name +## Backslash has to be escaped +#splitCharacters=@\\ + +##browserInputDelay -- if set (in milliseconds), the script pauses for this period between the actions instead of waiting for the next page element being visible (as it is not reliable on all websites) +#browserInputDelay=0 + +#browser_incognito=true + +#browser_insecure=false + +#browser_kiosk=false + +##user_data_dir -- Set profile folder in case you wish to keep user settings, for example bookmarks +#user_data_dir=%AppData%\ \ No newline at end of file