SecretsManager.ps1

#requires -Version 5.1

$Keeper_KSMAppCompleter = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)

    $result = @()
    [KeeperSecurity.Vault.VaultOnline]$private:vault = getVault
    if (-not $vault) {
        return $null
    }

    $toComplete = $wordToComplete
    if ($toComplete.Length -ge 1) {
        if ($toComplete[0] -eq '''') {
            $toComplete = $toComplete.Substring(1, $toComplete.Length - 1)
            $toComplete = $toComplete -replace '''''', ''''
        }
        if ($toComplete[0] -eq '"') {
            $toComplete = $toComplete.Substring(1, $toComplete.Length - 1)
            $toComplete = $toComplete -replace '""', '"'
            $toComplete = $toComplete -replace '`"', '"'
        }
    }

    $toComplete += '*'
    foreach ($app in $vault.KeeperApplications) {
        if ($app.Title -like $toComplete) {
            $name = $app.Title
            if ($name -match ' ') {
                $name = $name -replace '''', ''''''
                $name = '''' + $name + ''''
            }
            $result += $name
        }
    }

    if ($result.Count -gt 0) {
        return $result
    }
    else {
        return $null
    }
}

function Get-KeeperSecretManagerApp {
    <#
        .Synopsis
        Get Keeper Secret Manager Applications
 
        .Parameter Uid
        Record UID
 
        .Parameter Filter
        Return matching applications only
 
        .Parameter Detail
        Application details
    #>

    [CmdletBinding()]
    Param (
        [string] $Uid,
        [string] $Filter,
        [Switch] $Detail
    )

    [KeeperSecurity.Vault.VaultOnline]$vault = getVault
    if ($Uid) {
        [KeeperSecurity.Vault.ApplicationRecord] $application = $null
        if ($vault.TryGetKeeperApplication($uid, [ref]$application)) {
            if ($Detail.IsPresent) {
                $vault.GetSecretManagerApplication($application.Uid, $false).GetAwaiter().GetResult()
            }
            else {
                $application
            }
        }
    }
    else {
        foreach ($application in $vault.KeeperApplications) {
            if ($Filter) {
                $match = $($application.Uid, $application.Title) | Select-String $Filter | Select-Object -First 1
                if (-not $match) {
                    continue
                }
            }
            if ($Detail.IsPresent) {
                $vault.GetSecretManagerApplication($application.Uid, $false).GetAwaiter().GetResult()
            }
            else {
                $application
            }
        }
    }
}
New-Alias -Name ksm -Value Get-KeeperSecretManagerApp

function Add-KeeperSecretManagerApp {
    <#
        .Synopsis
        Creates Keeper Secret Manager Application
 
        .Parameter Name
        Secret Manager Application
    #>

    [CmdletBinding()]
    Param (
        [Parameter(Position = 0, Mandatory = $true)][string]$AppName
    )

    [KeeperSecurity.Vault.VaultOnline]$vault = getVault
    $vault.CreateSecretManagerApplication($AppName).GetAwaiter().GetResult()
}
New-Alias -Name ksm-create -Value Add-KeeperSecretManagerApp

function Grant-KeeperSecretManagerFolderAccess {
    <#
        .Synopsis
        Adds shared folder to KSM Application
 
        .Parameter App
       KSM Application UID or Title
 
        .Parameter Secret
       Shared Folder UID or Name
 
        .Parameter CanEdit
        Enable write access to shared secrets
 
    #>

    [CmdletBinding()]
    Param (
        [Parameter(Mandatory = $true)][string]$App,
        [Parameter(Mandatory = $true)][string]$Secret,
        [Parameter()][switch]$CanEdit
    )

    [KeeperSecurity.Vault.VaultOnline]$vault = getVault
    $apps = Get-KeeperSecretManagerApp -Filter $App
    if (-not $apps) {
        Write-Error -Message "Cannot find Secret Manager Application: $App" -ErrorAction Stop
    }
    [KeeperSecurity.Vault.ApplicationRecord]$application = $apps[0]

    [string]$uid = $null
    $sfs = Get-KeeperSharedFolder -Filter $Secret
    if ($sfs) {
        $uid = $sfs[0].Uid
    }
    else {
        $recs = Get-KeeperRecord -Filter $Secret
        if ($recs) {
            $uid = $recs[0].Uid
        }
    }
    if (-not $uid) {
        Write-Error -Message "Cannot find Shared Folder: $Secret" -ErrorAction Stop
    }
    $vault.ShareToSecretManagerApplication($application.Uid, $uid, $CanEdit.IsPresent).GetAwaiter().GetResult()
}
Register-ArgumentCompleter -CommandName Grant-KeeperSecretManagerFolderAccess -ParameterName Secret -ScriptBlock $Keeper_SharedFolderCompleter
Register-ArgumentCompleter -CommandName Grant-KeeperSecretManagerFolderAccess -ParameterName App -ScriptBlock $Keeper_KSMAppCompleter
New-Alias -Name ksm-share -Value Grant-KeeperSecretManagerFolderAccess

function Revoke-KeeperSecretManagerFolderAccess {
    <#
        .Synopsis
        Removes Shared Folder from KSM Application
 
        .Parameter App
        Secret Manager Application
 
        .Parameter Secret
       Shared Folder UID or Name
    #>

    [CmdletBinding()]
    Param (
        [Parameter(Mandatory = $true)][string]$App,
        [Parameter(Mandatory = $true)][string]$Secret
    )

    [KeeperSecurity.Vault.VaultOnline]$vault = getVault
    $apps = Get-KeeperSecretManagerApp -Filter $App
    if (-not $apps) {
        Write-Error -Message "Cannot find Secret Manager Application: $App" -ErrorAction Stop
    }
    [KeeperSecurity.Vault.ApplicationRecord]$application = $apps[0]

    [string]$uid = $null
    $sfs = Get-KeeperSharedFolder -Filter $Secret
    if ($sfs) {
        $uid = $sfs[0].Uid
    }
    else {
        $recs = Get-KeeperRecord -Filter $Secret
        if ($recs) {
            $uid = $recs[0].Uid
        }
    }
    if (-not $uid) {
        Write-Error -Message "Cannot find Shared Folder: $Secret" -ErrorAction Stop
    }
    $vault.UnshareFromSecretManagerApplication($application.Uid, $uid).GetAwaiter().GetResult()
}
Register-ArgumentCompleter -CommandName Revoke-KeeperSecretManagerFolderAccess -ParameterName Secret -ScriptBlock $Keeper_SharedFolderCompleter
Register-ArgumentCompleter -CommandName Revoke-KeeperSecretManagerFolderAccess -ParameterName App -ScriptBlock $Keeper_KSMAppCompleter
New-Alias -Name ksm-unshare -Value Revoke-KeeperSecretManagerFolderAccess

function Add-KeeperSecretManagerClient {
    <#
        .Synopsis
        Adds client/device to KSM Application
 
        .Parameter App
        KSM Application UID or Title
 
        .Parameter Name
        Client or Device Name
 
        .Parameter UnlockIP
        Enable write access to shared secrets
    #>

    [CmdletBinding()]
    Param (
        [Parameter(Mandatory = $true)][string]$App,
        [Parameter()][string]$Name,
        [Parameter()][switch]$UnlockIP
    )

    [KeeperSecurity.Vault.VaultOnline]$vault = getVault
    $apps = Get-KeeperSecretManagerApp -Filter $App
    if (-not $apps) {
        Write-Error -Message "Cannot find Secret Manager Application: $App" -ErrorAction Stop
    }
    [KeeperSecurity.Vault.ApplicationRecord]$application = $apps[0]

    $rs = $vault.AddSecretManagerClient($application.Uid, $UnlockIP.IsPresent, $null, $null, $name).GetAwaiter().GetResult()
    $rs.Item2
}
Register-ArgumentCompleter -CommandName Add-KeeperSecretManagerClient -ParameterName App -ScriptBlock $Keeper_KSMAppCompleter
New-Alias -Name ksm-addclient -Value Add-KeeperSecretManagerClient

function Remove-KeeperSecretManagerClient {
    <#
        .Synopsis
        Removes client/device from KSM Application
 
        .Parameter App
        KSM Application UID or Title
 
        .Parameter Name
        Client Id or Device Name
 
    #>

    [CmdletBinding(SupportsShouldProcess=$true)]
    Param (
        [Parameter(Mandatory = $true)][string]$App,
        [Parameter(Mandatory = $true)][string]$Name
    )

    [KeeperSecurity.Vault.VaultOnline]$vault = getVault
    $apps = Get-KeeperSecretManagerApp -Filter $App -Detail
    if (-not $apps) {
        Write-Error -Message "Cannot find Secret Manager Application: $App" -ErrorAction Stop
    }
    [KeeperSecurity.Vault.ApplicationRecord]$application = $apps[0]

    $device = $application.Devices | Where-Object { $_.Name -ceq $Name -or $_.ShortDeviceId -ceq $Name }
    if (-not $device) {
        Write-Error -Message "Cannot find Device: $Name" -ErrorAction Stop
    }

    if ($PSCmdlet.ShouldProcess($application.Title, "Removing KSM Device '$($device.Name)'")) {
        $vault.DeleteSecretManagerClient($application.Uid, $device.DeviceId).GetAwaiter().GetResult() | Out-Null
        Write-Information -MessageData "Device $($device.Name) has been deleted from KSM application `"$($application.Title)`"."
    }
}

Register-ArgumentCompleter -CommandName Remove-KeeperSecretManagerClient -ParameterName App -ScriptBlock $Keeper_KSMAppCompleter
New-Alias -Name ksm-rmclient -Value Remove-KeeperSecretManagerClient

# SIG # Begin signature block
# MIIR1wYJKoZIhvcNAQcCoIIRyDCCEcQCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUakTb/dayVmGMbUA/GGjRGcjn
# ICaggg4jMIIGsDCCBJigAwIBAgIQCK1AsmDSnEyfXs2pvZOu2TANBgkqhkiG9w0B
# AQwFADBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD
# VQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVk
# IFJvb3QgRzQwHhcNMjEwNDI5MDAwMDAwWhcNMzYwNDI4MjM1OTU5WjBpMQswCQYD
# VQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lD
# ZXJ0IFRydXN0ZWQgRzQgQ29kZSBTaWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEg
# Q0ExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1bQvQtAorXi3XdU5
# WRuxiEL1M4zrPYGXcMW7xIUmMJ+kjmjYXPXrNCQH4UtP03hD9BfXHtr50tVnGlJP
# DqFX/IiZwZHMgQM+TXAkZLON4gh9NH1MgFcSa0OamfLFOx/y78tHWhOmTLMBICXz
# ENOLsvsI8IrgnQnAZaf6mIBJNYc9URnokCF4RS6hnyzhGMIazMXuk0lwQjKP+8bq
# HPNlaJGiTUyCEUhSaN4QvRRXXegYE2XFf7JPhSxIpFaENdb5LpyqABXRN/4aBpTC
# fMjqGzLmysL0p6MDDnSlrzm2q2AS4+jWufcx4dyt5Big2MEjR0ezoQ9uo6ttmAaD
# G7dqZy3SvUQakhCBj7A7CdfHmzJawv9qYFSLScGT7eG0XOBv6yb5jNWy+TgQ5urO
# kfW+0/tvk2E0XLyTRSiDNipmKF+wc86LJiUGsoPUXPYVGUztYuBeM/Lo6OwKp7AD
# K5GyNnm+960IHnWmZcy740hQ83eRGv7bUKJGyGFYmPV8AhY8gyitOYbs1LcNU9D4
# R+Z1MI3sMJN2FKZbS110YU0/EpF23r9Yy3IQKUHw1cVtJnZoEUETWJrcJisB9IlN
# Wdt4z4FKPkBHX8mBUHOFECMhWWCKZFTBzCEa6DgZfGYczXg4RTCZT/9jT0y7qg0I
# U0F8WD1Hs/q27IwyCQLMbDwMVhECAwEAAaOCAVkwggFVMBIGA1UdEwEB/wQIMAYB
# Af8CAQAwHQYDVR0OBBYEFGg34Ou2O/hfEYb7/mF7CIhl9E5CMB8GA1UdIwQYMBaA
# FOzX44LScV1kTN8uZz/nupiuHA9PMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAK
# BggrBgEFBQcDAzB3BggrBgEFBQcBAQRrMGkwJAYIKwYBBQUHMAGGGGh0dHA6Ly9v
# Y3NwLmRpZ2ljZXJ0LmNvbTBBBggrBgEFBQcwAoY1aHR0cDovL2NhY2VydHMuZGln
# aWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcnQwQwYDVR0fBDwwOjA4
# oDagNIYyaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJv
# b3RHNC5jcmwwHAYDVR0gBBUwEzAHBgVngQwBAzAIBgZngQwBBAEwDQYJKoZIhvcN
# AQEMBQADggIBADojRD2NCHbuj7w6mdNW4AIapfhINPMstuZ0ZveUcrEAyq9sMCcT
# Ep6QRJ9L/Z6jfCbVN7w6XUhtldU/SfQnuxaBRVD9nL22heB2fjdxyyL3WqqQz/WT
# auPrINHVUHmImoqKwba9oUgYftzYgBoRGRjNYZmBVvbJ43bnxOQbX0P4PpT/djk9
# ntSZz0rdKOtfJqGVWEjVGv7XJz/9kNF2ht0csGBc8w2o7uCJob054ThO2m67Np37
# 5SFTWsPK6Wrxoj7bQ7gzyE84FJKZ9d3OVG3ZXQIUH0AzfAPilbLCIXVzUstG2MQ0
# HKKlS43Nb3Y3LIU/Gs4m6Ri+kAewQ3+ViCCCcPDMyu/9KTVcH4k4Vfc3iosJocsL
# 6TEa/y4ZXDlx4b6cpwoG1iZnt5LmTl/eeqxJzy6kdJKt2zyknIYf48FWGysj/4+1
# 6oh7cGvmoLr9Oj9FpsToFpFSi0HASIRLlk2rREDjjfAVKM7t8RhWByovEMQMCGQ8
# M4+uKIw8y4+ICw2/O/TOHnuO77Xry7fwdxPm5yg/rBKupS8ibEH5glwVZsxsDsrF
# hsP2JjMMB0ug0wcCampAMEhLNKhRILutG4UI4lkNbcoFUCvqShyepf2gpx8GdOfy
# 1lKQ/a+FSCH5Vzu0nAPthkX0tGFuv2jiJmCG6sivqf6UHedjGzqGVnhOMIIHazCC
# BVOgAwIBAgIQAnNTGQOIer82vZ1cJyDJDjANBgkqhkiG9w0BAQsFADBpMQswCQYD
# VQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lD
# ZXJ0IFRydXN0ZWQgRzQgQ29kZSBTaWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEg
# Q0ExMB4XDTIyMDIwMjAwMDAwMFoXDTI1MDIwMTIzNTk1OVowcDELMAkGA1UEBhMC
# VVMxETAPBgNVBAgTCElsbGlub2lzMRAwDgYDVQQHEwdDaGljYWdvMR0wGwYDVQQK
# ExRLZWVwZXIgU2VjdXJpdHkgSW5jLjEdMBsGA1UEAxMUS2VlcGVyIFNlY3VyaXR5
# IEluYy4wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNgTqmksdjUyKF
# 5zWkDyghf0PLWJWdzG0TX2j8B4J55xwt+B17zd4Xc3n0dvmSVAyPQANeN+mP1chf
# 4LTRn9h4jWb8Jsfn+JzyRhj/gYINYvBnpRpqoM0z7QC9Ebwj5T61Cogm9EKGcrG+
# Ujh+Z7pTqfSUrHD8NMXhDL/UpVn+w0Pb4qg7o7AH2o94n7u/qTlMGZCs+VCAvhNr
# wPABxvFY07YGb9t5/IZlPE8vG3p1vw2SbgREgFWSEQFj6X2CIhSrbiFCW/766/Mq
# EX6qm+RyF71fD4d3yShg39guaE9o+TBl1MqVCje4bK/wGoNxCho0I6Z1fBBKloyp
# vlx3gPpU7tJJ+KpuIiel9R9dGQuscqKzehPtbRc9Abr9ThN/HrLg1sFFVMdn2oMR
# 63QCUdz+B1NuS7Ap8Ti7XvAPJHzEuQDcdMcRbkIfllJVqrb9UXEFwOPzvRU2KrcQ
# 42Jlnn4T+WenPx5Nr3o/o08WLhLTicEK1OacEowyRLBmih4Gxpdk3fUAVCEkdvmq
# TSydQpl1Bk8V88dxCkB1wMZyFYLNcddBL4kUbwjso/z6f2TtfAVYs/iIRWqs7Xqt
# 4F2BBqobOGMymwg6VgVjjzDIgJCZSbjpq2IoVTci5vli6vxgSoZ01fccSaKa4Izm
# B7DbobIkIjLgPqpnCkqlHuJj5hQ9twIDAQABo4ICBjCCAgIwHwYDVR0jBBgwFoAU
# aDfg67Y7+F8Rhvv+YXsIiGX0TkIwHQYDVR0OBBYEFCZd3/KEdT2t5WTIFb3TUaM4
# sTikMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzCBtQYDVR0f
# BIGtMIGqMFOgUaBPhk1odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRU
# cnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIxQ0ExLmNybDBToFGg
# T4ZNaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29k
# ZVNpZ25pbmdSU0E0MDk2U0hBMzg0MjAyMUNBMS5jcmwwPgYDVR0gBDcwNTAzBgZn
# gQwBBAEwKTAnBggrBgEFBQcCARYbaHR0cDovL3d3dy5kaWdpY2VydC5jb20vQ1BT
# MIGUBggrBgEFBQcBAQSBhzCBhDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGln
# aWNlcnQuY29tMFwGCCsGAQUFBzAChlBodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5j
# b20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIx
# Q0ExLmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4ICAQAGyDM3Cbxq
# Auhr8O2xwOoCSVKmFkXqicwlrugwLW44Y4WX+imvTrGfjj2S99k/4D5H8DgtW/u8
# tOxcCoehTOCIEwP5TLrieHppsqAR4jaJRcdAHOWiJ1bmwQBv/cBU9vaelL0oXxxf
# TwD9oDaQNuyq6p+nIJMqbKv33b8AWGe3zq4JwblaFjRDL5lUDNhPx3g/pm7JhnbX
# 7QTKydAJvpbuP5cqUH1GEeVMjc5vEELtGNy/fy7Ekm4dndX4IZcFXW5L0Lx8cReB
# hIZwA+pzdzTWQYvfxgRMb/j2uY+Tkb6Wz2x9BBS1UXiP2qrs3rhQv8DZRkUSqnko
# YD4uJP8gk8BXcIXIThgEF2YCq2hBiwna5Ijbwkmjn1lWwGv15SznTOTnrVApJqB1
# tB2s2ovUNV4CyKDPVr+9/CS6IQJfEZeHYcYLsIga2q5NZCrqZAasBfCwALVkALos
# DIWhs33vYLfETMSuk5Hd5JC+hLjVM3ZJwslvnc/wec2r0GNAiZ3a1aweC7NYuzRz
# 29Mi/eR/4ylmCltyZqYJ1JcC/g6eY2Q0xkdWc8P0yHfQ/3fe7+AKXXKNjfv858GW
# lg1Ck2lvwPdLqJWqj1FwJPiGRCB+WulPe0csTyWnf+ed45TXx69tZ6BZr0Xr2jXu
# ybBdJtg0NN0a62xxWrmX42CgsrzHzRm7OzGCAx4wggMaAgEBMH0waTELMAkGA1UE
# BhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMUEwPwYDVQQDEzhEaWdpQ2Vy
# dCBUcnVzdGVkIEc0IENvZGUgU2lnbmluZyBSU0E0MDk2IFNIQTM4NCAyMDIxIENB
# MQIQAnNTGQOIer82vZ1cJyDJDjAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEK
# MAigAoAAoQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3
# AgELMQ4wDAYKKwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQU4P4O65PI6xxIe/5X
# 3d+Q4SZJWkMwDQYJKoZIhvcNAQEBBQAEggIAe6mk55ttOzgt1b//lsflMxSfVKhx
# UoHXWG4tCWvJ17ma0y+wF2DtqasjCzLSzPjaLZW/fk9zxT9bld/9/I/GaU4if0wl
# t/ZPvT8xe5M9Uvj7n2obPTVIMaqplGfzEWt4Slk7WC27KztDCNdis6TyQaxsQT16
# a2vYLTA+Q3BNyqoY2A4l+Ij6ACNFijqKSFymIUb1JmfWxPQOlq3hhAh6QPV70dcJ
# zGfv6RtBNn29CKoahUWSHP7s5oF+c8zkryAf2dbL6ggwgdwwGu+lIUQZgDEkffBn
# 7CeIdsHDySueH916JUPITHZLs+5D5KqCRx8eJYeIJHem1GsbZ36rzz58uyAdRWH+
# T/fMgUUxJGQDvvS3VoGMCr5U4A5jJm0Ocp9pjR6EI7CWvkBSHAmaQQiQqwhoztEv
# uMSqd2uLBKCwMuuPHDVtAf1M0Q3Ko9/wlDYW53pr4CQYitq5uepde4YfT6qQmI/I
# QZlP94cfxsgYFcoSmjLNduQhyAlFHO2hrf9ucrzsupWS9dvLFa6zH0K6wy2wUsek
# vgexqzIVDDH6L/x4GP9iYPPK5td6T7fFji+tr7BtGre+ZqinowzljgmbaniV8O9d
# sJxiatKZoqK4Jt+/EkAIro1RO1/U4ASzXCmpu5lElQuE5aurEDlb10cnXqma/bpS
# i40PGCgMddzjI5w=
# SIG # End signature block