Functions/Accounts/Set-PASAccount.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
function Set-PASAccount {
    <#
.SYNOPSIS
Updates an existing accounts details.

.DESCRIPTION
Updates an existing accounts details.

For CyberArk version prior to 10.4:
All of the account's property details MUST be passed to the function.
Any current properties of the account not sent as part of the request will be removed
from the account.
To change a property value not exposed via a named parameter,
pass the property name and updated value to the function via the Properties parameter.
If changing the name or folder of a service account that has multiple dependencies (usages),
the connection between it and its dependencies will be automatically maintained.
If changing the name or folder of an account that is linked to another account (whether logon,
reconciliation or verification), the links will be automatically updated.

.PARAMETER AccountID
The unique ID of the account to update.
Retrieved by Get-PASAccount

.PARAMETER op
The operation to perform (add, remove, replace).
Requires CyberArk version 10.4+

.PARAMETER path
The path of the property to update, for instance /address or /name.
Requires CyberArk version 10.4+

.PARAMETER value
The new property value for add or replace operations.
Requires CyberArk version 10.4+

.PARAMETER operations
A collection of update actions to perform, must include op, path & value (except where action is remove).
Requires CyberArk version 10.4+

.PARAMETER Folder
The folder where the account is stored.

.PARAMETER AccountName
The name of the account

.PARAMETER DeviceType
The devicetype assigned to the account.
Ensure all required parameters are specified.
Different device types require different parameters

.PARAMETER PlatformID
The CyberArk platform assigned to the account
Ensure all required parameters are specified.
Different platforms require different parameters

.PARAMETER Address
The Name or Address of the machine where the account will be used

.PARAMETER Username
The Username on the target machine

.PARAMETER GroupName
A groupname with which the account will be associated
The name of the group with which the account is associated.
To create a new group, specify the group platform ID in the GroupPlatformID property,
then specify the group name. The group will then be created automatically.

.PARAMETER GroupPlatformID
GroupPlatformID is required if account is to be moved to a new group.

.PARAMETER Properties
Hashtable of name=value pairs.
Specify properties to update.

.PARAMETER InputObject
Receives object from pipeline.

.EXAMPLE
Set-PASAccount -AccountID 27_4 -op replace -path "/address" -value "NewAddress"

Replaces the current address value with NewAddress

.EXAMPLE
Set-PASAccount -AccountID 27_4 -op remove -path "/platformAccountProperties/UserDN"

Removes UserDN property set on account

.EXAMPLE
$actions += @{"op"="Add";"path"="/platformAccountProperties/UserDN";"value"="SomeDN"}
$actions += @{"op"="Replace";"path"="/Name";"value"="SomeName"}

Set-PASAccount -AccountID 27_4 -operations $actions

Performs the update operations contained in the $actions array against the account

.EXAMPLE
Get-PASAccount dbuser | Set-PASAccount -Properties @{"DSN"="myDSN"}

Sets DSN value on matched account dbUser

.EXAMPLE
 Set-PASAccount -AccountID 21_3 -Folder Root -AccountName NewName `
 -DeviceType Database -PlatformID Oracle -Address dbServer.domain.com -UserName dbuser

 Will set the AccountName of account with AccountID of 21_3 to "NewName".
 **Any/All additional properties of the account which are not specified via parameters will be cleared**

.INPUTS
All parameters, except "Properties", can be piped by property name.
Accepts pipeline object from Get-PASAccount functions.
When an object is piped into this function, properties which are
set on the account are automatically included in the request.
If run without pipeline input, all existing properties of the account
must be specified in the request, otherwise, any property values not
specified will be removed from the account.

.OUTPUTS
Outputs Object of Custom Type psPAS.CyberArk.Vault.Account or psPAS.CyberArk.Vault.Account.V10
Output format is defined via psPAS.Format.ps1xml.
To force all output to be shown, pipe to Select-Object *

.NOTES
Dependencies (usages) cannot be updated.
Accounts that do not have a policy ID cannot be updated.

To update account properties, "Update password properties" permission is required.
To rename accounts, "Rename accounts" permission is required.
To move accounts to a different folder, Move accounts/folders permission is required.

.LINK
https://pspas.pspete.dev/commands/Set-PASAccount
#>

    [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = "V10SingleOp")]
    param(

        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true
        )]
        [ValidateNotNullOrEmpty()]
        [Alias("id")]
        [string]$AccountID,

        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "V10SingleOp"
        )]
        [ValidateSet("add", "replace", "remove")]
        [Alias("Operation")]
        [string]$op,

        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "V10SingleOp"
        )]
        [string]$path,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "V10SingleOp"
        )]
        [string]$value,

        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "V10MultiOp"
        )]
        [hashtable[]]$operations,

        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "V9"
        )]
        [string]$Folder,

        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "V9"
        )]
        [Alias("Name")]
        [string]$AccountName,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "V9"
        )]
        [string]$DeviceType,

        [Alias("PolicyID")]
        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "V9"
        )]
        [string]$PlatformID,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "V9"
        )]
        [string]$Address,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "V9"
        )]
        [string]$UserName,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "V9"
        )]
        [string]$GroupName,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "V9"
        )]
        [string]$GroupPlatformID,

        [parameter(
            Mandatory = $false,
            ValueFromPipelineByPropertyName = $false,
            ParameterSetName = "V9"
        )]
        [hashtable]$Properties = @{ },

        [parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ParameterSetName = "V10SingleOp"
        )]
        [parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ParameterSetName = "V10MultiOp"
        )]
        [parameter(
            Mandatory = $false,
            ValueFromPipeline = $true,
            ParameterSetName = "V9"
        )]
        [psobject]$InputObject
    )

    BEGIN {
        $MinimumVersion = [System.Version]"10.4"
    }#begin

    PROCESS {

        #Get all parameters that will be sent in the request
        $boundParameters = $PSBoundParameters | Get-PASParameter -ParametersToRemove InputObject, AccountID

        if ($PSCmdlet.ParameterSetName -match "V10") {

            Assert-VersionRequirement -ExternalVersion $Script:ExternalVersion -RequiredVersion $MinimumVersion

            #Create URL for Request
            $URI = "$Script:BaseURI/api/Accounts/$AccountID"

            #Define method for request
            $Method = "PATCH"

            #Define type of output object
            $Type = "psPAS.CyberArk.Vault.Account.V10"

            if ($PSCmdlet.ParameterSetName -match "V10MultiOp") {

                $boundParameters = $boundParameters["operations"]

            }

            #Do Not Pipe into ConvertTo-JSON.
            #Correct JSON Format is only achieved when the array is not sent along the pipe
            $body = ConvertTo-JSON @($boundParameters)

        }

        if ($PSCmdlet.ParameterSetName -eq "V9") {

            #Create URL for Request
            $URI = "$Script:BaseURI/WebServices/PIMServices.svc/Accounts/$AccountID"

            #Define method for request
            $Method = "PUT"

            #Define type of output object
            $Type = "psPAS.CyberArk.Vault.Account"

            if ($PSBoundParameters.ContainsKey("Properties")) {

                #Format "Properties" parameter value.
                #Array of key=value pairs required for JSON convertion
                $boundParameters["Properties"] = @($boundParameters["Properties"].getenumerator() |

                    ForEach-Object { $_ })

            }

            If (($InputObject) -and (($InputObject | Get-Member).TypeName -eq "psPAS.CyberArk.Vault.Account")) {

                #If InputObject is psPAS.CyberArk.Vault.Account
                #i.e. receiving pipeline from Get-PASAccount

                #Get all existing properties as defined by input object:
                #Process Pipeline input object properties
                $InputObject |

                #exclude properties output by get-pasaccount not applicable to set-pasaccount request
                Select-Object -Property * -ExcludeProperty Name, PolicyID, Safe |

                #get all remaining noteproperties
                Get-Member -MemberType "NoteProperty" |

                #For each property
                ForEach-Object {

                    #Initialise hashtable
                    $ExistingProperty = @{ }

                    #if property is not bound to function parameter by name,
                    if (!(($PSBoundParameters.ContainsKey($($_.Name))) -or (

                                #if not being explicitly updated.
                                $($Properties).ContainsKey($($_.Name))))) {

                        [hashtable]$ExistingProperty.Add($($_.Name), $($InputObject.$($_.Name)))

                        #Add to Properties node of request data
                        [array]$boundParameters["Properties"] += $ExistingProperty.GetEnumerator() | ForEach-Object { $_ }
                        #any existing properties of an account not sent in a "set" request will be cleared on the account.
                        #This ensures correctly formatted request with all existing account properties included
                        #when function is sent data via the pipeline.

                    }

                }

            }

            #Create body of request
            $body = @{

                "Accounts" = $boundParameters

                #ensure nodes at all required depths are included in the JSON object
            } | ConvertTo-Json -Depth 3

        }

        if ($PSCmdlet.ShouldProcess($AccountID, "Update Account Properties")) {

            #send request to PAS web service
            $Result = Invoke-PASRestMethod -Uri $URI -Method $Method -Body $Body -WebSession $Script:WebSession

            If ($Result) {

                if ($PSCmdlet.ParameterSetName -eq "V9") {

                    $Return = $Result.UpdateAccountResult

                }

                Else {

                    $Return = $Result

                }

                $Return | Add-ObjectDetail -typename $Type -PropertyToAdd @{

                    "AccountID" = $AccountID

                }

            }

        }

    }#process

    END { }#end

}