Functions/Accounts/Get-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
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
function Get-PASAccount {
    <#
.SYNOPSIS
Returns details of matching accounts. (Version 10.4 onwards)
Returns information about a single account. (Version 9.3 - 10.3)

.DESCRIPTION
Version 10.4+:
This method returns a list of either a specific, or all the accounts in the Vault.
Requires the following permission in the Safe: List accounts.

Version 9.3 - 10.3:
Returns information about an account. If more than one account meets the search criteria,
only the first account will be returned (the Count output parameter will display the number
of accounts that were found).
Only the following users can access this account:
    - Users who are members of the Safe where the account is stored
    - Users who have access to this specific account.
    - The user who runs this web service requires the following permission in the Safe:
    - Retrieve account
This method does not display the actual password.
If ten or more accounts are found, the Count Output parameter will show 10.

.PARAMETER id
A specific account ID to return details for.

.PARAMETER search
The search term or keywords.

.PARAMETER searchType
Get accounts that either contain or start with the value specified in the Search parameter.

.PARAMETER safeName
The name of the safe to return accounts from.

.PARAMETER modificationTime
Specify to only return details of accounts modified after this date/time
Documented as an option since 11.4

.PARAMETER sort
Property or properties by which to sort returned accounts,
followed by asc (default) or desc to control sort direction.
Separate multiple properties with commas, up to a maximum of three properties.

.PARAMETER offset
An offset for the search results (to discard the first x results for instance).
*depreciated parameter in psPAS - nextLink functionality will fetch all results automatically

.PARAMETER limit
Maximum number of returned accounts. If not specified, the default value is 50.
The maximum number that can be specified is 1000. When used together with the Offset parameter,
this value determines the number of accounts to return, starting from the first account that is returned.
*depreciated parameter in psPAS - nextLink functionality will fetch all results automatically

.PARAMETER filter
A filter for the search.
Requires format: "SafeName eq 'YourSafe'"
*depreciated parameter in psPAS - safeName & modifiedTime will automatically be set as filter values

.PARAMETER Keywords
Keyword to search for.
If multiple keywords are specified, the search will include all the keywords.
Separate keywords with a space.
Relevant for CyberArk versions earlier than 10.4

.PARAMETER Safe
The name of a Safe to search that the authenticated user is authorized to access.
Relevant for CyberArk versions earlier than 10.4

.PARAMETER TimeoutSec
See Invoke-WebRequest
Specify a timeout value in seconds

.EXAMPLE
Get-PASAccount

Returns all accounts on safes where your user has "List accounts" rights.
This will only work from version 10.4 onwards.

.EXAMPLE
Get-PASAccount -search XUser -searchType startswith

Returns all accounts starting with "XUser".

.EXAMPLE
Get-PASAccount -safeName TargetSafe

Returns all accounts from TargetSafe

.EXAMPLE
Get-PASAccount -safeName TargetSafe -modificationTime (Get-Date 03/06/2020) -search some

Returns all accounts from TargetSafe modified after 03/06/2020

.EXAMPLE
Get-PASAccount -filter "SafeName eq TargetSafe"

Specify a filter value to return all accounts found in "TargetSafe"

.EXAMPLE
Get-PASAccount -filter "SafeName eq 'TargetSafe'" -sort "userName desc"

Returns all accounts found in TargetSafe, sort by username in descending order.

.EXAMPLE
Get-PASAccount -Keywords root -Safe UNIX

Finds account(s) matching keywords in UNIX safe:

AccountID : 19_6
Safe : UNIX
Folder : Root
Name : UNIXSSH-machine-root
UserName : root
PlatformID : UNIXSSH
DeviceType : Operating System
Address : machine

.EXAMPLE
Get-PASAccount -Keywords xtest

Finds accounts matching the specified keyword.
Only the first matching account will be returned.
If multiple accounts are found, a warning will be displayed before the result:

WARNING: 3 matching accounts found. Only the first result will be returned

AccountID : 19_9
Safe : TestSafe
Folder : Root
Name : Application-Cyberark-10.10.10.20-xTest3
UserName : xTest3
PlatformID : Cyberark
DeviceType : Application
Address : 10.10.10.20

.EXAMPLE
Get-PASAccount -search root -sort name -offset 100 -limit 5

Returns all accounts matching "root", sorted by AccountName, Search results offset by 100 and limited to 5.
*depreciated parameter in psPAS - nextLink functionality will fetch all results automatically

.INPUTS
All parameters can be piped by property name
Should accept pipeline objects from other *-PASAccount functions

.OUTPUTS
Outputs Object of Custom Type psPAS.CyberArk.Vault.Account
AccountID, Account Safe, Safe Folder, Account Name,
and any other set property of the account are contained in output.

Output format is defined via psPAS.Format.ps1xml.
To force all output to be shown, pipe to Select-Object *
Output format is defined via psPAS.Format.ps1xml.
To force all output to be shown, pipe to Select-Object *

.NOTES
New functionality added in version 10.4, limited functionality before this version.
As of psPAS v2.5.1+, the use of 'limit' and 'offset' parameters is discouraged - nextLink functionality was added

.LINK
https://pspas.pspete.dev/commands/Get-PASAccount

#>


    [CmdletBinding(DefaultParameterSetName = "v10ByQuery")]
    param(
        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "v10ByID"
        )]
        [Alias("AccountID")]
        [string]$id,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "v10ByFilter"
        )]
        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "v10ByQuery"
        )]
        [string]$search,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "v10ByFilter"
        )]
        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "v10ByQuery"
        )]
        [ValidateSet("startswith", "contains")]
        [string]$searchType,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "v10ByQuery"
        )]
        [string]$safeName,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "v10ByQuery"
        )]
        [datetime]$modificationTime,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "v10ByFilter"
        )]
        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "v10ByQuery"
        )]
        [string[]]$sort,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "v10ByFilter"
        )]
        [int]$offset,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "v10ByFilter"
        )]
        [ValidateRange(1, 1000)]
        [int]$limit,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "v10ByFilter"
        )]
        [string]$filter,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "v9"
        )]
        [ValidateLength(0, 500)]
        [string]$Keywords,

        [parameter(
            Mandatory = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = "v9"
        )]
        [ValidateLength(0, 28)]
        [string]$Safe,

        [parameter(
            Mandatory = $false,
            ValueFromPipelineByPropertyName = $false
        )]
        [int]$TimeoutSec

    )

    BEGIN {
        $MinimumVersion = [System.Version]"10.4"
        $RequiredVersion = [System.Version]"11.2"
        $Version114 = [System.Version]"11.4"
    }#begin

    PROCESS {

        #Get Parameters to include in request
        $boundParameters = $PSBoundParameters | Get-PASParameter -ParametersToRemove TimeoutSec, modificationTime, SafeName

        #Version 10.4 process
        If ($PSCmdlet.ParameterSetName -match "v10") {

            $FilterList = [Collections.Generic.List[Object]]@()

            switch ($PSBoundParameters) {

                ( { $PSItem.ContainsKey("modificationTime") }) {
                    #check required version
                    Assert-VersionRequirement -ExternalVersion $Script:ExternalVersion -RequiredVersion $Version114

                    #convert to unix time
                    #add result to FilterList
                    $null = $FilterList.Add("modificationTime gte $([math]::Round($(Get-Date $PSBoundParameters["modificationTime"] -UFormat %s)))")
                }

                ( { $PSItem.ContainsKey("searchType") }) {
                    #check required version
                    Assert-VersionRequirement -ExternalVersion $Script:ExternalVersion -RequiredVersion $RequiredVersion
                }

                ( { $PSItem.ContainsKey("safeName") }) {
                    #check required version
                    Assert-VersionRequirement -ExternalVersion $Script:ExternalVersion -RequiredVersion $MinimumVersion

                    #add result to FilterList
                    $null = $FilterList.Add("safeName eq $safeName")

                }

                default {
                    #check minimum version
                    Assert-VersionRequirement -ExternalVersion $Script:ExternalVersion -RequiredVersion $MinimumVersion
                }

            }

            #assign new type name
            $typeName = "psPAS.CyberArk.Vault.Account.V10"

            #define base URL
            $URI = "$Script:BaseURI/api/Accounts"

        }

        #legacy process
        If ($PSCmdlet.ParameterSetName -eq "v9") {

            #assign type name
            $typeName = "psPAS.CyberArk.Vault.Account"

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

        }

        If ($PSCmdlet.ParameterSetName -eq "v10ByID") {

            #define "by ID" URL
            $URI = "$URI/$id"

        }
        Else {

            If ($FilterList.count -gt 0) {

                $boundParameters["filter"] = $FilterList -join " AND "

            }

            #Create Query String, escaped for inclusion in request URL
            $queryString = $boundParameters | ConvertTo-QueryString

            If ($queryString) {

                #Build URL from base URL
                $URI = "$URI`?$queryString"

            }

        }

        #Send request to web service
        $result = Invoke-PASRestMethod -Uri $URI -Method GET -WebSession $Script:WebSession -TimeoutSec $TimeoutSec

        If ($result) {

            #Get count of accounts found
            $count = $($result.count)

            #Version 10.4 individual account process
            If ($PSCmdlet.ParameterSetName -eq "v10ByID") {

                #return expected single result
                $return = $result

            }

            #If accounts found
            if ($count -gt 0) {

                #Version 10.4 query process
                If ($PSCmdlet.ParameterSetName -eq "v10ByQuery") {

                    #to store list of query results
                    $AccountList = [Collections.Generic.List[Object]]@()

                    #add resultst to list
                    $null = $AccountList.Add($result.value)

                    #iterate any nextLinks
                    $NextLink = $result.nextLink
                    While ( $null -ne $NextLink ) {
                        $URI = "$Script:BaseURI/$NextLink"
                        $result = Invoke-PASRestMethod -Uri $URI -Method GET -WebSession $Script:WebSession -TimeoutSec $TimeoutSec
                        $NextLink = $result.nextLink
                        $null = $AccountList.AddRange(($result.value))
                    }

                    #return list
                    $return = $AccountList

                }

                #legacy process
                If ($PSCmdlet.ParameterSetName -eq "v9") {

                    #If multiple accounts found
                    if ($count -gt 1) {

                        #Alert that web service only displays information on first result
                        Write-Warning "$count matching accounts found. Only the first result will be returned"

                    }

                    #Get account details from search result
                    $account = ($result | Select-Object accounts).accounts

                    #Get account properties from found account
                    $properties = ($account | Select-Object -ExpandProperty properties)

                    #Get internal properties from found account
                    $InternalProperties = ($account | Select-Object -ExpandProperty InternalProperties)

                    $InternalProps = New-Object -TypeName psobject

                    #For every account property
                    For ($int = 0; $int -lt $InternalProperties.length; $int++) {

                        $InternalProps |

                        #Add each property name and value as object property of $InternalProps
                        Add-ObjectDetail -PropertyToAdd @{$InternalProperties[$int].key = $InternalProperties[$int].value } -Passthru $false

                    }

                    #Create output object
                    $return = New-object -TypeName psobject -Property @{

                        #Internal Unique ID of Account
                        "AccountID"          = $($account | Select-Object -ExpandProperty AccountID)

                        #InternalProperties object
                        "InternalProperties" = $InternalProps

                    }

                    #For every account property
                    For ($int = 0; $int -lt $properties.length; $int++) {

                        $return |

                        #Add each property name and value to results
                        Add-ObjectDetail -PropertyToAdd @{$properties[$int].key = $properties[$int].value } -Passthru $false

                    }

                }

            }

        }

        if ($return) {

            #Return Results
            $return | Add-ObjectDetail -typename $typeName

        }

    }#process

    END { }#end

}