Octopus.Script exported 2022-09-16 by harrisonmeister belongs to ‘HashiCorp Vault’ category.
This step logs into a HashiCorp Vault server with the AppRole auth method.
The client_token
from the response will be made available as a sensitive Output variable named AppRoleAuthToken
for use in other step templates.
This step template makes use of the Rest API, so no other dependencies are needed.
Required:
- The Vault server must be unsealed.
- You must supply the full path where the AppRole auth method is mounted.
- You must supply both a
RoleId
andSecretId
.
Optional:
- A Vault namespace to use. Nested namespaces can also be supplied, e.g.
ns1/ns2
. Note: This field is only supported on Vault Enterprise .
Notes:
- Tested on Vault Server
1.11.3
. - Tested on both PowerShell Desktop and PowerShell Core.
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.Login.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.Login.ApiVersion = v1
All API routes are prefixed with a version e.g. /v1/
.
See the API documentation for further details.
Namespace (Optional)
Vault.AppRole.Login.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 .
App Role Path
Vault.AppRole.Login.AppRolePath = /auth/approle
The path where the approle auth method was mounted. The default path is /auth/approle
. If the AppRole auth method was mounted at a different path, for example my-path
, then specify /my-path
instead.
Script body
Steps based on this template will execute the following PowerShell script.
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
# Variables
$VAULT_APPROLE_LOGIN_ADDRESS = $OctopusParameters["Vault.AppRole.Login.VaultAddress"]
$VAULT_APPROLE_LOGIN_API_VERSION = $OctopusParameters["Vault.AppRole.Login.ApiVersion"]
$VAULT_APPROLE_LOGIN_APPROLE_PATH = $OctopusParameters["Vault.AppRole.Login.AppRolePath"]
$VAULT_APPROLE_LOGIN_ROLEID = $OctopusParameters["Vault.AppRole.Login.RoleID"]
$VAULT_APPROLE_LOGIN_SECRETID = $OctopusParameters["Vault.AppRole.Login.SecretID"]
# Optional variables
$VAULT_APPROLE_LOGIN_NAMESPACE = $OctopusParameters["Vault.AppRole.Login.Namespace"]
# Validation
if ([string]::IsNullOrWhiteSpace($VAULT_APPROLE_LOGIN_ADDRESS)) {
throw "Required parameter VAULT_APPROLE_LOGIN_ADDRESS not specified"
}
if ([string]::IsNullOrWhiteSpace($VAULT_APPROLE_LOGIN_API_VERSION)) {
throw "Required parameter VAULT_APPROLE_LOGIN_API_VERSION not specified"
}
if ([string]::IsNullOrWhiteSpace($VAULT_APPROLE_LOGIN_APPROLE_PATH)) {
throw "Required parameter VAULT_APPROLE_LOGIN_APPROLE_PATH not specified"
}
if ([string]::IsNullOrWhiteSpace($VAULT_APPROLE_LOGIN_ROLEID)) {
throw "Required parameter VAULT_APPROLE_LOGIN_ROLEID not specified"
}
if ([string]::IsNullOrWhiteSpace($VAULT_APPROLE_LOGIN_SECRETID)) {
throw "Required parameter VAULT_APPROLE_LOGIN_SECRETID 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_LOGIN_ADDRESS = $VAULT_APPROLE_LOGIN_ADDRESS.TrimEnd('/')
$VAULT_APPROLE_LOGIN_APPROLE_PATH = $VAULT_APPROLE_LOGIN_APPROLE_PATH.TrimStart('/').TrimEnd('/')
# Local variables
$StepName = $OctopusParameters["Octopus.Step.Name"]
try {
$payload = @{
role_id = $VAULT_APPROLE_LOGIN_ROLEID
secret_id = $VAULT_APPROLE_LOGIN_SECRETID
}
$Headers = @{}
if (-not [string]::IsNullOrWhiteSpace($VAULT_APPROLE_LOGIN_NAMESPACE)) {
Write-Verbose "Setting 'X-Vault-Namespace' header to: $VAULT_APPROLE_LOGIN_NAMESPACE"
$Headers.Add("X-Vault-Namespace", $VAULT_APPROLE_LOGIN_NAMESPACE)
}
$uri = "$VAULT_APPROLE_LOGIN_ADDRESS/$VAULT_APPROLE_LOGIN_API_VERSION/$([uri]::EscapeDataString($VAULT_APPROLE_LOGIN_APPROLE_PATH))/login"
Write-Verbose "Making request to $uri"
$response = Invoke-RestMethod -Method Post -Uri $uri -Body ($payload | ConvertTo-Json -Depth 10) -Headers $Headers
if ($null -ne $response) {
Set-OctopusVariable -Name "AppRoleAuthToken" -Value $response.auth.client_token -Sensitive
Write-Host "Created output variable: ##{Octopus.Action[$StepName].Output.AppRoleAuthToken}"
}
else {
Write-Error "Null or Empty response returned from Vault server" -Category InvalidResult
}
}
catch {
$ExceptionMessage = $_.Exception.Message
$ErrorBody = Get-WebRequestErrorBody -RequestError $_
$Message = "An error occurred logging in with AppRole: $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.
To use this template in Octopus Deploy, copy the JSON below and paste it into the Library → Step templates → Import dialog.
{
"Id": "e04a9cec-f04a-4da2-849b-1aed0fd408f0",
"Name": "HashiCorp Vault - AppRole Login",
"Description": "This step logs into a HashiCorp Vault server with the [AppRole](https://www.vaultproject.io/docs/auth/approle) auth method.\n\nThe `client_token` from the response will be made available as a sensitive [Output variable](https://octopus.com/docs/projects/variables/output-variables#sensitive-output-variables) named `AppRoleAuthToken` for use in other step templates.\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**Required:** \n- The Vault server must be [unsealed](https://www.vaultproject.io/docs/concepts/seal).\n- You must supply the full path where the AppRole auth method is mounted.\n- You must supply both a `RoleId` and `SecretId`.\n\n*Optional*:\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\nNotes:\n\n- Tested on Vault Server `1.11.3`.\n- Tested on both PowerShell Desktop and PowerShell Core.\n",
"Version": 8,
"ExportedAt": "2022-09-16T19:37:08.177Z",
"ActionType": "Octopus.Script",
"Author": "harrisonmeister",
"Packages": [],
"Parameters": [
{
"Id": "bbf1cf96-066a-43e8-8387-24131fa63feb",
"Name": "Vault.AppRole.Login.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": "bd6ca2f2-2102-40e0-a1e0-36e526393203",
"Name": "Vault.AppRole.Login.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": "49dc9994-778b-40ad-afe5-80ed34e45056",
"Name": "Vault.AppRole.Login.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": "67c5d1c7-6373-4342-b02b-a7a6fa69402b",
"Name": "Vault.AppRole.Login.AppRolePath",
"Label": "App Role Path",
"HelpText": "The path where the approle auth method was mounted. The default path is `/auth/approle`. If the AppRole auth method was mounted at a different path, for example `my-path`, then specify `/my-path` instead.",
"DefaultValue": "/auth/approle",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "297871f1-a145-4dde-97ba-d7a9a0690cc6",
"Name": "Vault.AppRole.Login.RoleID",
"Label": "Role ID",
"HelpText": "The [RoleID](https://www.vaultproject.io/docs/auth/approle#roleid) of the AppRole.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "Sensitive"
}
},
{
"Id": "4c8ab1b0-36e3-4d19-9a45-557300bb0f06",
"Name": "Vault.AppRole.Login.SecretID",
"Label": "Secret ID",
"HelpText": "The [Secret ID](https://www.vaultproject.io/docs/auth/approle#secretid) of the AppRole.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "Sensitive"
}
}
],
"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_LOGIN_ADDRESS = $OctopusParameters[\"Vault.AppRole.Login.VaultAddress\"]\n$VAULT_APPROLE_LOGIN_API_VERSION = $OctopusParameters[\"Vault.AppRole.Login.ApiVersion\"]\n$VAULT_APPROLE_LOGIN_APPROLE_PATH = $OctopusParameters[\"Vault.AppRole.Login.AppRolePath\"]\n$VAULT_APPROLE_LOGIN_ROLEID = $OctopusParameters[\"Vault.AppRole.Login.RoleID\"]\n$VAULT_APPROLE_LOGIN_SECRETID = $OctopusParameters[\"Vault.AppRole.Login.SecretID\"]\n\n# Optional variables\n$VAULT_APPROLE_LOGIN_NAMESPACE = $OctopusParameters[\"Vault.AppRole.Login.Namespace\"]\n\n# Validation\nif ([string]::IsNullOrWhiteSpace($VAULT_APPROLE_LOGIN_ADDRESS)) {\n throw \"Required parameter VAULT_APPROLE_LOGIN_ADDRESS not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($VAULT_APPROLE_LOGIN_API_VERSION)) {\n throw \"Required parameter VAULT_APPROLE_LOGIN_API_VERSION not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($VAULT_APPROLE_LOGIN_APPROLE_PATH)) {\n throw \"Required parameter VAULT_APPROLE_LOGIN_APPROLE_PATH not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($VAULT_APPROLE_LOGIN_ROLEID)) {\n throw \"Required parameter VAULT_APPROLE_LOGIN_ROLEID not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($VAULT_APPROLE_LOGIN_SECRETID)) {\n throw \"Required parameter VAULT_APPROLE_LOGIN_SECRETID 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_LOGIN_ADDRESS = $VAULT_APPROLE_LOGIN_ADDRESS.TrimEnd('/')\n$VAULT_APPROLE_LOGIN_APPROLE_PATH = $VAULT_APPROLE_LOGIN_APPROLE_PATH.TrimStart('/').TrimEnd('/')\n\n# Local variables\n$StepName = $OctopusParameters[\"Octopus.Step.Name\"]\n\ntry {\n $payload = @{\n role_id = $VAULT_APPROLE_LOGIN_ROLEID\n secret_id = $VAULT_APPROLE_LOGIN_SECRETID\n }\n\n $Headers = @{}\n if (-not [string]::IsNullOrWhiteSpace($VAULT_APPROLE_LOGIN_NAMESPACE)) {\n Write-Verbose \"Setting 'X-Vault-Namespace' header to: $VAULT_APPROLE_LOGIN_NAMESPACE\"\n $Headers.Add(\"X-Vault-Namespace\", $VAULT_APPROLE_LOGIN_NAMESPACE)\n }\n\n $uri = \"$VAULT_APPROLE_LOGIN_ADDRESS/$VAULT_APPROLE_LOGIN_API_VERSION/$([uri]::EscapeDataString($VAULT_APPROLE_LOGIN_APPROLE_PATH))/login\"\n Write-Verbose \"Making request to $uri\"\n $response = Invoke-RestMethod -Method Post -Uri $uri -Body ($payload | ConvertTo-Json -Depth 10) -Headers $Headers\n \n if ($null -ne $response) {\n Set-OctopusVariable -Name \"AppRoleAuthToken\" -Value $response.auth.client_token -Sensitive\n Write-Host \"Created output variable: ##{Octopus.Action[$StepName].Output.AppRoleAuthToken}\"\n }\n else {\n Write-Error \"Null or Empty response returned from Vault server\" -Category InvalidResult\n }\n}\ncatch {\n $ExceptionMessage = $_.Exception.Message\n $ErrorBody = Get-WebRequestErrorBody -RequestError $_\n $Message = \"An error occurred logging in with AppRole: $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-login.json",
"Website": "/step-templates/e04a9cec-f04a-4da2-849b-1aed0fd408f0",
"Logo": "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",
"$Meta": {
"Type": "ActionTemplate"
}
}
Page updated on Friday, September 16, 2022