Octopus.Script exported 2021-10-19 by harrisonmeister belongs to ‘CyberArk’ category.
This step retrieves one or more secrets from CyberArk Conjur and creates sensitive output variables for each value retrieved. These values can be used in other steps in your deployment or runbook process.
This step differs from the CyberArk Conjur - Retrieve a Secret step template as it offers the ability to retrieve multiple secrets (with optional version) and performs a batched call where possible - see below for further details.
Retrieval Behavior:
- If any of the Conjur Variables have a version specified to retrieve, then the step template will retrieve all of the secrets individually using the Conjur REST API - Secret Retrieve endpoint.
- If none of the Conjur Variables have a version specified (i.e. retrieve the latest version) then the step template will retrieve the secrets using the Conjur REST API - Batch Retrieval endpoint.
Hint: If performance is important to you, don’t include specific versions of Conjur Variables. It’s faster to fetch secrets in a batch than to fetch them one at a time.
Required:
- PowerShell 5.1 or higher.
- A set of credentials with permissions to retrieve secrets from CyberArk Conjur.
- Access to the Conjur instance from the Worker or target where this step executes.
Notes:
- Tested on Conjur v1.13.2 / API v5.2.0.
- Tested on Octopus 2021.2.
- Tested on both Windows Server 2019 and Ubuntu 20.04.
Parameters
When steps based on the template are included in a project’s deployment process, the parameters below can be set.
Conjur URL
CyberArk.Conjur.RetrieveSecrets.Url =
The URL of the Conjur instance you are connecting to.
Conjur Account
CyberArk.Conjur.RetrieveSecrets.Account =
The Conjur account. This is the Conjur appliance identifier provided during Conjur configuration.
Conjur Login
CyberArk.Conjur.RetrieveSecrets.Login =
The username (from the point of view of the authenticator) of the user or machine (host) requesting authentication. For a host, the id assigned when the host was created should be used, prepended with the literal host/
.
Conjur Api Key
CyberArk.Conjur.RetrieveSecrets.ApiKey =
The API Key corresponding to the user/host provided.
Conjur Secret Variable IDs
CyberArk.Conjur.RetrieveSecrets.SecretVariables =
Specify the names of the secrets to be returned from Conjur, in the format:
VariableID Version | OutputVariableName
where:
VariableID
is the Variable ID of the Conjur secret.Version
is the version of the secret to retrieve. If this value isn’t specified, the latest version will be retrieved.OutputVariableName
is the optional Octopus output variable name to store the secret’s value in. If this value isn’t specified, an output name will be generated dynamically.
Note: Multiple Variable IDs can be retrieved by entering each one on a new line.
Print output variable names
CyberArk.Conjur.RetrieveSecrets.PrintVariableNames = False
Write out the Octopus output variable names to the task log. Default: False
.
Script body
Steps based on this template will execute the following PowerShell script.
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$ErrorActionPreference = 'Stop'
# Variables
$ConjurUrl = $OctopusParameters["CyberArk.Conjur.RetrieveSecrets.Url"]
$ConjurAccount = $OctopusParameters["CyberArk.Conjur.RetrieveSecrets.Account"]
$ConjurLogin = $OctopusParameters["CyberArk.Conjur.RetrieveSecrets.Login"]
$ConjurApiKey = $OctopusParameters["CyberArk.Conjur.RetrieveSecrets.ApiKey"]
$ConjurSecretVariables = $OctopusParameters["CyberArk.Conjur.RetrieveSecrets.SecretVariables"]
$PrintVariableNames = $OctopusParameters["CyberArk.Conjur.RetrieveSecrets.PrintVariableNames"]
# Validation
if ([string]::IsNullOrWhiteSpace($ConjurUrl)) {
throw "Required parameter CyberArk.Conjur.RetrieveSecrets.Url not specified"
}
if ([string]::IsNullOrWhiteSpace($ConjurAccount)) {
throw "Required parameter CyberArk.Conjur.RetrieveSecrets.Account not specified"
}
if ([string]::IsNullOrWhiteSpace($ConjurLogin)) {
throw "Required parameter CyberArk.Conjur.RetrieveSecrets.Login not specified"
}
if ([string]::IsNullOrWhiteSpace($ConjurApiKey)) {
throw "Required parameter CyberArk.Conjur.RetrieveSecrets.ApiKey not specified"
}
if ([string]::IsNullOrWhiteSpace($ConjurSecretVariables)) {
throw "Required parameter CyberArk.Conjur.RetrieveSecrets.SecretVariables not specified"
}
### Helper functions
# This function creates a URI and prevents Urls that have been Url encoded from being re-encoded.
# Typically this happens on Windows (dynamic) workers in Octopus, and not PS Core.
# Helpful background - https://stackoverflow.com/questions/25596564/percent-encoded-slash-is-decoded-before-the-request-dispatch
# Function based from https://github.com/IISResetMe/PSdotNETRuntimeHacks/blob/trunk/Set-DontUnescapePathDotsAndSlashes.ps1
function New-DontUnescapePathDotsAndSlashes-Uri {
param(
[Parameter(Mandatory = $true)]
[ValidateNotNull()]
[string]$SourceUri
)
$uri = New-Object System.Uri $SourceUri
# If running PS Core, not affected
if ($PSEdition -eq "Core") {
return $uri
}
# Retrieve the private Syntax field from the uri class,
# this is our indirect reference to the attached parser
$syntaxFieldInfo = $uri.GetType().GetField('m_Syntax', 'NonPublic,Instance')
if (-not $syntaxFieldInfo) {
throw [System.MissingFieldException]"'m_Syntax' field not found"
}
# Retrieve the private Flags field from the parser class,
# this is the value we're looking to update at runtime
$flagsFieldInfo = [System.UriParser].GetField('m_Flags', 'NonPublic,Instance')
if (-not $flagsFieldInfo) {
throw [System.MissingFieldException]"'m_Flags' field not found"
}
# Retrieve the actual instances
$uriParser = $syntaxFieldInfo.GetValue($uri)
$uriSyntaxFlags = $flagsFieldInfo.GetValue($uriParser)
# Define the bit flags we want to remove
$UnEscapeDotsAndSlashes = 0x2000000
$SimpleUserSyntax = 0x20000
# Clear the flags that we don't want
$uriSyntaxFlags = [int]$uriSyntaxFlags -band -bnot($UnEscapeDotsAndSlashes)
$uriSyntaxFlags = [int]$uriSyntaxFlags -band -bnot($SimpleUserSyntax)
# Overwrite the existing Flags field
$flagsFieldInfo.SetValue($uriParser, $uriSyntaxFlags)
return $uri
}
function Get-WebRequestErrorBody {
param (
$RequestError
)
$rawResponse = ""
# Powershell < 6 you can read the Exception
if ($PSVersionTable.PSVersion.Major -lt 6) {
if ($RequestError.Exception.Response) {
$reader = New-Object System.IO.StreamReader($RequestError.Exception.Response.GetResponseStream())
$reader.BaseStream.Position = 0
$reader.DiscardBufferedData()
$rawResponse = $reader.ReadToEnd()
}
}
else {
$rawResponse = $RequestError.ErrorDetails.Message
}
try { $response = $rawResponse | ConvertFrom-Json } catch { $response = $rawResponse }
return $response
}
function Format-SecretName {
[CmdletBinding()]
Param(
[string] $Name,
[string] $Version
)
$displayName = "'$Name'"
if (![string]::IsNullOrWhiteSpace($Version)) {
$displayName += " (v:$($Version))"
}
return $displayName
}
### End Helper function
$Secrets = @()
$VariablesCreated = 0
$StepName = $OctopusParameters["Octopus.Step.Name"]
$ConjurUrl = $ConjurUrl.TrimEnd("/")
# Extract secret names
@(($ConjurSecretVariables -Split "`n").Trim()) | ForEach-Object {
if (![string]::IsNullOrWhiteSpace($_)) {
Write-Verbose "Working on: '$_'"
$secretDefinition = ($_ -Split "\|")
$secretName = $secretDefinition[0].Trim()
$secretNameAndVersion = ($secretName -Split " ")
$secretVersion = ""
if ($secretNameAndVersion.Count -gt 1) {
$secretName = $secretNameAndVersion[0].Trim()
$secretVersion = $secretNameAndVersion[1].Trim()
}
if ([string]::IsNullOrWhiteSpace($secretName)) {
throw "Unable to establish secret name from: '$($_)'"
}
$UriEscapedName = [uri]::EscapeDataString($secretName)
$VariableIdPrefix = "$($ConjurAccount):variable"
$secret = [PsCustomObject]@{
Name = $secretName
UriEscapedName = $uriEscapedName
Version = $secretVersion
VariableName = if (![string]::IsNullOrWhiteSpace($secretDefinition[1])) { $secretDefinition[1].Trim() } else { "" }
VariableId = "$($VariableIdPrefix):$($secretName)"
UriEscapedVariableId = "$($VariableIdPrefix):$($UriEscapedName)"
}
$Secrets += $secret
}
}
$SecretsWithVersionSpecified = @($Secrets | Where-Object { ![string]::IsNullOrWhiteSpace($_.Version) })
Write-Verbose "Conjur Url: $ConjurUrl"
Write-Verbose "Conjur Account: $ConjurAccount"
Write-Verbose "Conjur Login: $ConjurLogin"
Write-Verbose "Conjur API Key: ********"
Write-Verbose "Secrets to retrieve: $($Secrets.Count)"
Write-Verbose "Secrets with Version specified: $($SecretsWithVersionSpecified.Count)"
Write-Verbose "Print variables: $PrintVariableNames"
try {
$headers = @{
"Content-Type" = "application/json";
"Accept-Encoding" = "base64"
}
$body = $ConjurApiKey
$loginUriSegment = [uri]::EscapeDataString($ConjurLogin)
$authnUri = New-DontUnescapePathDotsAndSlashes-Uri -SourceUri "$ConjurUrl/authn/$ConjurAccount/$loginUriSegment/authenticate"
$authToken = Invoke-RestMethod -Uri $authnUri -Method Post -Headers $headers -Body $body
}
catch {
$ExceptionMessage = $_.Exception.Message
$ErrorBody = Get-WebRequestErrorBody -RequestError $_
$Message = "An error occurred logging in to Conjur: $ExceptionMessage"
$AdditionalDetail = ""
if (![string]::IsNullOrWhiteSpace($ErrorBody)) {
if ($null -ne $ErrorBody.error) {
$AdditionalDetail = "$($ErrorBody.error.code) - $($ErrorBody.error.message)"
}
else {
$AdditionalDetail += $ErrorBody
}
}
if (![string]::IsNullOrWhiteSpace($AdditionalDetail)) {
$Message += "`nDetail: $AdditionalDetail"
}
Write-Error $Message -Category AuthenticationError
}
if ([string]::IsNullOrWhiteSpace($authToken)) {
Write-Error "Null or Empty token!"
return
}
# Set token auth header
$headers = @{
"Authorization" = "Token token=`"$($authToken)`"";
}
if ($SecretsWithVersionSpecified.Count -gt 0) {
Write-Verbose "Retrieving secrets individually as at least one has a version specified."
foreach ($secret in $Secrets) {
try {
$name = $secret.Name
$uriEscapedName = $secret.UriEscapedName
$secretVersion = $secret.Version
$variableName = $secret.VariableName
$displayName = Format-SecretName -Name $name -Version $secretVersion
if ([string]::IsNullOrWhiteSpace($variableName)) {
$variableName = "$($name.Trim().Replace("/","."))"
}
$secretUri = "$ConjurUrl/secrets/$ConjurAccount/variable/$uriEscapedName"
if (![string]::IsNullOrWhiteSpace($secretVersion)) {
$secretUri += "?version=$($secretVersion)"
}
$secretUri = New-DontUnescapePathDotsAndSlashes-Uri -SourceUri "$secretUri"
Write-Verbose "Retrieving Secret $displayName"
$secretValue = Invoke-RestMethod -Uri $secretUri -Method Get -Headers $headers
if ([string]::IsNullOrWhiteSpace($secretValue)) {
Write-Error "Error: Secret $displayName not found or has no versions."
break;
}
Set-OctopusVariable -Name $variableName -Value $secretValue -Sensitive
if ($PrintVariableNames -eq $True) {
Write-Output "Created output variable: ##{Octopus.Action[$StepName].Output.$variableName}"
}
$VariablesCreated += 1
}
catch {
$ExceptionMessage = $_.Exception.Message
$ErrorBody = Get-WebRequestErrorBody -RequestError $_
$Message = "An error occurred retrieving secret $($displayName) from Conjur: $ExceptionMessage"
$AdditionalDetail = ""
if (![string]::IsNullOrWhiteSpace($ErrorBody)) {
if ($null -ne $ErrorBody.error) {
$AdditionalDetail = "$($ErrorBody.error.code) - $($ErrorBody.error.message)"
}
else {
$AdditionalDetail += $ErrorBody
}
}
if (![string]::IsNullOrWhiteSpace($AdditionalDetail)) {
$Message += "`nDetail: $AdditionalDetail"
}
Write-Error $Message -Category ReadError
break;
}
}
}
else {
Write-Verbose "Retrieving secrets by batch as no versions specified."
$uriEscapedVariableIds = @($Secrets | ForEach-Object { "$($_.UriEscapedVariableId)" }) -Join ","
try {
$secretsUri = New-DontUnescapePathDotsAndSlashes-Uri -SourceUri "$ConjurUrl/secrets?variable_ids=$($uriEscapedVariableIds)"
$secretValues = Invoke-RestMethod -Uri $secretsUri -Method Get -Headers $headers
$secretKeyValues = $secretValues | Get-Member | Where-Object { $_.MemberType -eq "NoteProperty" } | Select-Object -ExpandProperty "Name"
foreach ($secret in $Secrets) {
$name = $secret.Name
$variableId = $secret.VariableId
$variableName = $secret.VariableName
Write-Verbose "Extracting Secret '$($name)' from Conjur batched response"
if ([string]::IsNullOrWhiteSpace($variableName)) {
$variableName = "$($name.Trim().Replace("/","."))"
}
if ($secretKeyValues -inotcontains $variableId) {
Write-Error "Secret '$name' not found in Conjur response."
return
}
$variableValue = $secretValues.$variableId
Set-OctopusVariable -Name $variableName -Value $variableValue -Sensitive
if ($PrintVariableNames -eq $True) {
Write-Host "Created output variable: ##{Octopus.Action[$StepName].Output.$variableName}"
}
$VariablesCreated += 1
}
}
catch {
$ExceptionMessage = $_.Exception.Message
$ErrorBody = Get-WebRequestErrorBody -RequestError $_
$Message = "An error occurred retrieving batched secrets from Conjur: $ExceptionMessage"
$AdditionalDetail = ""
if (![string]::IsNullOrWhiteSpace($ErrorBody)) {
if ($null -ne $ErrorBody.error) {
$AdditionalDetail = "$($ErrorBody.error.code) - $($ErrorBody.error.message)"
}
else {
$AdditionalDetail += $ErrorBody
}
}
if (![string]::IsNullOrWhiteSpace($AdditionalDetail)) {
$Message += "`nDetail: $AdditionalDetail"
}
Write-Error $Message -Category AuthenticationError
}
}
Write-Host "Created $variablesCreated output variables"
Provided under the Apache License version 2.0.
To use this template in Octopus Deploy, copy the JSON below and paste it into the Library → Step templates → Import dialog.
{
"Id": "522c7010-7189-4b2e-a3c8-36cb1759422a",
"Name": "CyberArk Conjur - Retrieve Secrets",
"Description": "This step retrieves one or more secrets from [CyberArk Conjur](https://www.conjur.org/) and creates [sensitive output variables](https://octopus.com/docs/projects/variables/output-variables#sensitive-output-variables) for each value retrieved. These values can be used in other steps in your deployment or runbook process.\n\nThis step differs from the [CyberArk Conjur - Retrieve a Secret](https://library.octopus.com/step-templates/eafe9740-1008-4375-9e82-0d193109b669/actiontemplate-cyberark-conjur-retrieve-a-secret) step template as it offers the ability to retrieve multiple secrets (with optional version) and performs a batched call where possible - see below for further details.\n\n---\n\n**Retrieval Behavior:**\n\n- If any of the Conjur Variables have a version specified to retrieve, then the step template will retrieve **all** of the secrets individually using the [Conjur REST API - Secret Retrieve](https://docs.conjur.org/Latest/en/Content/Developer/Conjur_API_Retrieve_Secret.htm) endpoint.\n- If none of the Conjur Variables have a version specified (i.e. retrieve the latest version) then the step template will retrieve the secrets using the [Conjur REST API - Batch Retrieval](https://docs.conjur.org/Latest/en/Content/Developer/Conjur_API_Batch_Retrieve.htm) endpoint.\n\n*Hint:* If performance is important to you, don't include specific versions of Conjur Variables. It’s faster to fetch secrets in a batch than to fetch them one at a time.\n\n---\n\n**Required:** \n- PowerShell **5.1** or higher.\n- A set of credentials with permissions to retrieve secrets from CyberArk Conjur.\n- Access to the Conjur instance from the Worker or target where this step executes.\n\nNotes:\n\n- Tested on Conjur **v1.13.2** / API **v5.2.0**.\n- Tested on Octopus **2021.2**.\n- Tested on both Windows Server 2019 and Ubuntu 20.04.",
"Version": 1,
"ExportedAt": "2021-10-19T10:19:57.315Z",
"ActionType": "Octopus.Script",
"Author": "harrisonmeister",
"Packages": [],
"Parameters": [
{
"Id": "66a70ea0-8d3a-4682-9575-c1dae8ad75e6",
"Name": "CyberArk.Conjur.RetrieveSecrets.Url",
"Label": "Conjur URL",
"HelpText": "The URL of the Conjur instance you are connecting to.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "ceae6659-4643-490d-9d8d-f642c1c1b4a0",
"Name": "CyberArk.Conjur.RetrieveSecrets.Account",
"Label": "Conjur Account",
"HelpText": "The Conjur account. This is the Conjur appliance identifier provided during Conjur configuration.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "0f501e04-207f-4a05-9d21-1e2462bf5b73",
"Name": "CyberArk.Conjur.RetrieveSecrets.Login",
"Label": "Conjur Login",
"HelpText": "The username (from the point of view of the authenticator) of the user or machine (host) requesting authentication. For a host, the id assigned when the host was created should be used, prepended with the literal `host/`.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "3985b74e-1ea8-4bda-affa-9e7b22056c58",
"Name": "CyberArk.Conjur.RetrieveSecrets.ApiKey",
"Label": "Conjur Api Key",
"HelpText": "The API Key corresponding to the user/host provided.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "Sensitive"
}
},
{
"Id": "eefe9594-7dd1-4fa4-9bb1-65ced026fdda",
"Name": "CyberArk.Conjur.RetrieveSecrets.SecretVariables",
"Label": "Conjur Secret Variable IDs",
"HelpText": "Specify the names of the secrets to be returned from Conjur, in the format:\n\n`VariableID Version | OutputVariableName` where:\n\n- `VariableID` is the Variable ID of the Conjur secret.\n- `Version` is the version of the secret to retrieve. *If this value isn't specified, the latest version will be retrieved*.\n- `OutputVariableName` is the _optional_ Octopus [output variable](https://octopus.com/docs/projects/variables/output-variables) name to store the secret's value in. *If this value isn't specified, an output name will be generated dynamically*.\n\n**Note:** Multiple Variable IDs can be retrieved by entering each one on a new line.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "MultiLineText"
}
},
{
"Id": "462f3385-dccd-4ac1-a30b-b06029fbfc18",
"Name": "CyberArk.Conjur.RetrieveSecrets.PrintVariableNames",
"Label": "Print output variable names",
"HelpText": "Write out the Octopus [output variable](https://octopus.com/docs/projects/variables/output-variables) names to the task log. Default: `False`.",
"DefaultValue": "False",
"DisplaySettings": {
"Octopus.ControlType": "Checkbox"
}
}
],
"Properties": {
"Octopus.Action.Script.ScriptSource": "Inline",
"Octopus.Action.Script.Syntax": "PowerShell",
"Octopus.Action.Script.ScriptBody": "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12\n$ErrorActionPreference = 'Stop'\n\n# Variables\n$ConjurUrl = $OctopusParameters[\"CyberArk.Conjur.RetrieveSecrets.Url\"]\n$ConjurAccount = $OctopusParameters[\"CyberArk.Conjur.RetrieveSecrets.Account\"]\n$ConjurLogin = $OctopusParameters[\"CyberArk.Conjur.RetrieveSecrets.Login\"]\n$ConjurApiKey = $OctopusParameters[\"CyberArk.Conjur.RetrieveSecrets.ApiKey\"]\n$ConjurSecretVariables = $OctopusParameters[\"CyberArk.Conjur.RetrieveSecrets.SecretVariables\"]\n$PrintVariableNames = $OctopusParameters[\"CyberArk.Conjur.RetrieveSecrets.PrintVariableNames\"]\n\n# Validation\nif ([string]::IsNullOrWhiteSpace($ConjurUrl)) {\n throw \"Required parameter CyberArk.Conjur.RetrieveSecrets.Url not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($ConjurAccount)) {\n throw \"Required parameter CyberArk.Conjur.RetrieveSecrets.Account not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($ConjurLogin)) {\n throw \"Required parameter CyberArk.Conjur.RetrieveSecrets.Login not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($ConjurApiKey)) {\n throw \"Required parameter CyberArk.Conjur.RetrieveSecrets.ApiKey not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($ConjurSecretVariables)) {\n throw \"Required parameter CyberArk.Conjur.RetrieveSecrets.SecretVariables not specified\"\n}\n\n### Helper functions\n\n# This function creates a URI and prevents Urls that have been Url encoded from being re-encoded.\n# Typically this happens on Windows (dynamic) workers in Octopus, and not PS Core.\n# Helpful background - https://stackoverflow.com/questions/25596564/percent-encoded-slash-is-decoded-before-the-request-dispatch\n# Function based from https://github.com/IISResetMe/PSdotNETRuntimeHacks/blob/trunk/Set-DontUnescapePathDotsAndSlashes.ps1\nfunction New-DontUnescapePathDotsAndSlashes-Uri {\n param(\n [Parameter(Mandatory = $true)]\n [ValidateNotNull()]\n [string]$SourceUri\n )\n\n $uri = New-Object System.Uri $SourceUri\n\n # If running PS Core, not affected\n if ($PSEdition -eq \"Core\") {\n return $uri\n }\n\n # Retrieve the private Syntax field from the uri class,\n # this is our indirect reference to the attached parser\n $syntaxFieldInfo = $uri.GetType().GetField('m_Syntax', 'NonPublic,Instance')\n if (-not $syntaxFieldInfo) {\n throw [System.MissingFieldException]\"'m_Syntax' field not found\"\n }\n\n # Retrieve the private Flags field from the parser class,\n # this is the value we're looking to update at runtime\n $flagsFieldInfo = [System.UriParser].GetField('m_Flags', 'NonPublic,Instance')\n if (-not $flagsFieldInfo) {\n throw [System.MissingFieldException]\"'m_Flags' field not found\"\n }\n\n # Retrieve the actual instances\n $uriParser = $syntaxFieldInfo.GetValue($uri)\n $uriSyntaxFlags = $flagsFieldInfo.GetValue($uriParser)\n\n # Define the bit flags we want to remove\n $UnEscapeDotsAndSlashes = 0x2000000\n $SimpleUserSyntax = 0x20000\n\n # Clear the flags that we don't want\n $uriSyntaxFlags = [int]$uriSyntaxFlags -band -bnot($UnEscapeDotsAndSlashes)\n $uriSyntaxFlags = [int]$uriSyntaxFlags -band -bnot($SimpleUserSyntax)\n\n # Overwrite the existing Flags field\n $flagsFieldInfo.SetValue($uriParser, $uriSyntaxFlags)\n\n return $uri\n}\n\nfunction Get-WebRequestErrorBody {\n param (\n $RequestError\n )\n $rawResponse = \"\"\n # Powershell < 6 you can read the Exception\n if ($PSVersionTable.PSVersion.Major -lt 6) {\n if ($RequestError.Exception.Response) {\n $reader = New-Object System.IO.StreamReader($RequestError.Exception.Response.GetResponseStream())\n $reader.BaseStream.Position = 0\n $reader.DiscardBufferedData()\n $rawResponse = $reader.ReadToEnd()\n }\n }\n else {\n $rawResponse = $RequestError.ErrorDetails.Message\n }\n\n try { $response = $rawResponse | ConvertFrom-Json } catch { $response = $rawResponse }\n return $response\n}\n\nfunction Format-SecretName {\n [CmdletBinding()]\n Param(\n [string] $Name,\n [string] $Version\n )\n $displayName = \"'$Name'\"\n if (![string]::IsNullOrWhiteSpace($Version)) {\n $displayName += \" (v:$($Version))\"\n }\n return $displayName\n}\n\n### End Helper function\n\n$Secrets = @()\n$VariablesCreated = 0\n$StepName = $OctopusParameters[\"Octopus.Step.Name\"]\n$ConjurUrl = $ConjurUrl.TrimEnd(\"/\")\n\n# Extract secret names\n@(($ConjurSecretVariables -Split \"`n\").Trim()) | ForEach-Object {\n if (![string]::IsNullOrWhiteSpace($_)) {\n Write-Verbose \"Working on: '$_'\"\n $secretDefinition = ($_ -Split \"\\|\")\n $secretName = $secretDefinition[0].Trim()\n $secretNameAndVersion = ($secretName -Split \" \")\n $secretVersion = \"\"\n if ($secretNameAndVersion.Count -gt 1) {\n $secretName = $secretNameAndVersion[0].Trim()\n $secretVersion = $secretNameAndVersion[1].Trim()\n }\n if ([string]::IsNullOrWhiteSpace($secretName)) {\n throw \"Unable to establish secret name from: '$($_)'\"\n }\n\n $UriEscapedName = [uri]::EscapeDataString($secretName)\n $VariableIdPrefix = \"$($ConjurAccount):variable\"\n\n $secret = [PsCustomObject]@{\n Name = $secretName\n UriEscapedName = $uriEscapedName\n Version = $secretVersion\n VariableName = if (![string]::IsNullOrWhiteSpace($secretDefinition[1])) { $secretDefinition[1].Trim() } else { \"\" }\n VariableId = \"$($VariableIdPrefix):$($secretName)\"\n UriEscapedVariableId = \"$($VariableIdPrefix):$($UriEscapedName)\"\n }\n $Secrets += $secret\n }\n}\n$SecretsWithVersionSpecified = @($Secrets | Where-Object { ![string]::IsNullOrWhiteSpace($_.Version) })\n\nWrite-Verbose \"Conjur Url: $ConjurUrl\"\nWrite-Verbose \"Conjur Account: $ConjurAccount\"\nWrite-Verbose \"Conjur Login: $ConjurLogin\"\nWrite-Verbose \"Conjur API Key: ********\"\nWrite-Verbose \"Secrets to retrieve: $($Secrets.Count)\"\nWrite-Verbose \"Secrets with Version specified: $($SecretsWithVersionSpecified.Count)\"\nWrite-Verbose \"Print variables: $PrintVariableNames\"\n\ntry {\n\n $headers = @{\n \"Content-Type\" = \"application/json\"; \n \"Accept-Encoding\" = \"base64\"\n }\n\n $body = $ConjurApiKey\n $loginUriSegment = [uri]::EscapeDataString($ConjurLogin)\n $authnUri = New-DontUnescapePathDotsAndSlashes-Uri -SourceUri \"$ConjurUrl/authn/$ConjurAccount/$loginUriSegment/authenticate\"\n $authToken = Invoke-RestMethod -Uri $authnUri -Method Post -Headers $headers -Body $body\n}\ncatch {\n $ExceptionMessage = $_.Exception.Message\n $ErrorBody = Get-WebRequestErrorBody -RequestError $_\n $Message = \"An error occurred logging in to Conjur: $ExceptionMessage\"\n $AdditionalDetail = \"\"\n if (![string]::IsNullOrWhiteSpace($ErrorBody)) {\n if ($null -ne $ErrorBody.error) {\n $AdditionalDetail = \"$($ErrorBody.error.code) - $($ErrorBody.error.message)\"\n }\n else {\n $AdditionalDetail += $ErrorBody\n }\n }\n if (![string]::IsNullOrWhiteSpace($AdditionalDetail)) {\n $Message += \"`nDetail: $AdditionalDetail\"\n }\n \n Write-Error $Message -Category AuthenticationError\n}\n\nif ([string]::IsNullOrWhiteSpace($authToken)) {\n Write-Error \"Null or Empty token!\"\n return\n}\n\n# Set token auth header\n$headers = @{\n \"Authorization\" = \"Token token=`\"$($authToken)`\"\"; \n}\n\nif ($SecretsWithVersionSpecified.Count -gt 0) {\n Write-Verbose \"Retrieving secrets individually as at least one has a version specified.\"\n foreach ($secret in $Secrets) {\n try {\n $name = $secret.Name\n $uriEscapedName = $secret.UriEscapedName\n $secretVersion = $secret.Version\n $variableName = $secret.VariableName\n $displayName = Format-SecretName -Name $name -Version $secretVersion\n\n if ([string]::IsNullOrWhiteSpace($variableName)) {\n $variableName = \"$($name.Trim().Replace(\"/\",\".\"))\"\n }\n $secretUri = \"$ConjurUrl/secrets/$ConjurAccount/variable/$uriEscapedName\"\n if (![string]::IsNullOrWhiteSpace($secretVersion)) {\n $secretUri += \"?version=$($secretVersion)\"\n }\n $secretUri = New-DontUnescapePathDotsAndSlashes-Uri -SourceUri \"$secretUri\"\n Write-Verbose \"Retrieving Secret $displayName\"\n $secretValue = Invoke-RestMethod -Uri $secretUri -Method Get -Headers $headers \n\n if ([string]::IsNullOrWhiteSpace($secretValue)) {\n Write-Error \"Error: Secret $displayName not found or has no versions.\"\n break;\n }\n \n Set-OctopusVariable -Name $variableName -Value $secretValue -Sensitive\n \n if ($PrintVariableNames -eq $True) {\n Write-Output \"Created output variable: ##{Octopus.Action[$StepName].Output.$variableName}\"\n }\n $VariablesCreated += 1\n }\n catch {\n $ExceptionMessage = $_.Exception.Message\n $ErrorBody = Get-WebRequestErrorBody -RequestError $_\n $Message = \"An error occurred retrieving secret $($displayName) from Conjur: $ExceptionMessage\"\n $AdditionalDetail = \"\"\n if (![string]::IsNullOrWhiteSpace($ErrorBody)) {\n if ($null -ne $ErrorBody.error) {\n $AdditionalDetail = \"$($ErrorBody.error.code) - $($ErrorBody.error.message)\"\n }\n else {\n $AdditionalDetail += $ErrorBody\n }\n }\n \n if (![string]::IsNullOrWhiteSpace($AdditionalDetail)) {\n $Message += \"`nDetail: $AdditionalDetail\"\n }\n \n Write-Error $Message -Category ReadError\n break;\n }\n }\n}\nelse {\n Write-Verbose \"Retrieving secrets by batch as no versions specified.\"\n $uriEscapedVariableIds = @($Secrets | ForEach-Object { \"$($_.UriEscapedVariableId)\" }) -Join \",\"\n\n try { \n $secretsUri = New-DontUnescapePathDotsAndSlashes-Uri -SourceUri \"$ConjurUrl/secrets?variable_ids=$($uriEscapedVariableIds)\"\n $secretValues = Invoke-RestMethod -Uri $secretsUri -Method Get -Headers $headers\n $secretKeyValues = $secretValues | Get-Member | Where-Object { $_.MemberType -eq \"NoteProperty\" } | Select-Object -ExpandProperty \"Name\"\n foreach ($secret in $Secrets) {\n $name = $secret.Name\n $variableId = $secret.VariableId\n $variableName = $secret.VariableName\n\n Write-Verbose \"Extracting Secret '$($name)' from Conjur batched response\"\n\n if ([string]::IsNullOrWhiteSpace($variableName)) {\n $variableName = \"$($name.Trim().Replace(\"/\",\".\"))\"\n }\n if ($secretKeyValues -inotcontains $variableId) {\n Write-Error \"Secret '$name' not found in Conjur response.\"\n return\n }\n \n $variableValue = $secretValues.$variableId\n Set-OctopusVariable -Name $variableName -Value $variableValue -Sensitive\n\n if ($PrintVariableNames -eq $True) {\n Write-Host \"Created output variable: ##{Octopus.Action[$StepName].Output.$variableName}\"\n }\n $VariablesCreated += 1\n }\n }\n catch {\n $ExceptionMessage = $_.Exception.Message\n $ErrorBody = Get-WebRequestErrorBody -RequestError $_\n $Message = \"An error occurred retrieving batched secrets from Conjur: $ExceptionMessage\"\n $AdditionalDetail = \"\"\n if (![string]::IsNullOrWhiteSpace($ErrorBody)) {\n if ($null -ne $ErrorBody.error) {\n $AdditionalDetail = \"$($ErrorBody.error.code) - $($ErrorBody.error.message)\"\n }\n else {\n $AdditionalDetail += $ErrorBody\n }\n }\n if (![string]::IsNullOrWhiteSpace($AdditionalDetail)) {\n $Message += \"`nDetail: $AdditionalDetail\"\n }\n \n Write-Error $Message -Category AuthenticationError\n }\n}\n\nWrite-Host \"Created $variablesCreated output variables\""
},
"Category": "CyberArk",
"HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates//opt/buildagent/work/75443764cd38076d/step-templates/cyberark-conjur-retrieve-secrets.json",
"Website": "/step-templates/522c7010-7189-4b2e-a3c8-36cb1759422a",
"Logo": "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f/rT5pgoL6KI/Pa3vz322GNvv/32BCiq+vnPfz7BSi6XW7JkyQ033FA2SeXjJMqgp6fnm9/8pqrW1tYC+MlPfnLyyScnyEg+lkqlkj+3YciSYz7zzDOnn376r3/9a2vt5h5eLpdLFO0OmrPNbVMYhsnvt30EZn711VfPOeecH/7whwmd473fMhb7JyiaO5983ecbw9EN1FTHTbU8vM6OHtZlGm97/A0gpGTO9KZftYoUHCBBylJjIzcPo6YGNNWjuZ6aaml4nhrz1FxHzXW2KR8050xjrifbNOOd2n/6X89++zePFsiSOkmK3KBKAsDkajGi3jbVcWOtaa5F08hsugEQuF5jg1sfmnPjnxcGe+3JI5gbM8HIujA7knq7f/utj5555NQ4ihOrNWbMmLPOOuuss84aN25cYj3sIKfnl7/85eWXX26MyeVyvb29uVzuxBNPPPTQQ/fZZ58wDJctW/bcc88988wzra2txpi2trarr776gx/84NixYxPEfOtb35oxY8ayZcuMMT/96U8/+tGPHnfccWXEJMttjPnZz342c+bMfD7f1dV15plnfulLXyqb1OTPRFOWSqWGhoZzzjnHWpt8oOxRdXV1Pf3008kW1zl3xRVXHHroodOmTRvk2CXKwzlXU1Nz2GGHJdewRYgYY7q6ukaNGrW521R2ns4///x8Pj/IlY7j+LXXXpszZ04QBM65q6++esqUKRdccMHmyn5AT4ix4WsrWv84cw3VjPFRSSlI3C5xHg31d76y4J/PPnDvEfVe/KbFiSrkoQoQeVUfqStAHSiZCQqwL7eFdmQBhnOgDNcPN/mmGx+Y15BPfevCD5IrElmwCEGAWC187L1TcQwLEVEApTCbeeq1lVf+19/c2JEwHegTUEYzoa5ecP2l0z/2gb174jhtOHmpkiVKVib5qy2bJ2vto48+evnllycGpbe395JLLrnyyisPOOCAyvf4y1/+8tKlS//jP/7j+uuvnzhx4t133z127NhEaUVRNH78+Guvvfbiiy9O/vqtb33r0UcfzWazybubeG+zZs36wQ9+QETd3d11dXXXXnttKpUqlUrJnmCQU7LXXnvddNNNuVxu0OMkosWLF1911VX33ntvEASlUumOO+6YNm3aFkGjqvvuu+8999yTz+fL3tgWNwHJVrfyA2WnLZ1O//CHP5w0aVIldssov/HG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",
"$Meta": {
"Type": "ActionTemplate"
}
}
Page updated on Tuesday, October 19, 2021