pspete / psPAS

PowerShell module for CyberArk Privileged Access Security REST API
https://pspas.pspete.dev
MIT License
291 stars 91 forks source link

Powershell 5.1 variable splatting not working properly #340

Closed gunplar closed 3 years ago

gunplar commented 3 years ago

Describe the issue Running Add-PASSafeMember @groupConfig, with $groupConfig storing a hash table (values in error), returns this error `Add-PASSafeMember : A positional parameter cannot be found that accepts argument '@{SafeName=Phuc2403_4; MemberName=SafeAccess_Phuc2403_4_Owner; UseAccounts=True; RetrieveAccounts=True; ListAccounts=True; AddAccounts=True; UpdateAccountContent=True; UpdateAccountProperties=True; InitiateCPMAccountManagementOperations=True; SpecifyNextAccountContent=True; RenameAccounts=True; DeleteAccounts=True; UnlockAccounts=True; ManageSafe=True; ManageSafeMembers=True; BackupSafe=True; ViewAuditLog=True; ViewSafeMembers=True; RequestsAuthorizationLevel=2; AccessWithoutConfirmation=True; CreateFolders=True; DeleteFolders=True; MoveAccountsAndFolders=True}'. At line:1 char:1

To Reproduce Steps to reproduce the behavior:

  1. $groupConfig = Get-Content $ownerConfigPath | ConvertFrom-Json
  2. Add-PASSafeMember @groupConfig

Expected behavior Cmdlet executes without error.

Your Environment Include relevant details about your environment

JohnnyLeuthard commented 3 years ago

I am experiencing the same issue. After the splatting failed I also tried importing a CSV and piping it to the Ad-PASSameMember cmdlet since the help states it allows pipeline input by Property Name.

I'm running version 5.1.18362.171

I have tried it in the ISE, PowerShell command window, Visual Studio Code (version 1.54.2) In my CSV I have tried putting the values as true, fales, 0, 1 and all produce the same error saying "...Cannot convert value "system.string:" ton type "system.boolean..."

pspete commented 3 years ago

start here: about_Splatting

@gunplar - your ConvertFrom-Json command will be returning an object, not a hashtable.... The issue cannot be reproduced, no issue can be observed splatting the parameters in PowerShell 5.1:

$splat = @{
SafeName="SomeSafe";
MemberName="SomeSafeMember"; 
UseAccounts=$True; RetrieveAccounts=$True; ListAccounts=$True; AddAccounts=$True; UpdateAccountContent=$True; 
UpdateAccountProperties=$True; InitiateCPMAccountManagementOperations=$True;SpecifyNextAccountContent=$True; 
RenameAccounts=$True; DeleteAccounts=$True; UnlockAccounts=$True; ManageSafe=$True;ManageSafeMembers=$True; 
BackupSafe=$True; ViewAuditLog=$True; ViewSafeMembers=$True; RequestsAuthorizationLevel=2;
AccessWithoutConfirmation=$True; CreateFolders=$True; DeleteFolders=$True; MoveAccountsAndFolders=$True
}

 > Add-PASSafeMember @splat

MemberName     SearchIn SafeName Permissions                                                                                                                                         
----------     -------- -------- -----------                                                                                                                                         
SomeSafeMember vault    SomeSafe @{UseAccounts=True; RetrieveAccounts=True; ListAccounts=True; AddAccounts=True; UpdateAccountContent=True; UpdateAccountProperties=True; Initiate...
pspete commented 3 years ago

"...Cannot convert value "system.string:" to type "system.boolean..."

@JohnnyLeuthard if the previous answer does not help you, your issue appears to stem from using values not cast as boolean.

Consider:

 > "True" -is [boolean]
False

 > "False" -is [boolean]
False

 > $true -is [boolean]
True

 > $false -is [boolean]
True

 > (1).gettype()

IsPublic IsSerial Name                                     BaseType                                                                                                                  
-------- -------- ----                                     --------                                                                                                                  
True     True     Int32                                    System.ValueType                                                                                                          

 > ([boolean]1) -is [boolean]
True

Hope this helps

pspete commented 3 years ago

since the help states it allows pipeline input by Property Name

It does, see: https://pspas.pspete.dev/docs/safe-permissions/

gunplar commented 3 years ago

Ah I see, the syntax makes it look like a hashtable, but indeed it was not one. Thanks for pointing that out!

JohnnyLeuthard commented 3 years ago

"...Cannot convert value "system.string:" to type "system.boolean..."

@JohnnyLeuthard if the previous answer does not help you, your issue appears to stem from using values not cast as boolean.

Consider:

 > "True" -is [boolean]
False

 > "False" -is [boolean]
False

 > $true -is [boolean]
True

 > $false -is [boolean]
True

 > (1).gettype()

IsPublic IsSerial Name                                     BaseType                                                                                                                  
-------- -------- ----                                     --------                                                                                                                  
True     True     Int32                                    System.ValueType                                                                                                          

 > ([boolean]1) -is [boolean]
True

Hope this helps

Not sure why it's working today and wasn't last week. I tried $true, 'true', 1, 0, $false, 'false', verified the type with gettype(). Maybe i should have walked away for a while. Sometimes thats all it takes. :) What I was ultimately trying to do last week and was able to successfully this morning was to have an INI file that has all the different types of access I will need to use. Things like Vault Admin, auditors, Provider and APPID's, owners, approvers, etc. Then read that into an array where each object is a hashtable. Then depending on the member being added I am just reading that object back into a new hashtable and passing across to the Add member cmdlet. That way I can have a process that me and others can user and access rights are consistent and any modifications or additions just need to be made to the INI. Works pretty slick. This module has really become useful.

JohnnyLeuthard commented 3 years ago

Upon further investigation it looks like it's something with how I'm loading my hashtable. I have an INI file I read into an array. Each object in the array is a hashtable. I read the individual object into a new variable and pass that across to the command and for some reason even though the variable is a hashtable verified with $AccesRights.gettype() and the values are true/false it tells me they are string and not boolean. My objecting is to have an INI that has a section for each member type that I will be using so there is consistency and a single file to edit when adding, and modifying. It looks as though there is an issue with how I am sucking in the hashtable from an array and how it converts the value. If I create the hashtable manually and pass it across it works fine.

pspete commented 3 years ago

@JohnnyLeuthard you can use the same gettype() method to confirm that the values stored in the hashtable imported from your INI file are strings and not boolean. unless commands like export-clixml | import-clixml are used to store actual representations of the objects and their data types, a method which casts the string values into boolean values will need to be used when the input file is read/imported.

 > $ht = @{"True" = "True"; "False" = "False"}

 > $ht["True"].gettype()

IsPublic IsSerial Name                                     BaseType                                                                                                                  
-------- -------- ----                                     --------                                                                                                                  
True     True     String                                   System.Object                                                                                                             

> ([boolean]$ht["False"]).gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Boolean                                  System.ValueType

 > $ht["True"] = $ht["True"] -as [Boolean]

 > $ht["True"].gettype()

IsPublic IsSerial Name                                     BaseType                                                                                                                  
-------- -------- ----                                     --------                                                                                                                  
True     True     Boolean                                  System.ValueType