195 lines
8.5 KiB
PowerShell
195 lines
8.5 KiB
PowerShell
|
# Ignore Measure-HelpSynopsis warnings in the PSScript Analyzer
|
||
|
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('Alkami.PowerShell.PSScriptAnalyzerRules\Measure-HelpSynopsis', '', Scope = 'Class')]
|
||
|
# Ignore Measure-HelpSynopsis warnings in the PSScript Analyzer - PS Classes can't do CmdletBinding, afaict
|
||
|
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('Alkami.PowerShell.PSScriptAnalyzerRules\Measure-CmdletBinding', '', Scope = 'Class')]
|
||
|
|
||
|
Class SecretServerConnection {
|
||
|
[string]$api
|
||
|
[string]$site
|
||
|
[string]$userName
|
||
|
[string]$domain
|
||
|
[string]$password
|
||
|
[string]$tokenRoute
|
||
|
[ScriptBlock]$commonFilters = { "?filter.includeRestricted=true&filter.searchtext=$searchString&filter.folderId=$folderId&filter.includeSubFolders=true" }
|
||
|
[ScriptBlock]$updateEndpoint
|
||
|
[System.Collections.Generic.Dictionary[[String], [String]]]$commonHeader
|
||
|
$token
|
||
|
|
||
|
SecretServerConnection() { }
|
||
|
|
||
|
SecretServerConnection([string]$site, [string]$userName, [string]$password) {
|
||
|
$this.site = $site
|
||
|
$this.tokenRoute = "$site/oauth2/token"
|
||
|
$this.api = $site, "api/v1" -join "/"
|
||
|
$this.updateEndpoint = { "/secrets/$secretId/fields/$fieldToUpdate" }
|
||
|
$this.userName = $userName
|
||
|
$this.password = $password
|
||
|
$this.commonHeader = [System.Collections.Generic.Dictionary[[String], [String]]]::new()
|
||
|
}
|
||
|
|
||
|
[void]Authenticate() {
|
||
|
$this.Authenticate($False)
|
||
|
}
|
||
|
[void]Authenticate([bool]$UseTwoFactor) {
|
||
|
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||
|
$creds = @{
|
||
|
username = $this.username
|
||
|
password = $this.password
|
||
|
grant_type = "password"
|
||
|
}
|
||
|
|
||
|
$headers = $null
|
||
|
If ($UseTwoFactor) {
|
||
|
$headers = @{
|
||
|
"OTP" = (Read-Host -Prompt "Enter your OTP for 2FA: ")
|
||
|
}
|
||
|
}
|
||
|
try {
|
||
|
$response = Invoke-RestMethod $this.tokenRoute -Method Post -Body $creds -Headers $headers
|
||
|
$this.token = $response.access_token;
|
||
|
if ($this.commonHeader.Count -gt 0) { $this.commonHeader.Clear() }
|
||
|
$this.commonHeader.Add("Authorization", "Bearer $($this.token)")
|
||
|
} catch {
|
||
|
throw $_
|
||
|
}
|
||
|
}
|
||
|
[object]GetSecretByName([string]$secretName, [string]$folderId) {
|
||
|
# $searchString is used in $commonFilters above. This "not used" warning is a lie.
|
||
|
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'False Positive')]
|
||
|
$searchString = $secretName
|
||
|
$filters = $this.commonFilters.Invoke()
|
||
|
Write-Debug "$($this.api)/secrets/lookup$filters"
|
||
|
$result = Invoke-RestMethod "$($this.api)/secrets$filters" -Headers $this.commonHeader
|
||
|
|
||
|
return $result
|
||
|
}
|
||
|
|
||
|
[object]GetSecretById([string]$secretId) {
|
||
|
|
||
|
Write-Debug "$($this.api)/secrets/$secretId"
|
||
|
$response = Invoke-RestMethod "$($this.api)/secrets/$secretId" -Headers $this.commonHeader
|
||
|
|
||
|
return $response
|
||
|
}
|
||
|
[object]GetSecretByFolderId([string]$folderId) {
|
||
|
$parameters = "?filter.folderId=$folderId"
|
||
|
|
||
|
$response = Invoke-RestMethod "$($this.api)/secrets/$parameters" -Headers $this.commonHeader
|
||
|
|
||
|
return $response.records
|
||
|
}
|
||
|
|
||
|
[object]GetSecretTemplateById([int]$templateId, [int]$folderId) {
|
||
|
$secret = Invoke-RestMethod "$($this.api)/secrets/stub?filter.secrettemplateid=$templateId&filter.folderId=$folderId" -Headers $this.commonHeader
|
||
|
|
||
|
return $secret
|
||
|
}
|
||
|
|
||
|
[int]GetSecretTemplateIdByName([string]$templateName) {
|
||
|
$searchString = "?filter.searchText=$templateName"
|
||
|
|
||
|
$secret = Invoke-RestMethod -Method Get "$($this.api)/secret-templates$searchString" -Headers $this.commonHeader
|
||
|
|
||
|
if ($secret.records) {
|
||
|
$record = $secret.records | Where-Object { $_.name -eq $templateName }
|
||
|
return $record.id;
|
||
|
}
|
||
|
|
||
|
return -1
|
||
|
}
|
||
|
|
||
|
[int]CreateSecret([object]$secret, [int]$folderId, [string]$secretName) {
|
||
|
|
||
|
$secret.name = $secretName
|
||
|
$secret.siteId = 1
|
||
|
$secret.folderId = $folderId
|
||
|
|
||
|
# Get Secret Template first, set up the template with various items and their values and then pass it to create secret
|
||
|
$requestCreateSecretParams = $secret | ConvertTo-Json
|
||
|
$secret = Invoke-RestMethod "$($this.api)/secrets/" -Method Post -Body $requestCreateSecretParams -Headers $this.commonHeader -ContentType "application/json"
|
||
|
|
||
|
return $secret.id
|
||
|
}
|
||
|
[object]UpdateField([string]$secretId, [string]$fieldToUpdate, [string]$newValue) {
|
||
|
$body = @{ value = $newValue } | ConvertTo-Json
|
||
|
$response = Invoke-RestMethod -Method Put -Uri "$($this.api)$($this.updateEndpoint.Invoke())" -Headers $this.commonHeader -ContentType "application/json" -Body $body
|
||
|
return $response
|
||
|
}
|
||
|
|
||
|
[object]GetField([string]$secretId, [string]$field) {
|
||
|
$response = Invoke-RestMethod -Method Get -Uri "$($this.api)$($this.updateEndpoint.Invoke())" -Headers $this.commonHeader
|
||
|
return $response.Records
|
||
|
}
|
||
|
|
||
|
[void]UploadFile([int]$secretId, [string]$fieldToUpdate, [string]$filePath) {
|
||
|
|
||
|
$fileName = Get-ChildItem $filePath | Select-Object -ExpandProperty Name
|
||
|
|
||
|
$requestUploadFileParams = @{
|
||
|
fileName = $fileName;
|
||
|
fileAttachment = [IO.File]::ReadAllBytes($filePath)
|
||
|
} | ConvertTo-Json
|
||
|
|
||
|
Invoke-RestMethod -Method Put -Uri "$($this.api)$($this.updateEndpoint.Invoke())" -Headers $this.commonHeader -Body $requestUploadFileParams -ContentType "application/json"
|
||
|
|
||
|
}
|
||
|
|
||
|
[bool]DownloadFile([int]$secretId, [string]$fieldToupdate, [string]$filePath) {
|
||
|
# invokeing $this.updateEndpoint.Invoke() sets variables hidden above in SecretServerConnection
|
||
|
Write-Debug "$($this.api)$($this.updateEndpoint.Invoke())"
|
||
|
try {
|
||
|
Invoke-RestMethod -Method Get -Uri "$($this.api)$($this.updateEndpoint.Invoke())" -Headers $this.commonHeader -OutFile $filePath | Out-Null
|
||
|
return $true
|
||
|
} catch {
|
||
|
Write-Warning "An error occurred while downloading a file."
|
||
|
Write-Warning -Message "StatusCode: $($_.Exception.Response.StatusCode.value__)"
|
||
|
Write-Warning -Message "StatusDescription: $($_.Exception.Response.StatusDescription)"
|
||
|
return $false
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[int]AddFolder([int]$parentFolderId, [string]$folderName, [bool]$inheritPermissions, [bool]$inheritSecretPolicy) {
|
||
|
|
||
|
$folderStub = Invoke-RestMethod "$($this.api)/folders/stub" -Method GET -Headers $this.commonHeader -ContentType "application/json"
|
||
|
|
||
|
$folderStub.folderName = $folderName
|
||
|
$folderStub.folderTypeId = 1
|
||
|
$folderStub.inheritPermissions = $inheritPermissions
|
||
|
$folderStub.inheritSecretPolicy = $inheritSecretPolicy
|
||
|
$folderStub.parentFolderId = $parentFolderId
|
||
|
|
||
|
$folderArgs = $folderStub | ConvertTo-Json
|
||
|
|
||
|
$folderAddResult = Invoke-RestMethod "$($this.api)/folders" -Method POST -Body $folderArgs -Headers $this.commonHeader -ContentType "application/json"
|
||
|
|
||
|
return $folderAddResult.id
|
||
|
}
|
||
|
[int]AddFolder([int]$parentFolderId, [string]$folderName) {
|
||
|
return $this.AddFolder($parentFolderId, $folderName, $true, $true)
|
||
|
}
|
||
|
[object]GetFolderById([int]$folderId) {
|
||
|
$folderGetResult = Invoke-RestMethod "$($this.api)/folders/$folderId" -Method GET -Headers $this.commonHeader -ContentType "application/json"
|
||
|
return $folderGetResult.records
|
||
|
}
|
||
|
[object]GetChildFolders([int]$parentId) {
|
||
|
$parameters = "?filter.parentFolderId=$parentId"
|
||
|
$folderGetResult = Invoke-RestMethod "$($this.api)/folders/$parameters" -Method GET -Headers $this.commonHeader -ContentType "application/json"
|
||
|
return $folderGetResult.records
|
||
|
}
|
||
|
[object]GetFolderIdByName([string]$folderName) {
|
||
|
$searchFilter = "?filter.searchText=$folderName"
|
||
|
|
||
|
$searchResults = Invoke-RestMethod "$($this.api)/folders$searchFilter" -Method GET -Headers $this.commonHeader -ContentType "application/json"
|
||
|
|
||
|
return $searchResults.Records.Id
|
||
|
}
|
||
|
[object]GetFolderIdByName([string]$folderName, [int]$parentFolderId) {
|
||
|
$searchString = $folderName
|
||
|
$folderId = $parentFolderId
|
||
|
$filters = "?filter.includeRestricted=true&filter.parentFolderId=$folderId&filter.searchtext=%$searchString"
|
||
|
Write-Debug $filters
|
||
|
$searchResults = Invoke-RestMethod "$($this.api)/folders$filters" -Method GET -Headers $this.commonHeader -ContentType "application/json"
|
||
|
|
||
|
return $searchResults.Records.Id
|
||
|
}
|
||
|
}
|