PowerShell - Share Dev in progress

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

2 Likes