Hello,
If you use powershell to make api calls, here are some functions I’ve developed, starting with a function I found on this forum for the connection.
It’s not perfect, but that’s the whole point of sharing.
Theses functions require PSPGP Module !
function Get-GFTPassboltConnection {
<#
.SYNOPSIS
This function is required for all other functions (Connection begin)
.DESCRIPTION
This function allow you to connect.
Stock your privatekey in secure location (registry with controlled acl for example)
.NOTES
Version: 1.0
Changelog: N/A
Author: Odric BLUM
Filename: Get-GFTPassword.psm1
.Example
Get-GFTPassboltConnection -Credential (Get-Credential) -PrivateKeyContent (Get-Content MyPrivateKey) -FingerPrint "MyFingerPrint"
.Example
Get-GFTPassboltConnection -PrivateKeyContent (Get-Content MyPrivateKey)
.Example
Get-GFTPassboltConnection
#>
param (
[Parameter(
Mandatory = $false,
ValueFromPipeLine = $true,
ValueFromPipelineByPropertyName = $true
)]
[Alias(
'PSCredential'
)]
[ValidateNotNull()]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credentials,
[string]$Server = "https://mypassbolt",
[String]$PrivateKeyContent = (Get-ItemProperty 'HKLM:\Software\Microsoft\APIPass\').PrivateKey,
[string]$FingerPrint = (Get-ItemProperty 'HKLM:\Software\Microsoft\APIPass\').FingerPrint,
[string]$SecretPath = "C:\PowerShell\Temp\Secret$(Get-Random -Minimum 123456 -Maximum 789456)"
)
$ProgressPreference = 'SilentlyContinue'
if (!($Credentials)) {
$AccountXML = Import-Clixml "PATH TO XML CREDS"
$Credentials = New-Object System.Management.Automation.PSCredential($AccountXML.Username, (ConvertTo-SecureString -String "$($AccountXML.Password)" -Key $($AccountXML.Key)))
}
if (!(Test-Path $SecretPath)) {
New-Item $SecretPath -ItemType Directory -Force -Confirm:$false | Out-Null
} else {
Remove-Item $SecretPath -Recurse -Force -Confirm:$false
New-Item $SecretPath -ItemType Directory -Force -Confirm:$false | Out-Null
}
$ACL = Get-Acl $SecretPath
$ACL.SetAccessRuleProtection($true, $false)
$UserToAdd = [System.Security.Principal.NTAccount]$Env:USERNAME
$Permissions = $UserToAdd,"FullControl","ObjectInherit,ContainerInherit","None","Allow"
$Rule = New-Object System.Security.AccessControl.FileSystemAccessRule($Permissions)
$ACL.AddAccessRule($Rule)
$FileInfos = Get-Item $SecretPath
[System.IO.FileSystemAclExtensions]::SetAccessControl($FileInfos, $ACL)
$Password = $Credentials.GetNetworkCredential().Password
$UriLogin = '/auth/login.json'
$UriResourse = '/resources.json'
$Files = New-Item -Path $SecretPath -Name "$([System.IO.Path]::GetRandomFileName())$(Get-Random -Minimum 0 -Maximum 99999)" -ItemType File -Value $PrivateKeyContent
$Files = $Files.FullName
$Body = @{
'data[gpg_auth][keyid]' = $FingerPrint
}
$Response1 = Invoke-WebRequest -Uri ($Server+$UriLogin) -Method Post -ContentType 'multipart/form-data' -Form ($Body)
$DecryptedToken = Unprotect-PGP -FilePathPrivate $Files -Password $Password -String ([System.Web.HttpUtility]::UrlDecode($Response1.Headers.'X-GPGAuth-User-Auth-Token').Replace('\ ',' '))
$Body = @{
'data[gpg_auth][keyid]' = $FingerPrint
'data[gpg_auth][user_token_result]' = $DecryptedToken
}
$Response2 = Invoke-RestMethod -SkipCertificateCheck -UseBasicParsing -Uri ($Server+$UriLogin) -Method Post -ContentType 'multipart/form-data' -Form ($Body) -SessionVariable Session
$Response3 = Invoke-RestMethod -SkipCertificateCheck -UseBasicParsing -Uri ($Server) -Method Get -WebSession $Session
$csrfToken = ($Session.Cookies.GetAllCookies() | Where-Object {$_.Name -eq 'csrfToken'}).value
$Headers = @{
'X-CSRF-Token' = $csrfToken
}
$Session.Headers.Add("X-CSRF-Token","$csrfToken")
$Session.Headers.Add("SPath","$SecretPath")
$Session.Headers.Add("SSPath","$Files")
$Session.Headers.Add("Server","$Server")
$Session.Headers.Add("URIResources",$UriResourse)
Return $Session
}
function Stop-GFTPassboltConnection {
[CmdletBinding()]
param (
[Microsoft.PowerShell.Commands.WebRequestSession]$Session,
[string]$SecretPath = "C:\PowerShell\Temp\"
)
try {
if (!($Session)) {
$PathToDelete = (Join-Path $SecretPath "Secret*")
if (Test-Path $PathToDelete) {
Remove-Item $PathToDelete -Force -Confirm:$false -Recurse | Out-Null
}
} else {
$PathToDelete = $Session.Headers.SPath
if (Test-Path $PathToDelete) {
Remove-Item $PathToDelete -Force -Confirm:$false -Recurse | Out-Null
}
}
} catch {
$_.Exception.Message
}
}
function Get-GFTPassword {
<#
.SYNOPSIS
This function allow you to search password in Passbolt
.DESCRIPTION
This function allow you to search password in Passbolt with specific account.
You can filter your search with SearchMethod (uri, name, id) and SearchContent.
Require Module PSPGP (Install-Module -Name PSPGP -AllowClobber -Force -Scope AllUsers)
.NOTES
Version: 1.0
Changelog: N/A
Author: Odric BLUM
Filename: Get-GFTPassword.psm1
.Example
Get-GFTPassword
.Example
Get-GFTPassword -SearchMethod uri -SearchContent "http://mypassbolt"
.Example
Get-GFTPassword -SearchMethod name -SearchContent "My Service"
#>
param (
[Parameter(
Mandatory = $false,
ValueFromPipeLine = $true,
ValueFromPipelineByPropertyName = $true
)]
[Alias(
'PSCredential'
)]
[ValidateNotNull()]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credentials,
[Microsoft.PowerShell.Commands.WebRequestSession]$Session,
[ValidateSet("uri","name","id")]
[String]$SearchMethod,
[String]$SearchContent,
[switch]$Direct,
[string]$ID
)
Begin {
$ProgressPreference = 'SilentlyContinue'
if (!($Credentials)) {
$AccountXML = Import-Clixml "PATH TO XML CREDS"
$Credentials = New-Object System.Management.Automation.PSCredential($AccountXML.Username, (ConvertTo-SecureString -String "$($AccountXML.Password)" -Key $($AccountXML.Key)))
}
if (!($Session)) {
$Session = Get-GFTPassboltConnection
}
$params = @{}
if ($Session) {
$params['Session'] = $Session
}
$SecretPath = $Session.Headers.SPath
if (!($SecretPath)) {
Return "No secret found !"
}
$Files = $Session.Headers.SSPath
$Server = $Session.Headers.Server
$UriResourse = $Session.Headers.URIResources
$ProgressPreference = 'SilentlyContinue'
}
Process {
$Password = $Credentials.GetNetworkCredential().Password
$array = @()
if ($Direct) {
$Content = (Invoke-RestMethod -Uri ($Server+"/resources/$ID.json?api-version=v2&contain[secret]=1") -Method Get -WebSession $Session).Body
$Secret = Unprotect-PGP -FilePathPrivate $Files -Password $Password -String $($Content.Secrets.data)
if ($Secret -match 'description') {
$Description = $($Secret -split ",")[0] -replace '^\{"description":"', '' -replace '\"$',''
$Secret = $($Secret -split ",")[1] -replace '^"password":"', '' -replace '"\}$',''
} else {
$Description = ""
}
$Obj = @{
id = $Content.Id
Name = $Content.name
Username = $Content.username
Secret = $Secret
Description = $Description
uri = $Content.uri
}
$Array += [pscustomobject]$Obj
} else {
$Array = [System.Collections.ArrayList]::Synchronized((New-Object System.Collections.ArrayList))
$Resources = (Invoke-RestMethod -UseBasicParsing -SkipCertificateCheck -Uri ($Server+$UriResourse) -Method Get -WebSession $Session).Body
$Resources | ? {$_."$SearchMethod" -match "$SearchContent"} | % -Parallel {
$Server = $using:Server
$Session = $using:Session
$SecretPath = $using:SecretPath
$Files = $using:Files
$Array = $using:Array
$Password = $using:Password
(Invoke-RestMethod -UseBasicParsing -Uri ($Server+"/resources/$($_.id).json?api-version=v2&contain[secret]=1") -Method Get -WebSession $Session).Body |% -Parallel {
$Server = $using:Server
$Array = $using:Array
$Password = $using:Password
$Files = $using:Files
$Secret = Unprotect-PGP -FilePathPrivate $Files -Password $Password -String $($_.Secrets.data)
if ($Secret -match 'description') {
$Json = $Secret | ConvertFrom-Json
$Description = $Json.Description # $($Secret -split ",")[0] -replace '^\{"description":"', '' -replace '\"$',''
$Secret = $Json.Password #$($Secret -split ",")[1] -replace '^"password":"', '' -replace '"\}$',''
} else {
$Description = ""
}
$Obj = @{
id = $_.Id
Name = $_.name
Username = $_.username
Secret = $Secret
Description = $Description
uri = $_.uri
}
$Array.Add([pscustomobject]$Obj) | Out-Null
} -ThrottleLimit 10
}
}
Stop-GFTPassboltConnection @params
Return $Array
}
End {
Stop-GFTPassboltConnection @params
}
}
function Get-GFTPassboltPGPPubKey {
param (
[Microsoft.PowerShell.Commands.WebRequestSession]$Session
)
Begin {
$ProgressPreference = 'SilentlyContinue'
if (!($Session)) {
$Session = Get-GFTPassboltConnection
}
$params = @{}
if ($Session) {
$params['Session'] = $Session
}
$SecretPath = $Session.Headers.SPath
if (!($SecretPath)) {
Return "No secret found !"
}
$Server = $Session.Headers.Server
$ProgressPreference = 'SilentlyContinue'
}
Process {
$Content = (Invoke-RestMethod -Uri ($Server+"/gpgkeys.json") -Method Get -WebSession $Session).Body
Stop-GFTPassboltConnection
Return $Content
}
}
function New-GFTPassboltPassword {
param (
[Microsoft.PowerShell.Commands.WebRequestSession]$Session,
[String]$PublicKeyContent = (Get-GFTPassboltPGPPubKey | ? { $_.uid -match "APIPass" }).armored_key,
[String]$UserID = (Get-GFTPassboltPGPPubKey | ? { $_.uid -match "APIPass" }).user_id,
[String]$PasswordName,
[String]$PasswordUsername,
[String]$PasswordUrl,
[String]$PasswordDescription,
[String]$NewPassword
)
Begin {
$ProgressPreference = 'SilentlyContinue'
if (!($Session)) {
$Session = Get-GFTPassboltConnection
}
$params = @{}
if ($Session) {
$params['Session'] = $Session
}
$SecretPath = $Session.Headers.SPath
if (!($SecretPath)) {
Return "No secret found !"
}
$Files = $Session.Headers.SPath
$Server = $Session.Headers.Server
$ProgressPreference = 'SilentlyContinue'
$Files = New-Item -Path $SecretPath -Name "$([System.IO.Path]::GetRandomFileName())$(Get-Random -Minimum 0 -Maximum 99999)" -ItemType File
Set-Content -Path $Files.FullName -Value $PublicKeyContent
$Password = Protect-PGP -FilePathPublic $files.FullName -String $NewPassword
}
Process {
$Json = @{}
$Secrets = @{}
$Json['name'] = $PasswordName
$Json['username'] = $PasswordUsername
$Json['description'] = $PasswordDescription
$Json['uri'] = $PasswordUrl
$Secrets['user_id'] = $UserID
$Secrets['data'] = "$Password"
$Json.Add('secrets',@($Secrets))
$Json = $Json | ConvertTo-Json
$Content = Invoke-RestMethod -Uri ($Server+"/resources.json") -Method Post -WebSession $Session -Body $Json -ContentType 'application/json'
$Content.Body
}
}
function Remove-GFTPassboltPassword {
param (
[Microsoft.PowerShell.Commands.WebRequestSession]$Session,
[String]$PasswordID
)
Begin {
$ProgressPreference = 'SilentlyContinue'
if (!($Session)) {
$Session = Get-GFTPassboltConnection
}
$params = @{}
if ($Session) {
$params['Session'] = $Session
}
$Server = $Session.Headers.Server
$ProgressPreference = 'SilentlyContinue'
}
Process {
$Content = (Invoke-RestMethod -Uri ($Server+"/resources/$PasswordID.json") -Method Delete -WebSession $Session).Body
Stop-GFTPassboltConnection
Return $Content
}
}
function Get-GFTPassboltFolders {
param (
[Microsoft.PowerShell.Commands.WebRequestSession]$Session,
[String]$FolderID
)
Begin {
$ProgressPreference = 'SilentlyContinue'
if (!($Session)) {
$Session = Get-GFTPassboltConnection
}
$params = @{}
if ($Session) {
$params['Session'] = $Session
}
$Server = $Session.Headers.Server
$ProgressPreference = 'SilentlyContinue'
}
Process {
if ($FolderID) {
$Content = (Invoke-RestMethod -Uri ($Server+"/folders/$FolderID.json?contain[children_folders]=1&contain[children_resources]=1&contain[permission]=1") -Method Get -WebSession $Session).Body
} else {
$Content = (Invoke-RestMethod -Uri ($Server+"/folders.json") -Method Get -WebSession $Session).Body
}
Stop-GFTPassboltConnection
Return $Content
}
}
function Get-GFTShareInformations {
param (
[Microsoft.PowerShell.Commands.WebRequestSession]$Session
)
Begin {
$ProgressPreference = 'SilentlyContinue'
if (!($Session)) {
$Session = Get-GFTPassboltConnection
}
$params = @{}
if ($Session) {
$params['Session'] = $Session
}
$Server = $Session.Headers.Server
$ProgressPreference = 'SilentlyContinue'
}
Process {
$Content = (Invoke-RestMethod -Uri ($Server+"/share/search-aros.json?contain[children_folders]=1&contain[children_resources]=1&contain[permission]=1") -Method Get -WebSession $Session).Body
Stop-GFTPassboltConnection
Return $Content
}
}
function Move-GFTPassboltPasswordToFolder {
param (
[Microsoft.PowerShell.Commands.WebRequestSession]$Session,
[String]$PasswordID,
[String]$FolderID
)
Begin {
$ProgressPreference = 'SilentlyContinue'
if (!($Session)) {
$Session = Get-GFTPassboltConnection
}
$params = @{}
if ($Session) {
$params['Session'] = $Session
}
$SecretPath = $Session.Headers.SPath
if (!($SecretPath)) {
Return "No secret found !"
}
$Server = $Session.Headers.Server
$ProgressPreference = 'SilentlyContinue'
}
Process {
$Json = @{}
$Json['folder_parent_id'] = $FolderID
$Json = $Json | ConvertTo-Json
$Content = Invoke-RestMethod -Uri ($Server+"/move/resource/$PasswordID.json") -Method Post -WebSession $Session -Body $Json -ContentType 'application/json'
$Content
}
}
function Get-GFTPassboltPasswordPermissions {
param (
[Microsoft.PowerShell.Commands.WebRequestSession]$Session,
[String]$PasswordID
)
Begin {
$ProgressPreference = 'SilentlyContinue'
if (!($Session)) {
$Session = Get-GFTPassboltConnection
}
$Server = $Session.Headers.Server
$ProgressPreference = 'SilentlyContinue'
}
Process {
$Content = Invoke-RestMethod -Uri ($Server+"/permissions/resource/$PasswordID.json") -Method Get -WebSession $Session
$Content.Body
}
}
function Set-GFTPassboltShare {
param (
[Microsoft.PowerShell.Commands.WebRequestSession]$Session,
[String]$PasswordID,
[String]$GroupID,
[String]$PublicKeyContent = (Get-GFTPassboltPGPPubKey | ? { $_.uid -match "APIPass" }).armored_key
)
Begin {
$ProgressPreference = 'SilentlyContinue'
if (!($Session)) {
$Session = Get-GFTPassboltConnection
}
$Files = $Session.Headers.SPath
$Server = $Session.Headers.Server
$ProgressPreference = 'SilentlyContinue'
}
Process {
$NewPass = (Get-GFTPassword -Direct -ID $PasswordID).Secret
$Json = @{}
$Permissions = @{}
$Permissions['is_new'] = "true"
$Permissions['aro'] = "Group"
$Permissions['aro_foreign_key'] = "$GroupID"
$Permissions['aco'] = "Resource"
$Permissions['aco_foreign_key'] = "$PasswordID"
$Permissions['type'] = "15"
$Temp = (Get-GFTShareInformations | ? {$_."groups_users".'group_id' -match $GroupID }) | % {
$Files = New-Item -Path $SecretPath -Name "$([System.IO.Path]::GetRandomFileName())$(Get-Random -Minimum 0 -Maximum 99999)" -ItemType File
Set-Content -Path $Files.FullName -Value $_.gpgkey.armored_key
@{
'user_id' = "$($_.id)"
'data' = "$(Protect-PGP -FilePathPublic $files.FullName -String $NewPass)"
}
}
$Json.Add("secrets",@($Temp))
$Json.Add("permissions",@($Permissions))
$Json = $Json | ConvertTo-Json -Depth 4
$Content = Invoke-RestMethod -Uri ($Server+"/share/resource/$PasswordID.json") -Method Put -WebSession $Session -Body $Json -ContentType 'application/json'
$Content.Body
}
}
function Get-GFTPassboltGroup {
param (
[Microsoft.PowerShell.Commands.WebRequestSession]$Session,
[String]$GroupName
)
Begin {
$ProgressPreference = 'SilentlyContinue'
if (!($Session)) {
$Session = Get-GFTPassboltConnection
}
$Server = $Session.Headers.Server
$ProgressPreference = 'SilentlyContinue'
}
Process {
$Content = Invoke-RestMethod -Uri ($Server+"/groups.json") -Method Get -WebSession $Session
$Content.Body
}
}
Have a good day
Odric