ps/Modules/Alkami.DevOps.Certificates/Private/SecretServerConnection.ps1

195 lines
8.5 KiB
PowerShell
Raw Normal View History

2023-05-30 22:51:22 -07:00
# 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
}
}