PoShPACLI
PoShPACLI copied to clipboard
Issue parsing output in the Find-PVFile function when account contains attributes with multi-line text
Your issue may already be reported. Please search existing issues before creating one.
Your Environment
- PowerShell Version: Name Value
PSVersion 5.1.17763.1852 PSEdition Desktop PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...} BuildVersion 10.0.17763.1852 CLRVersion 4.0.30319.42000 WSManStackVersion 3.0 PSRemotingProtocolVersion 2.3 SerializationVersion 1.1.0.1
- PoShPACLI Version: ModuleVersion = '2.1.27'
- PACLI Version: File version: 11.1.0.59 Product version: 11.01.0
- CyberArk Version: 11.1
Expected Behaviour
Find-PVFile function should provide the list of files and deatails about each file in the safe.
Current Behaviour
This function stops returning correct file details after one of the files contains attribute with multi-line content. For example, if FileCategories attribute contains CPMErrorDetails value wich spans on multiple lines.
Possible Solution
Before sending output to ConvertFrom-PacliOutput normalize it to avoid new lines and also # characters in the CPM error. Here is example code:
# Set the regex to capture multi-line CPM error message located between "#CPMErrorDetails:" and "#ResetImmediately" or "#CPMDisabled:" (note: could be also other, if reset or cmp disabled parameters are not present).
[regex]$captureErrorRegex = "(.*\#CPMErrorDetails:)([\S\s]*?)(\#ResetImmediately:.*|\#CPMDisabled:.*)"
# Remove empty lines from the output
$outputNoNewLine = $Return.StdOut | Select-String -Pattern "\S"
# Split by new lines
$splitOutput = $outputNoNewLine -split "\r\n"
# Init new output statements list
$newOutputStatements = @()
# Loop through each statement in the split output
for ([int]$i=0; $i -lt $splitOutput.Count; $i++) {
# Get statement
$originalStatement = $splitOutput[$i]
# Match regex against statement
$match = $captureErrorRegex.Matches($originalStatement)
# Check if match succeeded
if ($match.Success) {
Write-Host "Found CPM error. Normalize it."
# Get error value, which matches regex
$cpmErrorValue = $match.Groups[2].Value
# Replace possible new lines with comma
$cpmErrorValue = $cpmErrorValue -replace "\r\n",", " -replace "\r",", " -replace "\n",", "
# Replace double qoutes with single quotes
$cpmErrorValue = $cpmErrorValue -replace '"',''''
# Replace # character with % character (because it is used later to parse and split file categories)
$cpmErrorValue = $cpmErrorValue -replace '#','%'
Write-Host "New CPM error:"
Write-Host $cpmErrorValue
# Add new statement to the list by combining pre- and post- statement values
$newOutputStatements += $match.Groups[1].Value + $cpmErrorValue + $match.Groups[3].Value
# $newOutputStatements += $match.Groups[1].Value + "---------ERROR----------" + $match.Groups[3].Value
} else {
# No match
Write-Host "Couldn't find CPM error."
# Add orignal statement as is
$newOutputStatements += $originalStatement
}
}
# Create new output by joining statements with new lines
$newOutput = $newOutputStatements -join "`r`n"
#Convert Output to array
#.. your code goes below
Also it could be good to check the $Results.length to make sure that it can be divided by 32 without leftovers. If you get floating number, by division on 32, then your properties are shifted.
Steps to Reproduce (for bug reports)
1 . Create some attribute on account which accepts multiline input and set it.
2 . Add several accounts in the safe. All of them may contain this multiline attribute set or only some accoutns may have this attribute set.
3 . Try to use Find-PVFile function to query all accounts in the safe.
Here is example output, before it being processed by ConvertFrom-PacliOutput function, you can use it to reproduce the issue. Here I have 2 accounts in the safe:
"MyPlatformName1-MyAddress1-CYBERARK_TESTING","","Thu May 27 12:41:20 2021","CPMv20","--","","Thu May 27 12:41:20 2021","CPMv20","--","","","500","NO","000000000000052","MySafeName1","Root","5","-1","PENDING","Fri May 07 09:08:48 2021","user.name","Mon May 17 15:54:51 2021","usr1","Mon May 17 15:54:51 2021","usr1","Thu May 27 12:41:20 2021","CPMv20","Thu May 27 12:41:20 2021","CPMv20","--","","UserName:CYBERARK_TESTING#PolicyID:MyTestPlatform#DeviceType:Imported Platforms#Address:MyAddress#CreationMethod:PVWA#ServiceName:MySvcName1#CPMErrorDetails:Execution error. EXT01::Did not find any matching prompt for 'Traceback (most recent call last):
File "C:\Program Files (x86)\CyberArk\Password Manager\bin\MyScript.py", line 18, in <module>
temp.click()
File "C:\Program Files (x86)\Python39-32\lib\site-packages\selenium\webdriver\remote\webelement.py", line 80, in click
self._execute(Command.CLICK_ELEMENT)
File "C:\Program Files (x86)\Python39-32\lib\site-packages\selenium\webdriver\remote\webelement.py", line 633, in _execute
return self._parent.execute(command, params)
File "C:\Program Files (x86)\Python39-32\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 321, in execute
self.error_handler.check_response(response)
File "C:\Program Files (x86)\Python39-32\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 242, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.ElementNotVisibleException: Message: element not visible
(Session info: chrome=90.0.4430.93)
(Driver info: chromedriver=2.35.528161 (5b82f2d2aae0ca24b877009200ced9065a772e73),platform=Windows NT 6.3.9600 x86_64)
'. Error code:-1#ResetImmediately:ChangeTask#RetriesCount:1#CPMStatus:failure#LastTask:ChangeTask#LastFailDate:1622112081#CPMDisabled:(CPM)MaxRetries#"
"ztest1","","Wed Jun 23 14:51:03 2021","username2","--","","Wed Jun 23 14:51:03 2021","username2","--","","","500","NO","000000000000053","MySafeName1","Root","6","-1","PENDING","Wed Jun 23 14:51:03 2021","username2","Wed Jun 23 14:51:03 2021","username2","--","","--","","--","","--","","ServiceName:xtestsvc#DeviceType:Imported Platforms#UserName:xtestusr1#PolicyID:MyTestPlatform#Address:xtestaddr1#CreationMethod:PVWA#"
4 . Check the output and notice that after account with multi-line attribute all properties of other accounts would not be displayed correctly, because in the function below you expect that each property is located in a separate line, but in our case lines are shifted down because of multi-line property value:
#loop through results
For ($i = 0 ; $i -lt $Results.length ; $i += 32) {
#Get Range from array
$values = $Results[$i..($i + 32)]
#Output Object
[PSCustomObject] @{
"Filename" = $values[0]
"Accessed" = $values[1]
"CreationDate" = $values[2]
"CreatedBy" = $values[3]
"DeletionDate" = $values[4]
"DeletionBy" = $values[5]
"LastUsedDate" = $values[6]
"LastUsedBy" = $values[7]
"LockDate" = $values[8]
"LockedBy" = $values[9]
"LockedByGW" = $values[10]
"Size" = $values[11]
"History" = $values[12]
"InternalName" = $values[13]
"Safe" = $values[14]
"Folder" = $values[15]
"FileID" = $values[16]
"LockedByUserID" = $values[17]
"ValidationStatus" = $values[18]
"HumanCreationDate" = $values[19]
"HumanCreatedBy" = $values[20]
"HumanLastUsedDate" = $values[21]
"HumanLastUsedBy" = $values[22]
"HumanLastRetrievedByDate" = $values[23]
"HumanLastRetrievedBy" = $values[24]
"ComponentCreationDate" = $values[25]
"ComponentCreatedBy" = $values[26]
"ComponentLastUsedDate" = $values[27]
"ComponentLastUsedBy" = $values[28]
"ComponentLastRetrievedDate" = $values[29]
"ComponentLastRetrievedBy" = $values[30]
"FileCategories" = $values[31]
} | Add-ObjectDetail -TypeName pacli.PoShPACLI.File
Sample Output
Context
I'm getting the list of all accounts in safe with all their attributes, including filecategories and export it as a table.
Also I think it could be possible to normalize it in that way that later you can use ConvertFrom-Csv function, which also supports multi-line attributes and can grab it correctly natively and afterwards you will have parameter contain also multi-line string, instead of single line normalized line, as I did above. I belive that it is enough to replace double quotes " with single ' qote in the CPM Error message Headers are just for example below, h1, h2, etc.. could be replaced by "Filename", "Accessed", etc..
$header = "h1", "h2", "h3", "h4", "h5", "h6", "h7", "h8", "h9", "h10", "h11", "h12", "h13", "h14", "h15", "h16", "h17", "h18", "h19", "h20", "h21", "h22", "h23", "h24", "h25", "h26", "h27", "h28", "h29", "h30", "h31", "h32"
$csvPo = $normalizedoutput | ConvertFrom-Csv -Header $header