PPS.psm1
# Override Write-Verbose in this module so calling function is added to the message function script:Write-Verbose { [CmdletBinding()] param ( [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)] [String] $Message ) begin {} process { try { $PSBoundParameters['Message'] = $((Get-PSCallStack)[1].Command) + ': ' + $PSBoundParameters['Message'] } catch {} Microsoft.PowerShell.Utility\Write-Verbose @PSBoundParameters } end {} } function Connect-Pps { <# .SYNOPSIS Connect to Pleasant Password Server .DESCRIPTION Connect to Pleasant Password Server .PARAMETER Uri URI of server to connect to, eg. https://password.company.tld:10001 .PARAMETER Credential Credential object with username and password used to connect to Pleasant Password Server with .PARAMETER Username Username used to connect to Pleasant Password Server with .PARAMETER Password Password used to connect to Pleasant Password Server with .PARAMETER Session Makes it possible to connect to multiple Pleasant Password Servers .EXAMPLE Connect-Pps -Uri https://password.company.tld:10001 #> [CmdletBinding(DefaultParameterSetName='Default')] [OutputType([PSCustomObject])] param ( [Parameter(Mandatory=$true, Position=0)] [string] $Uri, [Parameter(ParameterSetName='Credential', Mandatory=$true, ValueFromPipelineByPropertyName=$true)] [pscredential] $Credential, [Parameter(ParameterSetName='UserPass', Mandatory=$true, ValueFromPipelineByPropertyName=$true)] [string] $Username, [Parameter(ParameterSetName='UserPass', Mandatory=$true, ValueFromPipelineByPropertyName=$true)] [string] $Password, [Parameter()] [string] $Session = 'Default' ) begin { Write-Verbose -Message "Begin (ErrorActionPreference: $ErrorActionPreference)" $origErrorActionPreference = $ErrorActionPreference $verbose = $PSBoundParameters.ContainsKey('Verbose') -or ($VerbosePreference -ne 'SilentlyContinue') # FIXXXME - should this be moved out - so it is run when module is imported? if (-not $script:SessionList) { Write-Verbose -Message 'Creating session list' $script:SessionList = @{} } } process { Write-Verbose -Message "Process begin (ErrorActionPreference: $ErrorActionPreference)" try { # Make sure that we don't continue on error, and that we catches the error $ErrorActionPreference = 'Stop' if ($Uri -notmatch ':') {$Uri = "https://${Uri}:10001"} $Uri = $Uri -replace '/$' if (-not ($Credential -or $Username -or $Password)) { $PSBoundParameters['Credential'] = Get-Credential -Message 'PPS' } $oauth2Params = @{ Uri = "$Uri/OAuth2/Token" ReturnHeader = $true } $PSBoundParameters.GetEnumerator() | Where-Object -Property Key -In -Value 'Credential','Username','Password' | ForEach-Object -Process { $oauth2Params[$_.Key] = $_.Value } $script:SessionList[$Session] = [PSCustomObject] @{ Uri = $Uri Headers = Connect-OAuth2 @oauth2Params } } catch { Write-Verbose -Message "Encountered an error: $_" Write-Error -ErrorAction $origErrorActionPreference -Exception $_.Exception } finally { $ErrorActionPreference = $origErrorActionPreference } Write-Verbose -Message 'Process end' } end { Write-Verbose -Message 'End' } } function Export-PpsEntry { <# .SYNOPSIS xxx .DESCRIPTION xxx .PARAMETER RootPath xxx .PARAMETER WithId xxx .PARAMETER Session Makes it possible to connect to multiple Pleasant Password Servers .EXAMPLE xxx #> [CmdletBinding()] [OutputType([PSCustomObject])] param ( [Parameter(Mandatory=$true)] [string] $RootPath, [Parameter()] [switch] $WithId, [Parameter()] [string] $Session = 'Default' ) begin { Write-Verbose -Message "Begin (ErrorActionPreference: $ErrorActionPreference)" $origErrorActionPreference = $ErrorActionPreference $verbose = $PSBoundParameters.ContainsKey('Verbose') -or ($VerbosePreference -ne 'SilentlyContinue') $p = @{ Session = $Session } function GetGrp ([guid] $GroupId, [string[]] $Path = @()) { $group = Get-PpsGroup @p -Id $GroupId $group.Credentials | ForEach-Object -Process { $e = [PSCustomObject] @{ Path = $Path -join '/' Name = $_.Name Username = $_.UserName Password = Get-PpsEntry -Id $_.Id -PasswordOnly Url = $_.Url Notes = $_.Notes } if ($WithId) {$e | Add-Member -NotePropertyName Id -NotePropertyValue $_.Id} $e } $group.Children | ForEach-Object -Process { GetGrp -GroupId $_.Id -Path ($Path + $_.Name) } } } process { Write-Verbose -Message "Process begin (ErrorActionPreference: $ErrorActionPreference)" try { # Make sure that we don't continue on error, and that we catches the error $ErrorActionPreference = 'Stop' $groupId = Get-PpsGroup @p -Path $RootPath -ReturnId GetGrp -GroupId $groupId } catch { Write-Verbose -Message "Encountered an error: $_" Write-Error -ErrorAction $origErrorActionPreference -Exception $_.Exception } finally { $ErrorActionPreference = $origErrorActionPreference } Write-Verbose -Message 'Process end' } end { Write-Verbose -Message 'End' } } function Get-PpsEntry { <# .SYNOPSIS Get credential entry from Pleasant Password Server .DESCRIPTION Get credential entry from Pleasant Password Server .PARAMETER Id ID of entry to get info about .PARAMETER Path xxx .PARAMETER Name xxx .PARAMETER AllowMultiple xxx .PARAMETER ReturnPSCredential xxx .PARAMETER Session Makes it possible to connect to multiple Pleasant Password Servers .EXAMPLE Get-PpsEntry -Id 5cbfabe7-70ee-4041-a1e0-263c9170f650 #> [CmdletBinding(DefaultParameterSetName='Id')] [OutputType([PSCustomObject], ParameterSetName='Id')] [OutputType([PSCustomObject], ParameterSetName='Path')] [OutputType([PSCredential], ParameterSetName='IdCred')] [OutputType([PSCredential], ParameterSetName='PathCred')] param ( [Parameter(ParameterSetName='Id', Mandatory=$true, Position=0)] [Parameter(ParameterSetName='IdCred', Mandatory=$true, Position=0)] [Parameter(ParameterSetName='IdPw', Mandatory=$true, Position=0)] [guid] $Id, [Parameter(ParameterSetName='Path', Mandatory=$true)] [Parameter(ParameterSetName='PathCred', Mandatory=$true)] [string] $Path, [Parameter(ParameterSetName='Path')] [Parameter(ParameterSetName='PathCred')] [string] $Name, [Parameter(ParameterSetName='Path')] [Parameter(ParameterSetName='PathCred')] [switch] $AllowMultiple, [Parameter(ParameterSetName='IdCred', Mandatory=$true)] [Parameter(ParameterSetName='PathCred', Mandatory=$true)] [switch] $ReturnPSCredential, [Parameter(ParameterSetName='IdPw', Mandatory=$true)] [switch] $PasswordOnly, [Parameter()] [string] $Session = 'Default' ) begin { Write-Verbose -Message "Begin (ErrorActionPreference: $ErrorActionPreference)" $origErrorActionPreference = $ErrorActionPreference $verbose = $PSBoundParameters.ContainsKey('Verbose') -or ($VerbosePreference -ne 'SilentlyContinue') } process { Write-Verbose -Message "Process begin (ErrorActionPreference: $ErrorActionPreference)" try { # Make sure that we don't continue on error, and that we catches the error $ErrorActionPreference = 'Stop' $p = @{ Session = $Session } if ($PasswordOnly -and $Id) { $entry = @([PSCustomObject] @{Id = $Id; Password = ''}) } elseif ($Id) { $entry = @(Invoke-PpsApiRequest @p -Uri "credential/$Id") } elseif ($Path) { $group = Get-PpsGroup @p -Path $Path $entry = @($group.Credentials) if ($Name) { $entry = @($entry | Where-Object -Property Name -Like -Value $Name) } if ($entry.Count -gt 1 -and -not $AllowMultiple) { throw "More than one ($($entry.Count)) entries returned and -AllowMultiple is not set" } } else { throw 'Should never happen' } foreach ($e in $entry) { $e.Password = Invoke-PpsApiRequest @p -Uri "credential/$($e.Id)/password" } # Return if ($ReturnPSCredential) { foreach ($e in $entry) { [pscredential]::new($e.Username, ($e.Password | ConvertTo-SecureString -AsPlainText -Force)) } } elseif ($PasswordOnly) { foreach ($e in $entry) { $e.Password } } else { $entry } } catch { Write-Verbose -Message "Encountered an error: $_" Write-Error -ErrorAction $origErrorActionPreference -Exception $_.Exception } finally { $ErrorActionPreference = $origErrorActionPreference } Write-Verbose -Message 'Process end' } end { Write-Verbose -Message 'End' } } function Get-PpsGroup { <# .SYNOPSIS Get credential group (folder) from Pleasant Password Server .DESCRIPTION Get credential group (folder) from Pleasant Password Server .PARAMETER All xxx .PARAMETER Id ID of group to get info about .PARAMETER Path xxx .PARAMETER ReturnId xxx .PARAMETER Session Makes it possible to connect to multiple Pleasant Password Servers .EXAMPLE Get-PpsGroup -Id f6190167-a9a1-4386-a8cd-ae46008c9188 .EXAMPLE Get-PpsGroup -All #> [CmdletBinding()] [OutputType([PSCustomObject])] param ( [Parameter(ParameterSetName='All', Mandatory=$true)] [switch] $All, [Parameter(ParameterSetName='Id', Mandatory=$true, Position=0)] [guid] $Id, [Parameter(ParameterSetName='Path', Mandatory=$true, Position=0)] [string] $Path, [Parameter(ParameterSetName='Id')] [Parameter(ParameterSetName='Path')] [switch] $ReturnId, [Parameter()] [string] $Session = 'Default' ) begin { Write-Verbose -Message "Begin (ErrorActionPreference: $ErrorActionPreference)" $origErrorActionPreference = $ErrorActionPreference $verbose = $PSBoundParameters.ContainsKey('Verbose') -or ($VerbosePreference -ne 'SilentlyContinue') # FIXXXME - should this be moved out - so it is run when module is imported? if (-not $script:GroupCache) { Write-Verbose -Message 'Creating group cache' $script:GroupCache = @{} } } process { Write-Verbose -Message "Process begin (ErrorActionPreference: $ErrorActionPreference)" try { # Make sure that we don't continue on error, and that we catches the error $ErrorActionPreference = 'Stop' $p = @{ Session = $Session } $uri = 'credentialgroup' if ($Path) { if ($script:GroupCache.ContainsKey($Path)) { $Id = $script:GroupCache[$Path] } elseif ($Path -ceq 'Root') { $script:GroupCache[$Path] = $Id = Invoke-PpsApiRequest @p -Uri "$uri/root" } elseif ($Path -notmatch '/') { throw "First part of path should always be Root, not $Path" } else { $parentPath, $name = $Path -split '/(?=[^/]*$)' $parent = Get-PpsGroup @p -Path $parentPath try { $script:GroupCache[$Path] = $Id = $parent.Children | Where-Object -Property Name -EQ -Value $Name | Select-Object -First 1 -ExpandProperty Id } catch { throw "Group path $Path not found" } } } if ($Id) { $uri = "$uri/$Id" } if ($ReturnId) { # Return $Id } else { # Return Invoke-PpsApiRequest @p -Uri $uri } } catch { Write-Verbose -Message "Encountered an error: $_" Write-Error -ErrorAction $origErrorActionPreference -Exception $_.Exception } finally { $ErrorActionPreference = $origErrorActionPreference } Write-Verbose -Message 'Process end' } end { Write-Verbose -Message 'End' } } function Import-PpsEntry { <# .SYNOPSIS xxx .DESCRIPTION xxx .PARAMETER RootPath xxx .PARAMETER InputObject xxx .PARAMETER NoCheck xxx .PARAMETER CheckProperty xxx .PARAMETER Session Makes it possible to connect to multiple Pleasant Password Servers .EXAMPLE xxx .EXAMPLE xxx #> [CmdletBinding()] [OutputType([PSCustomObject])] param ( [Parameter(Mandatory=$true)] [string] $RootPath, [Parameter(Mandatory=$true, ValueFromPipeline=$true)] [PSCustomObject] $InputObject, [Parameter()] [switch] $NoCheck, [Parameter()] [string[]] $CheckProperty = @('Name', 'Username'), [Parameter()] [string] $Session = 'Default' ) begin { Write-Verbose -Message "Begin (ErrorActionPreference: $ErrorActionPreference)" $origErrorActionPreference = $ErrorActionPreference $verbose = $PSBoundParameters.ContainsKey('Verbose') -or ($VerbosePreference -ne 'SilentlyContinue') $allProperties = @('Name', 'Username', 'Password', 'Url', 'Notes') if (-not $NoCheck) { # Some versions of PowerShell doesn't seem to trigger ValidateScript on an empty array. That's why it's located here if (-not $CheckProperty.Count) {throw 'CheckProperty should not be empty'} $CheckProperty | ForEach-Object -Process {if ($_ -notin $allProperties) {throw "$_ is not allowed in CheckProperty, only $($allProperties -join ',') is allowed"}} $CheckProperty = @('Path') + $CheckProperty $existing = Export-PpsEntry -RootPath $RootPath -WithId $existingHash = $existing | Group-Object -Property $CheckProperty -AsHashTable -AsString } } process { Write-Verbose -Message "Process begin (ErrorActionPreference: $ErrorActionPreference)" try { # Make sure that we don't continue on error, and that we catches the error $ErrorActionPreference = 'Stop' $p = @{ Session = $Session } $fullPath = if ($InputObject.Path) {$RootPath + '/' + $InputObject.Path} else {$RootPath} $entryParams = @{} $allProperties | ForEach-Object -Process { $entryParams[$_] = $InputObject.$_ } if ($NoCheck) { $null = New-PpsEntry @p -Path $fullPath @entryParams } else { $key = ($InputObject | Group-Object -Property $CheckProperty -AsHashTable -AsString).Keys | Select-Object -First 1 if ($e = @($existingHash[$key] | Where-Object -FilterScript {-not $_._PROCESSED_})) { if ($e.Count -gt 1) {Write-Warning -Message "Found $($e.Count) objects matching ""$key"", just selecting first match"} $e = $e[0] $e | Add-Member -NotePropertyName _PROCESSED_ -NotePropertyValue $true if (Compare-Object -ReferenceObject $e -DifferenceObject $InputObject -Property $allProperties) { "Updating $key" | Write-Host $null = Get-PpsEntry @p -Id $e.Id | Set-PpsEntry @p @entryParams } else { "OK $key" | Write-Host } } else { "Creating $key" | Write-Host $null = New-PpsEntry @p -Path $fullPath @entryParams } } } catch { Write-Verbose -Message "Encountered an error: $_" Write-Error -ErrorAction $origErrorActionPreference -Exception $_.Exception } finally { $ErrorActionPreference = $origErrorActionPreference } Write-Verbose -Message 'Process end' } end { # Not processed #$existing | Where-Object -FilterScript {-not $_._PROCESSED_} Write-Verbose -Message 'End' } } function Invoke-PpsApiRequest { <# .SYNOPSIS Invoke API request against Pleasant Password Server .DESCRIPTION Invoke API request against Pleasant Password Server .PARAMETER Uri xxx .PARAMETER Method xxx .PARAMETER Data xxx .PARAMETER Session Makes it possible to connect to multiple Pleasant Password Servers .EXAMPLE xxx #> [CmdletBinding()] [OutputType([PSCustomObject])] param ( [Parameter(Mandatory=$true)] [string] $Uri, [Parameter()] [Microsoft.PowerShell.Commands.WebRequestMethod] $Method = 'Get', [Parameter()] [object] $Data, [Parameter()] [string] $Session = 'Default' ) begin { Write-Verbose -Message "Begin (ErrorActionPreference: $ErrorActionPreference)" $origErrorActionPreference = $ErrorActionPreference $verbose = $PSBoundParameters.ContainsKey('Verbose') -or ($VerbosePreference -ne 'SilentlyContinue') # FIXXXME - should this be moved out - so it is run when module is imported? if (-not $script:SessionList) { Write-Verbose -Message 'Creating session list' $script:SessionList = @{} } } process { Write-Verbose -Message "Process begin (ErrorActionPreference: $ErrorActionPreference)" try { # Make sure that we don't continue on error, and that we catches the error $ErrorActionPreference = 'Stop' if (-not ($s = $script:SessionList[$Session])) { throw "Session <$Session> not found" } $requestParams = @{ Method = $Method Uri = "$($s.Uri)/api/v4/rest/$Uri" # FIXXXME - v4 should'n be hardcoded here! Headers = $s.Headers UseBasicParsing = $true } if ($Data) { $requestParams['Body'] = ConvertTo-Json -Compress -Depth 9 -InputObject $Data $requestParams['ContentType'] = 'application/json; charset=utf-8' } Write-Verbose -Message ($requestParams | ConvertTo-Json) # Return Invoke-RestMethod @requestParams } catch { Write-Verbose -Message "Encountered an error: $_" Write-Error -ErrorAction $origErrorActionPreference -Exception $_.Exception } finally { $ErrorActionPreference = $origErrorActionPreference } Write-Verbose -Message 'Process end' } end { Write-Verbose -Message 'End' } } function New-PpsEntry { <# .SYNOPSIS Create new credential entry in Pleasant Password Server .DESCRIPTION Create new credential entry in Pleasant Password Server .PARAMETER Entry Object with data to create in Pleasant Password Server .PARAMETER GroupId ID of credential group to create credential entry in .PARAMETER Name Name of credential in Pleasant Password Server .PARAMETER Username Username of credential in Pleasant Password Server .PARAMETER Password Password of credential in Pleasant Password Server .PARAMETER PSCredential xxx .PARAMETER Url Url of credential in Pleasant Password Server .PARAMETER Notes Notes of credential in Pleasant Password Server .PARAMETER Session Makes it possible to connect to multiple Pleasant Password Servers .EXAMPLE New-PpsEntry -GroupId f6190167-a9a1-4386-a8cd-ae46008c9188 -Name name -Username uname -Password pw -Url http://abc -Notes "This i a note" .EXAMPLE @{GroupId='f6190167-a9a1-4386-a8cd-ae46008c9188'; Name='name'; Username='user'; Password='pw'} | New-PpsEntry #> [CmdletBinding()] [OutputType([PSCustomObject])] param ( [Parameter(ParameterSetName='Entry', Mandatory=$true, ValueFromPipeline=$true)] [PSCustomObject] $Entry, [Parameter(ParameterSetName='Properties', Mandatory=$true)] [Parameter(ParameterSetName='PSCredential', Mandatory=$true)] [guid] $GroupId, [Parameter(ParameterSetName='PropertiesPath', Mandatory=$true)] [Parameter(ParameterSetName='PSCredentialPath', Mandatory=$true)] [string] $Path, [Parameter(ParameterSetName='Properties')] [Parameter(ParameterSetName='PSCredential')] [Parameter(ParameterSetName='PropertiesPath')] [Parameter(ParameterSetName='PSCredentialPath')] [AllowNull()] [AllowEmptyString()] [string] $Name, [Parameter(ParameterSetName='Properties')] [Parameter(ParameterSetName='PropertiesPath')] [AllowNull()] [AllowEmptyString()] [string] $Username, [Parameter(ParameterSetName='Properties')] [Parameter(ParameterSetName='PropertiesPath')] [AllowNull()] [AllowEmptyString()] [string] $Password, [Parameter(ParameterSetName='PSCredential', Mandatory=$true)] [Parameter(ParameterSetName='PSCredentialPath', Mandatory=$true)] [PSCredential] $PSCredential, [Parameter(ParameterSetName='Properties')] [Parameter(ParameterSetName='PSCredential')] [Parameter(ParameterSetName='PropertiesPath')] [Parameter(ParameterSetName='PSCredentialPath')] [AllowNull()] [AllowEmptyString()] [string] $Url, [Parameter(ParameterSetName='Properties')] [Parameter(ParameterSetName='PSCredential')] [Parameter(ParameterSetName='PropertiesPath')] [Parameter(ParameterSetName='PSCredentialPath')] [AllowNull()] [AllowEmptyString()] [string] $Notes, [Parameter()] [string] $Session = 'Default' ) begin { Write-Verbose -Message "Begin (ErrorActionPreference: $ErrorActionPreference)" $origErrorActionPreference = $ErrorActionPreference $verbose = $PSBoundParameters.ContainsKey('Verbose') -or ($VerbosePreference -ne 'SilentlyContinue') } process { Write-Verbose -Message "Process begin (ErrorActionPreference: $ErrorActionPreference)" try { # Make sure that we don't continue on error, and that we catches the error $ErrorActionPreference = 'Stop' $p = @{ Session = $Session } if (-not $Entry) { if ($PSCredential) { $Username = $PSCredential.UserName $Password = $PSCredential.GetNetworkCredential().Password } if ($Path) { $GroupId = New-PpsGroup @p -Path $Path -ReturnId } $Entry = [PSCustomObject] @{ GroupId = $GroupId Name = $Name Username = $Username Password = $Password Url = $Url Notes = $Notes } } $id = Invoke-PpsApiRequest @p -Uri "credential" -Data $Entry -Method Post # Return [PSCustomObject] @{ Id = $id Uri = "$($script:SessionList[$Session].Uri)/WebClient/Main?itemId=$id" } } catch { Write-Verbose -Message "Encountered an error: $_" Write-Error -ErrorAction $origErrorActionPreference -Exception $_.Exception } finally { $ErrorActionPreference = $origErrorActionPreference } Write-Verbose -Message 'Process end' } end { Write-Verbose -Message 'End' } } function New-PpsGroup { <# .SYNOPSIS Create new credential group (folder) from Pleasant Password Server .DESCRIPTION Create new credential group (folder) from Pleasant Password Server .PARAMETER Group Object contining group info .PARAMETER ParentId ID of parent group .PARAMETER Name Name of the new group (folder) .PARAMETER Path xxx .PARAMETER ReturnId xxx .PARAMETER Session Makes it possible to connect to multiple Pleasant Password Servers .EXAMPLE New-PpsGroup -ParentId f6190167-a9a1-4386-a8cd-ae46008c9188 -Name "New Password Group" #> [CmdletBinding()] [OutputType([PSCustomObject])] param ( [Parameter(ParameterSetName='Group', Mandatory=$true, ValueFromPipeline=$true)] [PSCustomObject] $Group, [Parameter(ParameterSetName='Properties', Mandatory=$true)] [guid] $ParentId, [Parameter(ParameterSetName='Properties', Mandatory=$true)] [string] $Name, [Parameter(ParameterSetName='Path', Mandatory=$true)] [string] $Path, [Parameter()] [switch] $ReturnId, [Parameter()] [string] $Session = 'Default' ) begin { Write-Verbose -Message "Begin (ErrorActionPreference: $ErrorActionPreference)" $origErrorActionPreference = $ErrorActionPreference $verbose = $PSBoundParameters.ContainsKey('Verbose') -or ($VerbosePreference -ne 'SilentlyContinue') } process { Write-Verbose -Message "Process begin (ErrorActionPreference: $ErrorActionPreference)" try { # Make sure that we don't continue on error, and that we catches the error $ErrorActionPreference = 'Stop' $p = @{ Session = $Session } if ($Path) { try { # Return Get-PpsGroup @p -Path $Path -ReturnId:$ReturnId } catch { if ($Path -notmatch '/') { throw "First part of path should always be Root, not $Path" } $parentPath, $n = $Path -split '/(?=[^/]*$)' $parentId = New-PpsGroup @p -Path $parentPath -ReturnId # Return New-PpsGroup @p -ParentId $ParentId -Name $n -ReturnId:$ReturnId } } else { if (-not $Group) { $Group = [PSCustomObject] @{ ParentId = $ParentId Name = $Name } } $id = Invoke-PpsApiRequest @p -Uri "credentialgroup" -Data $Group -Method Post # Return Get-PpsGroup @p -Id $Id -ReturnId:$ReturnId } } catch { Write-Verbose -Message "Encountered an error: $_" Write-Error -ErrorAction $origErrorActionPreference -Exception $_.Exception } finally { $ErrorActionPreference = $origErrorActionPreference } Write-Verbose -Message 'Process end' } end { Write-Verbose -Message 'End' } } function Set-PpsEntry { <# .SYNOPSIS Update existing credential entry in Pleasant Password Server .DESCRIPTION Update existing credential entry in Pleasant Password Server .PARAMETER Entry Object with updated info .PARAMETER Name Name of credential in Pleasant Password Server .PARAMETER Username Username of credential in Pleasant Password Server .PARAMETER Password Password of credential in Pleasant Password Server .PARAMETER PSCredential xxx .PARAMETER Url Url of credential in Pleasant Password Server .PARAMETER Notes Notes of credential in Pleasant Password Server .PARAMETER Session Makes it possible to connect to multiple Pleasant Password Servers .EXAMPLE $e=Get-PpsEntry -Id c079a48c-a465-4605-9477-2b4baa743e6f; $e.Username='user'; $e|Set-PpsEntry #> [CmdletBinding(DefaultParameterSetName='Properties')] [OutputType([PSCustomObject])] param ( [Parameter(Mandatory=$true, ValueFromPipeline=$true)] [PSCustomObject] $Entry, [Parameter(ParameterSetName='Properties')] [Parameter(ParameterSetName='PSCredential')] [AllowNull()] [AllowEmptyString()] [string] $Name, [Parameter(ParameterSetName='Properties')] [AllowNull()] [AllowEmptyString()] [string] $Username, [Parameter(ParameterSetName='Properties')] [AllowNull()] [AllowEmptyString()] [string] $Password, [Parameter(ParameterSetName='PSCredential', Mandatory=$true)] [PSCredential] $PSCredential, [Parameter(ParameterSetName='Properties')] [Parameter(ParameterSetName='PSCredential')] [AllowNull()] [AllowEmptyString()] [string] $Url, [Parameter(ParameterSetName='Properties')] [Parameter(ParameterSetName='PSCredential')] [AllowNull()] [AllowEmptyString()] [string] $Notes, [Parameter()] [string] $Session = 'Default' ) begin { Write-Verbose -Message "Begin (ErrorActionPreference: $ErrorActionPreference)" $origErrorActionPreference = $ErrorActionPreference $verbose = $PSBoundParameters.ContainsKey('Verbose') -or ($VerbosePreference -ne 'SilentlyContinue') } process { Write-Verbose -Message "Process begin (ErrorActionPreference: $ErrorActionPreference)" try { # Make sure that we don't continue on error, and that we catches the error $ErrorActionPreference = 'Stop' $p = @{ Session = $Session } if ($PSCredential) { $PSBoundParameters['Username'] = $PSCredential.UserName $PSBoundParameters['Password'] = $PSCredential.GetNetworkCredential().Password } 'Name', 'Username', 'Password', 'Url', 'Notes' | ForEach-Object -Process { if ($PSBoundParameters.ContainsKey($_)) { $Entry.$_ = $PSBoundParameters[$_] } } $id = $Entry.Id $null = Invoke-PpsApiRequest @p -Uri "credential/$($Entry.Id)" -Data $Entry -Method Put # Return [PSCustomObject] @{ Id = $id Uri = "$($script:SessionList[$Session].Uri)/WebClient/Main?itemId=$id" } } catch { Write-Verbose -Message "Encountered an error: $_" Write-Error -ErrorAction $origErrorActionPreference -Exception $_.Exception } finally { $ErrorActionPreference = $origErrorActionPreference } Write-Verbose -Message 'Process end' } end { Write-Verbose -Message 'End' } } Export-ModuleMember -Function New-PpsEntry Export-ModuleMember -Function New-PpsGroup Export-ModuleMember -Function Connect-Pps Export-ModuleMember -Function Get-PpsGroup Export-ModuleMember -Function Invoke-PpsApiRequest Export-ModuleMember -Function Import-PpsEntry Export-ModuleMember -Function Get-PpsEntry Export-ModuleMember -Function Set-PpsEntry Export-ModuleMember -Function Export-PpsEntry |