HashiCorp Vault - AppRole Unwrap Secret ID

Octopus.Script exported 2022-09-18 by harrisonmeister belongs to ‘HashiCorp Vault’ category.

This step retrieves (and unwraps) a Secret ID for an AppRole using a wrapped auth token from a HashiCorp Vault server.


One property from the response will be made available as a sensitive Output variable:

  • data.secret_id - This is the unwrapped Secret ID from Vault. The output variable name will be UnwrappedSecretID.

This step template makes use of the Rest API, so no other dependencies are needed.


Required:

  • The Vault server must be unsealed.
  • The wrapped auth token used to retrieve the unwrapped Secret ID.

Optional


Notes:

  • Tested on Vault Server 1.11.3.
  • Tested on both PowerShell Desktop and PowerShell Core.
  • See the HashiCorp AppRole patterns documentation for further information.

Parameters

When steps based on the template are included in a project’s deployment process, the parameters below can be set.

Vault Server URL

Vault.AppRole.UnwrapSecretID.VaultAddress =

The URL of the Vault instance you are connecting to. Port should be included (The default is 8200). For example:

https://myvault.local:8200/

API version

Vault.AppRole.UnwrapSecretID.ApiVersion = v1

All API routes are prefixed with a version e.g. /v1/.

See the API documentation for further details.

Namespace (Optional)

Vault.AppRole.UnwrapSecretID.Namespace =

The optional namespace to use. Nested namespaces can also be supplied, e.g. ns1/ns2.

Note: This field is only supported on Vault Enterprise .

Wrapped Token

Vault.AppRole.UnwrapSecretID.WrappedToken =

This is the wrapped token used to retrieve the actual Secret ID from Vault.

Token Creation Path

Vault.AppRole.UnwrapSecretID.WrappedTokenCreationPath =

Optional - the creation path of the wrapped token. If this parameter value is provided, the step template will perform a wrapping lookup to validate no malfeasance has occurred.

Script body

Steps based on this template will execute the following PowerShell script.

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

# Variables
$VAULT_APPROLE_UNWRAP_SECRETID_ADDRESS = $OctopusParameters["Vault.AppRole.UnwrapSecretID.VaultAddress"]
$VAULT_APPROLE_UNWRAP_SECRETID_API_VERSION = $OctopusParameters["Vault.AppRole.UnwrapSecretID.ApiVersion"]
$VAULT_APPROLE_UNWRAP_SECRETID_TOKEN = $OctopusParameters["Vault.AppRole.UnwrapSecretID.WrappedToken"]

# Optional Variables
$VAULT_APPROLE_UNWRAP_SECRETID_NAMESPACE = $OctopusParameters["Vault.AppRole.UnwrapSecretID.Namespace"]
$VAULT_APPROLE_UNWRAP_SECRETID_TOKEN_CREATION_PATH = $OctopusParameters["Vault.AppRole.UnwrapSecretID.WrappedTokenCreationPath"]

# Validation
if ([string]::IsNullOrWhiteSpace($VAULT_APPROLE_UNWRAP_SECRETID_ADDRESS)) {
    throw "Required parameter VAULT_APPROLE_UNWRAP_SECRETID_ADDRESS not specified"
}
if ([string]::IsNullOrWhiteSpace($VAULT_APPROLE_UNWRAP_SECRETID_API_VERSION)) {
    throw "Required parameter VAULT_APPROLE_UNWRAP_SECRETID_API_VERSION not specified"
}

if ([string]::IsNullOrWhiteSpace($VAULT_APPROLE_UNWRAP_SECRETID_TOKEN)) {
    throw "Required parameter VAULT_APPROLE_UNWRAP_SECRETID_TOKEN not specified"
}

# Helper functions
###############################################################################
function Get-WebRequestErrorBody {
    param (
        $RequestError
    )

    # 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()
            $response = ""
            try { $response = $rawResponse | ConvertFrom-Json } catch { $response = $rawResponse }
            return $response
        }
    }
    else {
        return $RequestError.ErrorDetails.Message
    }
}
###############################################################################

$VAULT_APPROLE_UNWRAP_SECRETID_ADDRESS = $VAULT_APPROLE_UNWRAP_SECRETID_ADDRESS.TrimEnd('/')

# Local variables
$StepName = $OctopusParameters["Octopus.Step.Name"]

try {

    Write-Verbose "X-Vault-Namespace header: $VAULT_APPROLE_UNWRAP_SECRETID_NAMESPACE"

    # Should we validate lookup token's creation path?
    if (![string]::IsNullOrWhiteSpace($VAULT_APPROLE_UNWRAP_SECRETID_TOKEN_CREATION_PATH)) {
        $uri = "$VAULT_APPROLE_UNWRAP_SECRETID_ADDRESS/$VAULT_APPROLE_UNWRAP_SECRETID_API_VERSION/sys/wrapping/lookup"    
        $payload = @{
            token = $VAULT_APPROLE_UNWRAP_SECRETID_TOKEN
        }

        $Headers = @{}
        if (-not [string]::IsNullOrWhiteSpace($VAULT_APPROLE_UNWRAP_SECRETID_NAMESPACE)) {
            $Headers.Add("X-Vault-Namespace", $VAULT_APPROLE_UNWRAP_SECRETID_NAMESPACE)
        }

        Write-Verbose "Making Post request to $uri"
        $response = Invoke-RestMethod -Uri $uri -Method Post -Body ($payload | ConvertTo-Json -Depth 10) -Headers $Headers

        if ($null -ne $response) {
            Write-Verbose "Validating Wrapped token creation path."
            $Lookup_CreationPath = $response.data.creation_path
            if ($VAULT_APPROLE_UNWRAP_SECRETID_TOKEN_CREATION_PATH -ne $Lookup_CreationPath) {
                throw "Supplied Wrapped token creation path failed lookup validation. Check the creation path value and retry."
            }
        }
        else {
            Write-Error "Null or Empty response returned from Vault server lookup" -Category InvalidResult
        }
    }

    # Call to unwrap secret id from wrapped token.
    $Headers = @{
        "X-Vault-Token" = $VAULT_APPROLE_UNWRAP_SECRETID_TOKEN
    }

    if (-not [string]::IsNullOrWhiteSpace($VAULT_APPROLE_UNWRAP_SECRETID_NAMESPACE)) {
        $Headers.Add("X-Vault-Namespace", $VAULT_APPROLE_UNWRAP_SECRETID_NAMESPACE)
    }
    
    $uri = "$VAULT_APPROLE_UNWRAP_SECRETID_ADDRESS/$VAULT_APPROLE_UNWRAP_SECRETID_API_VERSION/sys/wrapping/unwrap"
    Write-Verbose "Making Post request to $uri"
    $response = Invoke-RestMethod -Uri $uri -Headers $Headers -Method Post
    
    if ($null -ne $response) {
        Set-OctopusVariable -Name "UnwrappedSecretID" -Value $response.data.secret_id -Sensitive
        Write-Host "Created output variable: ##{Octopus.Action[$StepName].Output.UnwrappedSecretID}"
    }
    else {
        Write-Error "Null or Empty response returned from Vault server unwrap" -Category InvalidResult
    }
}
catch {
    $ExceptionMessage = $_.Exception.Message
    $ErrorBody = Get-WebRequestErrorBody -RequestError $_
    $Message = "An error occurred unwrapping secretid: $ExceptionMessage"
    $AdditionalDetail = ""
    if (![string]::IsNullOrWhiteSpace($ErrorBody)) {
        if ($null -ne $ErrorBody.errors) {
            $AdditionalDetail = $ErrorBody.errors -Join ","   
        }
        else {
            $errorDetails = $null
            try { $errorDetails = ConvertFrom-Json $ErrorBody } catch {}
            $AdditionalDetail += if ($null -ne $errorDetails) { $errorDetails.errors -Join "," } else { $ErrorBody } 
        }
    }
    
    if (![string]::IsNullOrWhiteSpace($AdditionalDetail)) {
        $Message += "`n`tDetail: $AdditionalDetail"
    }

    Write-Error $Message -Category ConnectionError
}

Provided under the Apache License version 2.0.

Report an issue

To use this template in Octopus Deploy, copy the JSON below and paste it into the Library → Step templates → Import dialog.

{
  "Id": "c1f56030-0bcd-458d-bc70-b4f43ec0d30f",
  "Name": "HashiCorp Vault - AppRole Unwrap Secret ID",
  "Description": "This step retrieves (and unwraps) a Secret ID for an [AppRole](https://www.vaultproject.io/docs/auth/approle) using a wrapped auth token from a HashiCorp Vault server.\n\n---\n\nOne property from the response will be made available as a [sensitive Output variable](https://octopus.com/docs/projects/variables/output-variables#sensitive-output-variables):\n\n- `data.secret_id` - This is the unwrapped Secret ID from Vault. The output variable name will be `UnwrappedSecretID`.\n\nThis step template makes use of the [Rest API](https://www.vaultproject.io/api-docs/auth/approle#login-with-approle), so no other dependencies are needed. \n\n---\n\n**Required:** \n- The Vault server must be [unsealed](https://www.vaultproject.io/docs/concepts/seal).\n- The wrapped [auth token](https://www.vaultproject.io/docs/auth/token) used to retrieve the unwrapped Secret ID. \n\n---\n\n*Optional*\n- The creation path of the wrapped token. If this parameter value is provided, the step template will perform a [wrapping lookup](https://www.vaultproject.io/api-docs/system/wrapping-lookup) to [validate no malfeasance](https://www.vaultproject.io/docs/concepts/response-wrapping#response-wrapping-token-validation) has occurred.\n- A Vault [namespace](https://www.vaultproject.io/docs/enterprise/namespaces) to use. Nested namespaces can also be supplied, e.g. `ns1/ns2`. **Note:** This field is only supported on [Vault Enterprise](https://www.hashicorp.com/products/vault).\n\n---\n\nNotes:\n\n- Tested on Vault Server `1.11.3`.\n- Tested on both PowerShell Desktop and PowerShell Core.\n- See the HashiCorp [AppRole patterns documentation](https://learn.hashicorp.com/tutorials/vault/pattern-approle?in=vault/recommended-patterns#vault-returns-a-token) for further information.",
  "Version": 4,
  "ExportedAt": "2022-09-18T09:22:26.156Z",
  "ActionType": "Octopus.Script",
  "Author": "harrisonmeister",
  "Packages": [],
  "Parameters": [
    {
      "Id": "b30bafd3-a5b6-4c26-8eea-af938f5ba7da",
      "Name": "Vault.AppRole.UnwrapSecretID.VaultAddress",
      "Label": "Vault Server URL",
      "HelpText": "The URL of the Vault instance you are connecting to. Port should be included (The default is `8200`). For example:\n\n\n`https://myvault.local:8200/`",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "a810fce1-3180-4eb8-b342-8b2d76a39667",
      "Name": "Vault.AppRole.UnwrapSecretID.ApiVersion",
      "Label": "API version",
      "HelpText": "All API routes are prefixed with a version e.g. `/v1/`.\n\nSee the [API documentation](https://www.vaultproject.io/api-docs) for further details.",
      "DefaultValue": "v1",
      "DisplaySettings": {
        "Octopus.ControlType": "Select",
        "Octopus.SelectOptions": "v1|v1"
      }
    },
    {
      "Id": "e60b5c0b-dacc-4a99-8907-82e57eb9f573",
      "Name": "Vault.AppRole.UnwrapSecretID.Namespace",
      "Label": "Namespace (Optional)",
      "HelpText": "The _optional_ [namespace](https://www.vaultproject.io/docs/enterprise/namespaces) to use. Nested namespaces can also be supplied, e.g. `ns1/ns2`.\n\n**Note:** This field is only supported on [Vault Enterprise](https://www.hashicorp.com/products/vault) .",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "6fd2fe01-9600-4ccc-a3f2-f733af79a255",
      "Name": "Vault.AppRole.UnwrapSecretID.WrappedToken",
      "Label": "Wrapped Token",
      "HelpText": "This is the wrapped token used to retrieve the actual Secret ID from Vault.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "Sensitive"
      }
    },
    {
      "Id": "6dc8f829-c89c-403f-805c-350710d8d855",
      "Name": "Vault.AppRole.UnwrapSecretID.WrappedTokenCreationPath",
      "Label": "Token Creation Path",
      "HelpText": "*Optional* - the creation path of the wrapped token. If this parameter value is provided, the step template will perform a [wrapping lookup](https://www.vaultproject.io/api-docs/system/wrapping-lookup) to [validate no malfeasance](https://www.vaultproject.io/docs/concepts/response-wrapping#response-wrapping-token-validation) has occurred.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    }
  ],
  "Properties": {
    "Octopus.Action.Script.ScriptSource": "Inline",
    "Octopus.Action.Script.Syntax": "PowerShell",
    "Octopus.Action.Script.ScriptBody": "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12\n\n# Variables\n$VAULT_APPROLE_UNWRAP_SECRETID_ADDRESS = $OctopusParameters[\"Vault.AppRole.UnwrapSecretID.VaultAddress\"]\n$VAULT_APPROLE_UNWRAP_SECRETID_API_VERSION = $OctopusParameters[\"Vault.AppRole.UnwrapSecretID.ApiVersion\"]\n$VAULT_APPROLE_UNWRAP_SECRETID_TOKEN = $OctopusParameters[\"Vault.AppRole.UnwrapSecretID.WrappedToken\"]\n\n# Optional Variables\n$VAULT_APPROLE_UNWRAP_SECRETID_NAMESPACE = $OctopusParameters[\"Vault.AppRole.UnwrapSecretID.Namespace\"]\n$VAULT_APPROLE_UNWRAP_SECRETID_TOKEN_CREATION_PATH = $OctopusParameters[\"Vault.AppRole.UnwrapSecretID.WrappedTokenCreationPath\"]\n\n# Validation\nif ([string]::IsNullOrWhiteSpace($VAULT_APPROLE_UNWRAP_SECRETID_ADDRESS)) {\n    throw \"Required parameter VAULT_APPROLE_UNWRAP_SECRETID_ADDRESS not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($VAULT_APPROLE_UNWRAP_SECRETID_API_VERSION)) {\n    throw \"Required parameter VAULT_APPROLE_UNWRAP_SECRETID_API_VERSION not specified\"\n}\n\nif ([string]::IsNullOrWhiteSpace($VAULT_APPROLE_UNWRAP_SECRETID_TOKEN)) {\n    throw \"Required parameter VAULT_APPROLE_UNWRAP_SECRETID_TOKEN not specified\"\n}\n\n# Helper functions\n###############################################################################\nfunction Get-WebRequestErrorBody {\n    param (\n        $RequestError\n    )\n\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            $response = \"\"\n            try { $response = $rawResponse | ConvertFrom-Json } catch { $response = $rawResponse }\n            return $response\n        }\n    }\n    else {\n        return $RequestError.ErrorDetails.Message\n    }\n}\n###############################################################################\n\n$VAULT_APPROLE_UNWRAP_SECRETID_ADDRESS = $VAULT_APPROLE_UNWRAP_SECRETID_ADDRESS.TrimEnd('/')\n\n# Local variables\n$StepName = $OctopusParameters[\"Octopus.Step.Name\"]\n\ntry {\n\n    Write-Verbose \"X-Vault-Namespace header: $VAULT_APPROLE_UNWRAP_SECRETID_NAMESPACE\"\n\n    # Should we validate lookup token's creation path?\n    if (![string]::IsNullOrWhiteSpace($VAULT_APPROLE_UNWRAP_SECRETID_TOKEN_CREATION_PATH)) {\n        $uri = \"$VAULT_APPROLE_UNWRAP_SECRETID_ADDRESS/$VAULT_APPROLE_UNWRAP_SECRETID_API_VERSION/sys/wrapping/lookup\"    \n        $payload = @{\n            token = $VAULT_APPROLE_UNWRAP_SECRETID_TOKEN\n        }\n\n        $Headers = @{}\n        if (-not [string]::IsNullOrWhiteSpace($VAULT_APPROLE_UNWRAP_SECRETID_NAMESPACE)) {\n            $Headers.Add(\"X-Vault-Namespace\", $VAULT_APPROLE_UNWRAP_SECRETID_NAMESPACE)\n        }\n\n        Write-Verbose \"Making Post request to $uri\"\n        $response = Invoke-RestMethod -Uri $uri -Method Post -Body ($payload | ConvertTo-Json -Depth 10) -Headers $Headers\n\n        if ($null -ne $response) {\n            Write-Verbose \"Validating Wrapped token creation path.\"\n            $Lookup_CreationPath = $response.data.creation_path\n            if ($VAULT_APPROLE_UNWRAP_SECRETID_TOKEN_CREATION_PATH -ne $Lookup_CreationPath) {\n                throw \"Supplied Wrapped token creation path failed lookup validation. Check the creation path value and retry.\"\n            }\n        }\n        else {\n            Write-Error \"Null or Empty response returned from Vault server lookup\" -Category InvalidResult\n        }\n    }\n\n    # Call to unwrap secret id from wrapped token.\n    $Headers = @{\n        \"X-Vault-Token\" = $VAULT_APPROLE_UNWRAP_SECRETID_TOKEN\n    }\n\n    if (-not [string]::IsNullOrWhiteSpace($VAULT_APPROLE_UNWRAP_SECRETID_NAMESPACE)) {\n        $Headers.Add(\"X-Vault-Namespace\", $VAULT_APPROLE_UNWRAP_SECRETID_NAMESPACE)\n    }\n    \n    $uri = \"$VAULT_APPROLE_UNWRAP_SECRETID_ADDRESS/$VAULT_APPROLE_UNWRAP_SECRETID_API_VERSION/sys/wrapping/unwrap\"\n    Write-Verbose \"Making Post request to $uri\"\n    $response = Invoke-RestMethod -Uri $uri -Headers $Headers -Method Post\n    \n    if ($null -ne $response) {\n        Set-OctopusVariable -Name \"UnwrappedSecretID\" -Value $response.data.secret_id -Sensitive\n        Write-Host \"Created output variable: ##{Octopus.Action[$StepName].Output.UnwrappedSecretID}\"\n    }\n    else {\n        Write-Error \"Null or Empty response returned from Vault server unwrap\" -Category InvalidResult\n    }\n}\ncatch {\n    $ExceptionMessage = $_.Exception.Message\n    $ErrorBody = Get-WebRequestErrorBody -RequestError $_\n    $Message = \"An error occurred unwrapping secretid: $ExceptionMessage\"\n    $AdditionalDetail = \"\"\n    if (![string]::IsNullOrWhiteSpace($ErrorBody)) {\n        if ($null -ne $ErrorBody.errors) {\n            $AdditionalDetail = $ErrorBody.errors -Join \",\"   \n        }\n        else {\n            $errorDetails = $null\n            try { $errorDetails = ConvertFrom-Json $ErrorBody } catch {}\n            $AdditionalDetail += if ($null -ne $errorDetails) { $errorDetails.errors -Join \",\" } else { $ErrorBody } \n        }\n    }\n    \n    if (![string]::IsNullOrWhiteSpace($AdditionalDetail)) {\n        $Message += \"`n`tDetail: $AdditionalDetail\"\n    }\n\n    Write-Error $Message -Category ConnectionError\n}"
  },
  "Category": "HashiCorp Vault",
  "HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates//opt/buildagent/work/75443764cd38076d/step-templates/hashicorp-vault-approle-unwrap-secretid.json",
  "Website": "/step-templates/c1f56030-0bcd-458d-bc70-b4f43ec0d30f",
  "Logo": "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",
  "$Meta": {
    "Type": "ActionTemplate"
  }
}

History

Page updated on Sunday, September 18, 2022