Octopus.Script exported 2021-08-23 by benjimac93 belongs to ‘Venafi’ category.
This step template will authenticate against a Venafi TPP instance using an existing OAuth access token, export a certificate by its Distinguished Name (DN), and then import the certificate into the Octopus certificate store.
The export is achieved using the VenafiPS PowerShell module’s Export-VenafiCertificate function.
Export options:
- Provide the distinguished name (DN) path to the certificate.
- Choose from the following export formats:
Base64
Base64 (PKCS #8)
DER
PKCS #12
- Optional - Include the full certificate chain in the export.
- Optional - Friendly name (Label or alias) to use. Permitted with
Base64
andPKCS #12
formats. - Optional - Include the private key in the export. Not supported with
DER
format. - Optional - Provide a password to be used for the exported private key.
- Optional - Also store the export certificate response in
JSON
format in an Octopus sensitive output variable. This output variable can then be used in additional deployment or runbook steps. - Optional - on successful completion, you can revoke the access token used.
Octopus Import options:
- Octopus URL
- Octopus API Key
- Octopus Space name
- Certificate name
- Optional - replace the existing certificate if it already exists
Required:
- The
VenafiPS
PowerShell module installed on the deployment target or worker. If the module can’t be found, the step will attempt to download a version from the PowerShell gallery. - PowerShell
5
or greater. - Octopus API key with permission to save the certificate.
Notes:
- Tested on Octopus
2021.2
. - Tested with VenafiPS
3.1.5
. - Tested with both Windows PowerShell and PowerShell Core on Linux.
Parameters
When steps based on the template are included in a project’s deployment process, the parameters below can be set.
Venafi TPP Server
Venafi.TPP.ImportCert.Server =
Required: The URL of the Venafi TPP instance you want to export the certificate from.
For example: https://mytppserver.example.com
.
Venafi TPP Access Token
Venafi.TPP.ImportCert.AccessToken =
Required: The access token to authenticate against the TPP instance.
Venafi TPP Certificate Path
Venafi.TPP.ImportCert.DNPath =
Required: The Distinguished Name (DN) of the certificate you wish to export. This is the absolute path to the certificate in the TPP instance, separated by \
.
Certificate Export Format
Venafi.TPP.ImportCert.Format =
Required: The certificate export format. Valid options are:
Base64
Base64 (PKCS #8)
DER
PKCS #12
Include certificate chain (Optional)
Venafi.TPP.ImportCert.IncludeChain = False
Optional: Include the certificate chain with the exported certificate. Not supported with DER
format. Default: False
.
Friendly Name (Optional)
Venafi.TPP.ImportCert.FriendlyName =
Optional: Label or alias to use. Permitted with Base64
and PKCS #12
formats.
Include Private Key (Optional)
Venafi.TPP.ImportCert.IncludePrivateKey = False
Optional: Include the private key in the certificate export. If this is selected, the Venafi.TPP.Export.PrivateKeyPassword
must also be provided. Default: False
.
Private Key password (Optional)
Venafi.TPP.ImportCert.PrivateKeyPassword =
Optional: The password required to include the private key. Not supported with DER
format. You must adhere to the following rules:
- Password is at least 12 characters.
- Comprised of at least three of the following:
- Uppercase alphabetic letters
- Lowercase alphabetic letters
- Numeric characters
- Special characters
Certificate output variable name (Optional)
Venafi.TPP.ImportCert.OutputVariableName =
Optional: Create an output variable with the certificate details returned from the export call. The certificate details will be stored in JSON
format.
Revoke access token on completion?
Venafi.TPP.ImportCert.RevokeTokenOnCompletion = False
Optional: Should the access token used be revoked once the step has been completed successfully? Default: False
.
Octopus Server Url
Venafi.TPP.ImportCert.OctopusServerUri =
Required: Provide the base URL of your Octopus Server. There are two built-in Octopus variables you can use:
#{if Octopus.Web.ServerUri}#{Octopus.Web.ServerUri}#{else}#{Octopus.Web.BaseUrl}#{/if}
Octopus.Web.ServerUri
See our system variables page for further details.
Octopus API Key
Venafi.TPP.ImportCert.OctopusApiKey =
Required: Provide an Octopus API Key with appropriate permissions to save the certificate.
Octopus Space Name
Venafi.TPP.ImportCert.OctopusSpaceName = #{Octopus.Space.Name}
Required: Provide the Space name for the certificate to be saved in. The default is the current space the step is running within: #{Octopus.Space.Name}
.
Octopus Certificate Name
Venafi.TPP.ImportCert.OctopusCertificateName =
Required: A short, memorable, unique name for the imported certificate.
Replace existing Octopus certificate?
Venafi.TPP.ImportCert.OctopusReplaceExistingCertificate = True
Optional: If a certificate exists in Octopus with the same name as the one to be imported, should the one stored in Octopus be replaced? Default: True
.
Note: If multiple matches are found, the step template will not replace any, and will log a warning instead.
See replacing certificates for further information.
Script body
Steps based on this template will execute the following PowerShell script.
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$ErrorActionPreference = 'Stop'
# TPP required variables
$Server = $OctopusParameters["Venafi.TPP.ImportCert.Server"]
$Token = $OctopusParameters["Venafi.TPP.ImportCert.AccessToken"]
$Path = $OctopusParameters["Venafi.TPP.ImportCert.DNPath"]
$Format = $OctopusParameters["Venafi.TPP.ImportCert.Format"]
# TPP optional variables
$IncludeChain = $OctopusParameters["Venafi.TPP.ImportCert.IncludeChain"]
$FriendlyName = $OctopusParameters["Venafi.TPP.ImportCert.FriendlyName"]
$IncludePrivateKey = $OctopusParameters["Venafi.TPP.ImportCert.IncludePrivateKey"]
$PrivateKeyPassword = $OctopusParameters["Venafi.TPP.ImportCert.PrivateKeyPassword"]
$OutputVariableName = $OctopusParameters["Venafi.TPP.ImportCert.OutputVariableName"]
$RevokeToken = $OctopusParameters["Venafi.TPP.ImportCert.RevokeTokenOnCompletion"]
# Octopus required variables
$OctopusServerUri = $OctopusParameters["Venafi.TPP.ImportCert.OctopusServerUri"]
$OctopusApiKey = $OctopusParameters["Venafi.TPP.ImportCert.OctopusApiKey"]
$OctopusSpaceName = $OctopusParameters["Venafi.TPP.ImportCert.OctopusSpaceName"]
$OctopusCertificateName = $OctopusParameters["Venafi.TPP.ImportCert.OctopusCertificateName"]
$OctopusReplaceExistingCertificate = $OctopusParameters["Venafi.TPP.ImportCert.OctopusReplaceExistingCertificate"]
# TPP validation
if ([string]::IsNullOrWhiteSpace($Server)) {
throw "Required parameter Venafi.TPP.ImportCert.Server not specified"
}
if ([string]::IsNullOrWhiteSpace($Token)) {
throw "Required parameter Venafi.TPP.ImportCert.AccessToken not specified"
}
if ([string]::IsNullOrWhiteSpace($Path)) {
throw "Required parameter Venafi.TPP.ImportCert.DNPath not specified"
}
else {
if ($Path.Contains("\") -eq $False) {
throw "At least one '\' is required for the Venafi.TPP.ImportCert.DNPath value"
}
}
if ([string]::IsNullOrWhiteSpace($Format)) {
throw "Required parameter Venafi.TPP.ImportCert.Format not specified"
}
# TPP conditional validation
if ($IncludePrivateKey -eq $True) {
if ([string]::IsNullOrWhiteSpace($PrivateKeyPassword)) {
throw "IncludePrivateKey set to true, but parameter Venafi.TPP.ImportCert.PrivateKeyPassword not specified"
}
}
else {
$PrivateKeyPassword = $null
}
# Octopus validation
if ([string]::IsNullOrWhiteSpace($OctopusServerUri)) {
throw "Required parameter Venafi.TPP.ImportCert.OctopusServerUri not specified"
}
if ([string]::IsNullOrWhiteSpace($OctopusApiKey)) {
throw "Required parameter Venafi.TPP.ImportCert.OctopusApiKey not specified"
}
if ([string]::IsNullOrWhiteSpace($OctopusSpaceName)) {
throw "Required parameter Venafi.TPP.ImportCert.OctopusSpaceName not specified"
}
if ([string]::IsNullOrWhiteSpace($OctopusCertificateName)) {
throw "Required parameter Venafi.TPP.ImportCert.OctopusCertificateName not specified"
}
if ([string]::IsNullOrWhiteSpace($OctopusReplaceExistingCertificate)) {
throw "Required parameter Venafi.TPP.ImportCert.OctopusReplaceExistingCertificate 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
}
}
function Get-MatchingOctopusCertificates {
param (
[string]$ServerUri,
[string]$ApiKey,
[string]$SpaceId,
[string]$CertificateName
)
Write-Debug "Entering: Get-MatchingOctopusCertificates"
try {
$header = @{ "X-Octopus-ApiKey" = $ApiKey }
# Get a list of certificates that match our domain search criteria.
$partial_certificates = (Invoke-RestMethod -Uri "$ServerUri/api/$SpaceId/certificates?partialName=$([uri]::EscapeDataString($CertificateName))&skip=0&take=2000" -Headers $header) | Select-Object -ExpandProperty Items
# return certs that arent archived and havent been replaced.
return $partial_certificates | Where-Object {
$null -eq $_.ReplacedBy -and
$null -eq $_.Archived -and
$CertificateName -eq $_.Name
}
}
catch {
$Detail = (Get-WebRequestErrorBody -RequestError $_)
Write-Error "Could not retrieve certificates from Octopus. Error: $($_.Exception.Message).`n`t$Detail"
}
}
function Replace-OctopusCertificate {
param (
[string]$ServerUri,
[string]$ApiKey,
[string]$SpaceId,
[string]$CertificateId,
[string]$CertificateName,
[string]$CertificateData,
[string]$CertificatePwd
)
Write-Debug "Entering: Replace-OctopusCertificate"
try {
$header = @{ "X-Octopus-ApiKey" = $ApiKey }
$replacement_certificate = @{
CertificateData = $CertificateData
}
if (![string]::IsNullOrWhiteSpace($CertificatePwd)) {
$replacement_certificate.Password = $CertificatePwd
}
# Replace the cert
$updated_certificate = Invoke-RestMethod -Method Post -Uri "$ServerUri/api/$SpaceId/certificates/$CertificateId/replace" -Headers $header -Body ($replacement_certificate | ConvertTo-Json -Depth 10)
Write-Highlight "Replaced certificate in Octopus for '$($updated_certificate.Name)' ($($updated_certificate.Id))"
}
catch {
$Detail = (Get-WebRequestErrorBody -RequestError $_)
Write-Error "Could not replace certificate in Octopus. Error: $($_.Exception.Message).`n`t$Detail"
}
}
function New-OctopusCertificate {
param (
[string]$ServerUri,
[string]$ApiKey,
[string]$SpaceId,
[string]$CertificateName,
[string]$CertificateData,
[string]$CertificatePwd
)
Write-Debug "Entering: New-OctopusCertificate"
try {
$header = @{ "X-Octopus-ApiKey" = $ApiKey }
$certificate = @{
Name = $CertificateName;
CertificateData = @{
NewValue = $CertificateData;
HasData = $True;
}
Password = @{
HasValue = $False;
NewValue = $null;
}
}
if (![string]::IsNullOrWhiteSpace($CertificatePwd)) {
$certificate.Password.NewValue = $CertificatePwd
$certificate.Password.HasData = $True
}
# Create new certificate
$new_certificate = Invoke-RestMethod -Method Post -Uri "$ServerUri/api/$SpaceId/certificates" -Headers $header -Body ($certificate | ConvertTo-Json -Depth 10)
Write-Highlight "New certificate created in Octopus for '$($new_certificate.Name)' ($($new_certificate.Id))"
}
catch {
$Detail = (Get-WebRequestErrorBody -RequestError $_)
Write-Error "Could not create new certificate in Octopus. Error: $($_.Exception.Message).`n`t$Detail"
}
}
function Clean-VenafiCertificateForOctopus {
param (
[string]$CertificateData
)
Write-Debug "Entering: Clean-VenafiCertificateForOctopus"
$PemHeaderFragment = "-----BEGIN *"
$PemFooterFragment = "-----END *"
$CertificateBytes = [Convert]::FromBase64String($CertificateData)
$RawCert = [System.Text.Encoding]::UTF8.GetString($CertificateBytes)
$CleanedCertLines = @()
if (![string]::IsNullOrWhiteSpace($RawCert)) {
$RawCertLines = ($RawCert -Split "`n")
$currentLine = 0
while ($currentLine -lt $RawCertLines.Length) {
Write-Verbose "Working on line $currentLine"
$headerPosition = [Array]::FindIndex($RawCertLines, $currentLine, [Predicate[string]] { $args[0] -like $PemHeaderFragment })
if ($headerPosition -gt -1) {
$footerPosition = [Array]::FindIndex($RawCertLines, $headerPosition, [Predicate[string]] { $args[0] -like $PemFooterFragment })
if ($footerPosition -lt 0) {
throw "Unable to find a matching '-----END' PEM fragment!"
}
else {
Write-Verbose "Selecting PEM lines: $headerPosition-$footerPosition"
$pemLines = $RawCertLines[$headerPosition..$footerPosition]
$CleanedCertLines += $pemLines
$currentLine = $footerPosition
}
}
else {
$currentLine++
}
}
}
if ($CleanedCertLines.Length -le 0) {
throw "Something went wrong extracting contents from file (no cleansed contents)"
}
$CleanedCert = $CleanedCertLines | Out-String
$CleanedCertData = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($CleanedCert))
return $CleanedCertData
}
###############################################################################
# MAIN STEP TEMPLATE FLOW
###############################################################################
# TPP Access token
$SecureToken = ConvertTo-SecureString $Token -AsPlainText -Force
[PSCredential]$AccessToken = New-Object System.Management.Automation.PsCredential("token", $SecureToken)
# Clean-up
$Server = $Server.TrimEnd('/')
$OctopusServerUri = $OctopusServerUri.TrimEnd('/')
$OctopusSpaceName = $OctopusSpaceName.Trim(" ")
$OctopusCertificateName = $OctopusCertificateName.Trim(" ")
# Required Venafi Module
function Get-NugetPackageProviderNotInstalled {
# See if the nuget package provider has been installed
return ($null -eq (Get-PackageProvider -ListAvailable -Name Nuget -ErrorAction SilentlyContinue))
}
# Check to see if the package provider has been installed
if ((Get-NugetPackageProviderNotInstalled) -ne $false) {
Write-Host "Nuget package provider not found, installing ..."
Install-PackageProvider -Name Nuget -Force -Scope CurrentUser
}
Write-Host "Checking for required VenafiPS module ..."
$required_venafips_version = 3.1.5
$module_available = Get-Module -ListAvailable -Name VenafiPS | Where-Object { $_.Version -ge $required_venafips_version }
if (-not ($module_available)) {
Write-Host "Installing VenafiPS module ..."
Install-Module -Name VenafiPS -MinimumVersion 3.1.5 -Scope CurrentUser -Force
}
else {
$first_match = $module_available | Select-Object -First 1
Write-Host "Found version: $($first_match.Version)"
}
Write-Host "Importing VenafiPS module ..."
Import-Module VenafiPS
$StepName = $OctopusParameters["Octopus.Step.Name"]
$ExportFormatsIncompatibleWithOctopusCertificateStore = @("Base64", "Base64 (PKCS #8)")
Write-Verbose "Venafi.TPP.ImportCert.Server: $Server"
Write-Verbose "Venafi.TPP.ImportCert.AccessToken: ********"
Write-Verbose "Venafi.TPP.ImportCert.DNPath: $Path"
Write-Verbose "Venafi.TPP.ImportCert.Format: $Format"
Write-Verbose "Venafi.TPP.ImportCert.IncludeChain: $IncludeChain"
Write-Verbose "Venafi.TPP.ImportCert.FriendlyName: $FriendlyName"
Write-Verbose "Venafi.TPP.ImportCert.IncludePrivateKey: $IncludePrivateKey"
Write-Verbose "Venafi.TPP.ImportCert.PrivateKeyPassword: ********"
Write-Verbose "Venafi.TPP.ImportCert.CertDetails.OutputVariableName: $OutputVariableName"
Write-Verbose "Venafi.TPP.ImportCert.RevokeTokenOnCompletion: $RevokeTokenOnCompletion"
Write-Verbose "Venafi.TPP.ImportCert.OctopusServerUri: $OctopusServerUri"
Write-Verbose "Venafi.TPP.ImportCert.OctopusApiKey: ********"
Write-Verbose "Venafi.TPP.ImportCert.OctopusSpaceName: $OctopusSpaceName"
Write-Verbose "Venafi.TPP.ImportCert.OctopusCertificateName: $OctopusCertificateName"
Write-Verbose "Venafi.TPP.ImportCert.OctopusReplaceExistingCertificate: $OctopusReplaceExistingCertificate"
Write-Verbose "Step Name: $StepName"
Write-Host "Requesting new session from $Server"
New-VenafiSession -Server $Server -AccessToken $AccessToken
# Export certificate
$ExportCert_Params = @{
CertificateId = $Path;
Format = $Format;
}
# Optional IncludeChain field
if ($IncludeChain -eq $True) {
$ExportCert_Params.IncludeChain = $True
}
# Optional FriendlyName field
if (-not [string]::IsNullOrWhiteSpace($FriendlyName)) {
$ExportCert_Params.FriendlyName = $FriendlyName
}
# Optional Private key field
if (-not [string]::IsNullOrWhiteSpace($PrivateKeyPassword) -and $IncludePrivateKey -eq $True) {
$SecurePrivateKeyPassword = ConvertTo-SecureString $PrivateKeyPassword -AsPlainText -Force
$ExportCert_Params.PrivateKeyPassword = $SecurePrivateKeyPassword
$ExportCert_Params.IncludePrivateKey = $True
}
# Do the export
$ExportCertificateResponse = ((Export-VenafiCertificate @ExportCert_Params) 6> $null)
if ($null -eq $ExportCertificateResponse -or $null -eq $ExportCertificateResponse.CertificateData) {
Write-Warning "No certificate data returned for path: $Path`nCheck the path value represents a certificate, and not a folder."
}
else {
Write-Host "Successfully retrieved certificate data to export for path: $Path"
# Get octopus space Id
$header = @{ "X-Octopus-ApiKey" = $OctopusApiKey }
$spaces = Invoke-RestMethod -Uri "$OctopusServerUri/api/spaces?partialName=$([uri]::EscapeDataString($OctopusSpaceName))&skip=0&take=500" -Headers $header
$OctopusSpace = @($spaces.Items | Where-Object { $_.Name -eq $OctopusSpaceName }) | Select-Object -First 1
if ($null -eq $OctopusSpace) {
throw "Couldnt find Octopus space with name '$OctopusSpaceName'."
}
# Check for certificate based on name
$CertificateMatches = @(Get-MatchingOctopusCertificates -ServerUri $OctopusServerUri -ApiKey $OctopusApiKey -SpaceId $($OctopusSpace.Id) -CertificateName $OctopusCertificateName)
Write-Host "Found $($CertificateMatches.Length) certificates matching '$OctopusCertificateName'"
$FirstCertificateMatch = $CertificateMatches | Select-Object -First 1
$CertificateData = $ExportCertificateResponse.CertificateData
if ($ExportFormatsIncompatibleWithOctopusCertificateStore -icontains $Format) {
Write-Host "Requested export format $Format needs to be cleaned before import to Octopus."
$CertificateData = Clean-VenafiCertificateForOctopus -CertificateData $CertificateData
if ([string]::IsNullOrWhiteSpace($CertificateData)) {
throw "Cleaned certificate data empty!"
}
}
switch ($CertificateMatches.Length) {
0 {
# New cert
Write-Host "Creating a new certificate '$OctopusCertificateName'"
New-OctopusCertificate -ServerUri $OctopusServerUri -ApiKey $OctopusApiKey -SpaceId $($OctopusSpace.Id) -CertificateName $OctopusCertificateName -CertificateData $($CertificateData) -CertificatePwd $PrivateKeyPassword
}
1 {
# One cert to replace
if ($OctopusReplaceExistingCertificate -eq $False) {
Write-Host "Replace existing certificate set to False, nothing to do."
}
else {
Write-Host "Replacing existing certificate '$OctopusCertificateName' ($($FirstCertificateMatch.Id))"
Replace-OctopusCertificate -ServerUri $OctopusServerUri -ApiKey $OctopusApiKey -SpaceId $($OctopusSpace.Id) -CertificateId $($FirstCertificateMatch.Id) -CertificateName $OctopusCertificateName -CertificateData $($CertificateData) -CertificatePwd $PrivateKeyPassword
}
}
default {
Write-Warning "Multiple certs matching name '$OctopusCertificateName' found, nothing to do."
return
}
}
if ([string]::IsNullOrWhiteSpace($OutputVariableName) -eq $False) {
$CertificateJson = $ExportCertificateResponse | ConvertTo-Json -Compress -Depth 10
Set-OctopusVariable -Name $OutputVariableName -Value $CertificateJson -Sensitive
Write-Highlight "Created sensitive output variable: ##{Octopus.Action[$StepName].Output.$OutputVariableName}"
}
}
if ($RevokeToken -eq $true) {
# Revoke TPP access token
Write-Host "Revoking access token with $Server"
Revoke-TppToken -AuthServer $Server -AccessToken $AccessToken -Force
}
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": "e10820c2-ae6d-4030-8a8a-b73ed60a81fc",
"Name": "Venafi TPP - Import Certificate into Octopus",
"Description": "This step template will authenticate against a Venafi TPP instance using an existing OAuth access token, export a certificate by its Distinguished Name (DN), and then import the certificate into the Octopus certificate store.\n\nThe export is achieved using the VenafiPS PowerShell module's [Export-VenafiCertificate](https://venafips.readthedocs.io/en/latest/functions/Export-VenafiCertificate/) function.\n\n---\n\n**Export options:**\n\n- Provide the distinguished name (DN) path to the certificate.\n- Choose from the following export formats:\n - `Base64`\n - `Base64 (PKCS #8)`\n - `DER`\n - `PKCS #12` \n- *Optional* - Include the full certificate chain in the export.\n- *Optional* - Friendly name (Label or alias) to use. Permitted with `Base64` and `PKCS #12` formats. \n- *Optional* - Include the private key in the export. Not supported with `DER` format.\n- *Optional* - Provide a password to be used for the exported private key.\n- *Optional* - Also store the export certificate response in `JSON` format in an [Octopus sensitive output variable](https://octopus.com/docs/projects/variables/output-variables#sensitive-output-variables). This output variable can then be used in additional deployment or runbook steps.\n- *Optional* - on successful completion, you can revoke the access token used.\n\n---\n\n**Octopus Import options:**\n\n- Octopus URL\n- Octopus API Key\n- Octopus Space name\n- Certificate name\n- *Optional* - replace the existing certificate if it already exists\n\n---\n\n**Required:** \n- The `VenafiPS` PowerShell module installed on the deployment target or worker. If the module can't be found, the step will attempt to download a version from the [PowerShell gallery](https://www.powershellgallery.com/packages/VenafiPS).\n- PowerShell `5` or greater.\n- Octopus API key with permission to save the certificate.\n\nNotes:\n\n- Tested on Octopus `2021.2`.\n- Tested with VenafiPS `3.1.5`.\n- Tested with both Windows PowerShell and PowerShell Core on Linux.",
"Version": 2,
"ExportedAt": "2021-08-23T12:40:10.975Z",
"ActionType": "Octopus.Script",
"Author": "benjimac93",
"Packages": [],
"Parameters": [
{
"Id": "56ef4967-37f5-40a0-a66e-f3fa589b6467",
"Name": "Venafi.TPP.ImportCert.Server",
"Label": "Venafi TPP Server",
"HelpText": "*Required*: The URL of the Venafi TPP instance you want to export the certificate from.\n\nFor example: `https://mytppserver.example.com`.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "49bcdbbb-3674-4901-8bf6-164e5e4bc395",
"Name": "Venafi.TPP.ImportCert.AccessToken",
"Label": "Venafi TPP Access Token",
"HelpText": "*Required*: The access token to authenticate against the TPP instance.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "Sensitive"
}
},
{
"Id": "e3156852-4ba9-4dc0-8d39-5a93c52b1910",
"Name": "Venafi.TPP.ImportCert.DNPath",
"Label": "Venafi TPP Certificate Path",
"HelpText": "*Required*: The Distinguished Name (DN) of the certificate you wish to export. This is the absolute path to the certificate in the TPP instance, separated by `\\`.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "4f9f4d4b-d686-4d00-aa93-af35b7df320b",
"Name": "Venafi.TPP.ImportCert.Format",
"Label": "Certificate Export Format",
"HelpText": "*Required*: The certificate export format. Valid options are:\n\n- `Base64`\n- `Base64 (PKCS #8)`\n- `DER`\n- `PKCS #12`",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "Select",
"Octopus.SelectOptions": "Base64|Base64\nBase64 (PKCS #8)|Base64 (PKCS #8)\nDER|DER\nPKCS #12|PKCS #12"
}
},
{
"Id": "309d30de-79b6-4461-8a54-1698aedd5822",
"Name": "Venafi.TPP.ImportCert.IncludeChain",
"Label": "Include certificate chain (Optional)",
"HelpText": "*Optional*: Include the certificate chain with the exported certificate. Not supported with `DER` format. Default: `False`.",
"DefaultValue": "False",
"DisplaySettings": {
"Octopus.ControlType": "Checkbox"
}
},
{
"Id": "71fecac3-25c4-4161-9135-94815a485f03",
"Name": "Venafi.TPP.ImportCert.FriendlyName",
"Label": "Friendly Name (Optional)",
"HelpText": "*Optional*: Label or alias to use. Permitted with `Base64` and `PKCS #12` formats.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "2aaedf1d-be93-4df4-856c-c69650db452a",
"Name": "Venafi.TPP.ImportCert.IncludePrivateKey",
"Label": "Include Private Key (Optional)",
"HelpText": "*Optional*: Include the private key in the certificate export. If this is selected, the `Venafi.TPP.Export.PrivateKeyPassword` must also be provided. Default: `False`.",
"DefaultValue": "False",
"DisplaySettings": {
"Octopus.ControlType": "Checkbox"
}
},
{
"Id": "2d168360-bcbf-4bdc-833d-a9c182e98a47",
"Name": "Venafi.TPP.ImportCert.PrivateKeyPassword",
"Label": "Private Key password (Optional)",
"HelpText": "*Optional*: The password required to include the private key. Not supported with `DER` format. You must adhere to the following rules: \n\n- Password is at least 12 characters. \n- Comprised of at least three of the following: \n - Uppercase alphabetic letters \n - Lowercase alphabetic letters \n - Numeric characters \n - Special characters",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "Sensitive"
}
},
{
"Id": "84f92dd5-064b-47e5-bb11-3dd0faacfeb4",
"Name": "Venafi.TPP.ImportCert.OutputVariableName",
"Label": "Certificate output variable name (Optional)",
"HelpText": "*Optional*: Create an output variable with the certificate details returned from the export call. The certificate details will be stored in `JSON` format.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "606acdfe-641a-47f2-a4ea-56559477ea0c",
"Name": "Venafi.TPP.ImportCert.RevokeTokenOnCompletion",
"Label": "Revoke access token on completion?",
"HelpText": "*Optional*: Should the access token used be revoked once the step has been completed successfully? Default: `False`.",
"DefaultValue": "False",
"DisplaySettings": {
"Octopus.ControlType": "Checkbox"
}
},
{
"Id": "7813080c-d6d6-4bd1-8c38-d6d03921f541",
"Name": "Venafi.TPP.ImportCert.OctopusServerUri",
"Label": "Octopus Server Url",
"HelpText": "*Required*: Provide the base URL of your Octopus Server. There are two built-in Octopus variables you can use:\n\n- `#{if Octopus.Web.ServerUri}#{Octopus.Web.ServerUri}#{else}#{Octopus.Web.BaseUrl}#{/if}`\n- `Octopus.Web.ServerUri`\n\nSee our [system variables](https://octopus.com/docs/projects/variables/system-variables#Systemvariables-Server) page for further details.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "5be3cf08-43ef-44a3-bd89-3ec3b4928b01",
"Name": "Venafi.TPP.ImportCert.OctopusApiKey",
"Label": "Octopus API Key",
"HelpText": "*Required*: Provide an Octopus API Key with appropriate permissions to save the certificate.\n",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "Sensitive"
}
},
{
"Id": "d901f398-a035-4ba6-a546-553360eed283",
"Name": "Venafi.TPP.ImportCert.OctopusSpaceName",
"Label": "Octopus Space Name",
"HelpText": "*Required*: Provide the Space name for the certificate to be saved in. The default is the current space the step is running within: `#{Octopus.Space.Name}`.",
"DefaultValue": "#{Octopus.Space.Name}",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "56f8e1a8-fb6c-4b91-a216-eadc2f5cd673",
"Name": "Venafi.TPP.ImportCert.OctopusCertificateName",
"Label": "Octopus Certificate Name",
"HelpText": "*Required*: A short, memorable, unique name for the imported certificate.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "3a85993f-8844-49aa-951a-804471f53b23",
"Name": "Venafi.TPP.ImportCert.OctopusReplaceExistingCertificate",
"Label": "Replace existing Octopus certificate?",
"HelpText": "*Optional*: If a certificate exists in Octopus with the same name as the one to be imported, should the one stored in Octopus be replaced? Default: `True`.\n\n**Note**: If multiple matches are found, the step template will not replace any, and will log a warning instead.\n\nSee [replacing certificates](https://octopus.com/docs/deployments/certificates/replace-certificate) for further information.",
"DefaultValue": "True",
"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# TPP required variables\n$Server = $OctopusParameters[\"Venafi.TPP.ImportCert.Server\"]\n$Token = $OctopusParameters[\"Venafi.TPP.ImportCert.AccessToken\"]\n$Path = $OctopusParameters[\"Venafi.TPP.ImportCert.DNPath\"]\n$Format = $OctopusParameters[\"Venafi.TPP.ImportCert.Format\"]\n\n# TPP optional variables\n$IncludeChain = $OctopusParameters[\"Venafi.TPP.ImportCert.IncludeChain\"]\n$FriendlyName = $OctopusParameters[\"Venafi.TPP.ImportCert.FriendlyName\"]\n$IncludePrivateKey = $OctopusParameters[\"Venafi.TPP.ImportCert.IncludePrivateKey\"]\n$PrivateKeyPassword = $OctopusParameters[\"Venafi.TPP.ImportCert.PrivateKeyPassword\"]\n$OutputVariableName = $OctopusParameters[\"Venafi.TPP.ImportCert.OutputVariableName\"]\n$RevokeToken = $OctopusParameters[\"Venafi.TPP.ImportCert.RevokeTokenOnCompletion\"]\n\n# Octopus required variables\n$OctopusServerUri = $OctopusParameters[\"Venafi.TPP.ImportCert.OctopusServerUri\"]\n$OctopusApiKey = $OctopusParameters[\"Venafi.TPP.ImportCert.OctopusApiKey\"]\n$OctopusSpaceName = $OctopusParameters[\"Venafi.TPP.ImportCert.OctopusSpaceName\"]\n$OctopusCertificateName = $OctopusParameters[\"Venafi.TPP.ImportCert.OctopusCertificateName\"]\n$OctopusReplaceExistingCertificate = $OctopusParameters[\"Venafi.TPP.ImportCert.OctopusReplaceExistingCertificate\"]\n\n# TPP validation\nif ([string]::IsNullOrWhiteSpace($Server)) {\n throw \"Required parameter Venafi.TPP.ImportCert.Server not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($Token)) {\n throw \"Required parameter Venafi.TPP.ImportCert.AccessToken not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($Path)) {\n throw \"Required parameter Venafi.TPP.ImportCert.DNPath not specified\"\n}\nelse {\n if ($Path.Contains(\"\\\") -eq $False) {\n throw \"At least one '\\' is required for the Venafi.TPP.ImportCert.DNPath value\"\n }\n}\nif ([string]::IsNullOrWhiteSpace($Format)) {\n throw \"Required parameter Venafi.TPP.ImportCert.Format not specified\"\n}\n\n# TPP conditional validation\nif ($IncludePrivateKey -eq $True) {\n if ([string]::IsNullOrWhiteSpace($PrivateKeyPassword)) {\n throw \"IncludePrivateKey set to true, but parameter Venafi.TPP.ImportCert.PrivateKeyPassword not specified\"\n }\n}\nelse {\n $PrivateKeyPassword = $null\n}\n\n# Octopus validation\nif ([string]::IsNullOrWhiteSpace($OctopusServerUri)) {\n throw \"Required parameter Venafi.TPP.ImportCert.OctopusServerUri not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($OctopusApiKey)) {\n throw \"Required parameter Venafi.TPP.ImportCert.OctopusApiKey not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($OctopusSpaceName)) {\n throw \"Required parameter Venafi.TPP.ImportCert.OctopusSpaceName not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($OctopusCertificateName)) {\n throw \"Required parameter Venafi.TPP.ImportCert.OctopusCertificateName not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($OctopusReplaceExistingCertificate)) {\n throw \"Required parameter Venafi.TPP.ImportCert.OctopusReplaceExistingCertificate 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\nfunction Get-MatchingOctopusCertificates {\n param (\n [string]$ServerUri,\n [string]$ApiKey,\n [string]$SpaceId,\n [string]$CertificateName\n )\n Write-Debug \"Entering: Get-MatchingOctopusCertificates\"\n\n try {\n\n $header = @{ \"X-Octopus-ApiKey\" = $ApiKey }\n\n # Get a list of certificates that match our domain search criteria.\n $partial_certificates = (Invoke-RestMethod -Uri \"$ServerUri/api/$SpaceId/certificates?partialName=$([uri]::EscapeDataString($CertificateName))&skip=0&take=2000\" -Headers $header) | Select-Object -ExpandProperty Items\n\n # return certs that arent archived and havent been replaced.\n return $partial_certificates | Where-Object {\n $null -eq $_.ReplacedBy -and\n $null -eq $_.Archived -and \n $CertificateName -eq $_.Name\n }\n }\n catch {\n $Detail = (Get-WebRequestErrorBody -RequestError $_)\n Write-Error \"Could not retrieve certificates from Octopus. Error: $($_.Exception.Message).`n`t$Detail\"\n }\n}\n\nfunction Replace-OctopusCertificate {\n param (\n [string]$ServerUri,\n [string]$ApiKey,\n [string]$SpaceId,\n [string]$CertificateId,\n [string]$CertificateName,\n [string]$CertificateData,\n [string]$CertificatePwd\n )\n Write-Debug \"Entering: Replace-OctopusCertificate\" \n try {\n\n $header = @{ \"X-Octopus-ApiKey\" = $ApiKey }\n\n $replacement_certificate = @{\n CertificateData = $CertificateData\n }\n\n if (![string]::IsNullOrWhiteSpace($CertificatePwd)) {\n $replacement_certificate.Password = $CertificatePwd\n }\n \n # Replace the cert\n $updated_certificate = Invoke-RestMethod -Method Post -Uri \"$ServerUri/api/$SpaceId/certificates/$CertificateId/replace\" -Headers $header -Body ($replacement_certificate | ConvertTo-Json -Depth 10)\n Write-Highlight \"Replaced certificate in Octopus for '$($updated_certificate.Name)' ($($updated_certificate.Id))\"\n }\n catch {\n $Detail = (Get-WebRequestErrorBody -RequestError $_)\n Write-Error \"Could not replace certificate in Octopus. Error: $($_.Exception.Message).`n`t$Detail\"\n }\n}\n\nfunction New-OctopusCertificate {\n param (\n [string]$ServerUri,\n [string]$ApiKey,\n [string]$SpaceId,\n [string]$CertificateName,\n [string]$CertificateData,\n [string]$CertificatePwd\n )\n Write-Debug \"Entering: New-OctopusCertificate\" \n try {\n\n $header = @{ \"X-Octopus-ApiKey\" = $ApiKey }\n\n $certificate = @{\n Name = $CertificateName;\n CertificateData = @{\n NewValue = $CertificateData;\n HasData = $True;\n }\n Password = @{\n HasValue = $False;\n NewValue = $null;\n }\n }\n\n if (![string]::IsNullOrWhiteSpace($CertificatePwd)) {\n $certificate.Password.NewValue = $CertificatePwd\n $certificate.Password.HasData = $True\n }\n \n # Create new certificate\n $new_certificate = Invoke-RestMethod -Method Post -Uri \"$ServerUri/api/$SpaceId/certificates\" -Headers $header -Body ($certificate | ConvertTo-Json -Depth 10)\n Write-Highlight \"New certificate created in Octopus for '$($new_certificate.Name)' ($($new_certificate.Id))\"\n }\n catch {\n $Detail = (Get-WebRequestErrorBody -RequestError $_)\n Write-Error \"Could not create new certificate in Octopus. Error: $($_.Exception.Message).`n`t$Detail\"\n }\n}\n\nfunction Clean-VenafiCertificateForOctopus {\n param (\n [string]$CertificateData\n )\n Write-Debug \"Entering: Clean-VenafiCertificateForOctopus\" \n $PemHeaderFragment = \"-----BEGIN *\"\n $PemFooterFragment = \"-----END *\"\n\n $CertificateBytes = [Convert]::FromBase64String($CertificateData)\n $RawCert = [System.Text.Encoding]::UTF8.GetString($CertificateBytes)\n \n $CleanedCertLines = @()\n if (![string]::IsNullOrWhiteSpace($RawCert)) {\n $RawCertLines = ($RawCert -Split \"`n\")\n $currentLine = 0\n while ($currentLine -lt $RawCertLines.Length) {\n Write-Verbose \"Working on line $currentLine\"\n $headerPosition = [Array]::FindIndex($RawCertLines, $currentLine, [Predicate[string]] { $args[0] -like $PemHeaderFragment })\n if ($headerPosition -gt -1) {\n $footerPosition = [Array]::FindIndex($RawCertLines, $headerPosition, [Predicate[string]] { $args[0] -like $PemFooterFragment })\n if ($footerPosition -lt 0) {\n throw \"Unable to find a matching '-----END' PEM fragment!\"\n }\n else {\n Write-Verbose \"Selecting PEM lines: $headerPosition-$footerPosition\"\n $pemLines = $RawCertLines[$headerPosition..$footerPosition]\n $CleanedCertLines += $pemLines\n $currentLine = $footerPosition\n }\n }\n else {\n $currentLine++\n }\n }\n }\n if ($CleanedCertLines.Length -le 0) {\n throw \"Something went wrong extracting contents from file (no cleansed contents)\"\n }\n\n $CleanedCert = $CleanedCertLines | Out-String\n $CleanedCertData = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($CleanedCert))\n \n return $CleanedCertData \n}\n###############################################################################\n# MAIN STEP TEMPLATE FLOW\n###############################################################################\n\n# TPP Access token\n$SecureToken = ConvertTo-SecureString $Token -AsPlainText -Force\n[PSCredential]$AccessToken = New-Object System.Management.Automation.PsCredential(\"token\", $SecureToken)\n\n# Clean-up\n$Server = $Server.TrimEnd('/')\n$OctopusServerUri = $OctopusServerUri.TrimEnd('/')\n$OctopusSpaceName = $OctopusSpaceName.Trim(\" \")\n$OctopusCertificateName = $OctopusCertificateName.Trim(\" \")\n\n# Required Venafi Module\nfunction Get-NugetPackageProviderNotInstalled {\n # See if the nuget package provider has been installed\n return ($null -eq (Get-PackageProvider -ListAvailable -Name Nuget -ErrorAction SilentlyContinue))\n}\n\n# Check to see if the package provider has been installed\nif ((Get-NugetPackageProviderNotInstalled) -ne $false) {\n Write-Host \"Nuget package provider not found, installing ...\" \n Install-PackageProvider -Name Nuget -Force -Scope CurrentUser\n}\n\nWrite-Host \"Checking for required VenafiPS module ...\"\n$required_venafips_version = 3.1.5\n$module_available = Get-Module -ListAvailable -Name VenafiPS | Where-Object { $_.Version -ge $required_venafips_version }\nif (-not ($module_available)) {\n Write-Host \"Installing VenafiPS module ...\"\n Install-Module -Name VenafiPS -MinimumVersion 3.1.5 -Scope CurrentUser -Force\n}\nelse {\n $first_match = $module_available | Select-Object -First 1 \n Write-Host \"Found version: $($first_match.Version)\"\n}\n\nWrite-Host \"Importing VenafiPS module ...\"\nImport-Module VenafiPS\n\n$StepName = $OctopusParameters[\"Octopus.Step.Name\"]\n$ExportFormatsIncompatibleWithOctopusCertificateStore = @(\"Base64\", \"Base64 (PKCS #8)\")\n\nWrite-Verbose \"Venafi.TPP.ImportCert.Server: $Server\"\nWrite-Verbose \"Venafi.TPP.ImportCert.AccessToken: ********\"\nWrite-Verbose \"Venafi.TPP.ImportCert.DNPath: $Path\"\nWrite-Verbose \"Venafi.TPP.ImportCert.Format: $Format\"\nWrite-Verbose \"Venafi.TPP.ImportCert.IncludeChain: $IncludeChain\"\nWrite-Verbose \"Venafi.TPP.ImportCert.FriendlyName: $FriendlyName\"\nWrite-Verbose \"Venafi.TPP.ImportCert.IncludePrivateKey: $IncludePrivateKey\"\nWrite-Verbose \"Venafi.TPP.ImportCert.PrivateKeyPassword: ********\"\nWrite-Verbose \"Venafi.TPP.ImportCert.CertDetails.OutputVariableName: $OutputVariableName\"\nWrite-Verbose \"Venafi.TPP.ImportCert.RevokeTokenOnCompletion: $RevokeTokenOnCompletion\"\nWrite-Verbose \"Venafi.TPP.ImportCert.OctopusServerUri: $OctopusServerUri\"\nWrite-Verbose \"Venafi.TPP.ImportCert.OctopusApiKey: ********\"\nWrite-Verbose \"Venafi.TPP.ImportCert.OctopusSpaceName: $OctopusSpaceName\"\nWrite-Verbose \"Venafi.TPP.ImportCert.OctopusCertificateName: $OctopusCertificateName\"\nWrite-Verbose \"Venafi.TPP.ImportCert.OctopusReplaceExistingCertificate: $OctopusReplaceExistingCertificate\"\nWrite-Verbose \"Step Name: $StepName\"\n\nWrite-Host \"Requesting new session from $Server\"\nNew-VenafiSession -Server $Server -AccessToken $AccessToken\n\n# Export certificate\n$ExportCert_Params = @{\n CertificateId = $Path;\n Format = $Format;\n}\n\n# Optional IncludeChain field\nif ($IncludeChain -eq $True) {\n $ExportCert_Params.IncludeChain = $True\n}\n\n# Optional FriendlyName field\nif (-not [string]::IsNullOrWhiteSpace($FriendlyName)) {\n $ExportCert_Params.FriendlyName = $FriendlyName\n}\n\n# Optional Private key field\nif (-not [string]::IsNullOrWhiteSpace($PrivateKeyPassword) -and $IncludePrivateKey -eq $True) {\n $SecurePrivateKeyPassword = ConvertTo-SecureString $PrivateKeyPassword -AsPlainText -Force\n $ExportCert_Params.PrivateKeyPassword = $SecurePrivateKeyPassword \n $ExportCert_Params.IncludePrivateKey = $True\n}\n\n# Do the export\n$ExportCertificateResponse = ((Export-VenafiCertificate @ExportCert_Params) 6> $null)\n\nif ($null -eq $ExportCertificateResponse -or $null -eq $ExportCertificateResponse.CertificateData) {\n Write-Warning \"No certificate data returned for path: $Path`nCheck the path value represents a certificate, and not a folder.\"\n}\nelse {\n Write-Host \"Successfully retrieved certificate data to export for path: $Path\"\n \n # Get octopus space Id\n $header = @{ \"X-Octopus-ApiKey\" = $OctopusApiKey }\n $spaces = Invoke-RestMethod -Uri \"$OctopusServerUri/api/spaces?partialName=$([uri]::EscapeDataString($OctopusSpaceName))&skip=0&take=500\" -Headers $header \n $OctopusSpace = @($spaces.Items | Where-Object { $_.Name -eq $OctopusSpaceName }) | Select-Object -First 1\n\n if ($null -eq $OctopusSpace) {\n throw \"Couldnt find Octopus space with name '$OctopusSpaceName'.\"\n }\n\n # Check for certificate based on name\n $CertificateMatches = @(Get-MatchingOctopusCertificates -ServerUri $OctopusServerUri -ApiKey $OctopusApiKey -SpaceId $($OctopusSpace.Id) -CertificateName $OctopusCertificateName) \n Write-Host \"Found $($CertificateMatches.Length) certificates matching '$OctopusCertificateName'\"\n\n $FirstCertificateMatch = $CertificateMatches | Select-Object -First 1\n $CertificateData = $ExportCertificateResponse.CertificateData\n\n if ($ExportFormatsIncompatibleWithOctopusCertificateStore -icontains $Format) {\n Write-Host \"Requested export format $Format needs to be cleaned before import to Octopus.\"\n $CertificateData = Clean-VenafiCertificateForOctopus -CertificateData $CertificateData\n if ([string]::IsNullOrWhiteSpace($CertificateData)) {\n throw \"Cleaned certificate data empty!\"\n }\n }\n\n switch ($CertificateMatches.Length) {\n 0 { \n # New cert\n Write-Host \"Creating a new certificate '$OctopusCertificateName'\"\n New-OctopusCertificate -ServerUri $OctopusServerUri -ApiKey $OctopusApiKey -SpaceId $($OctopusSpace.Id) -CertificateName $OctopusCertificateName -CertificateData $($CertificateData) -CertificatePwd $PrivateKeyPassword\n }\n 1 { \n # One cert to replace\n if ($OctopusReplaceExistingCertificate -eq $False) {\n Write-Host \"Replace existing certificate set to False, nothing to do.\"\n }\n else {\n Write-Host \"Replacing existing certificate '$OctopusCertificateName' ($($FirstCertificateMatch.Id))\"\n Replace-OctopusCertificate -ServerUri $OctopusServerUri -ApiKey $OctopusApiKey -SpaceId $($OctopusSpace.Id) -CertificateId $($FirstCertificateMatch.Id) -CertificateName $OctopusCertificateName -CertificateData $($CertificateData) -CertificatePwd $PrivateKeyPassword\n }\n }\n default {\n Write-Warning \"Multiple certs matching name '$OctopusCertificateName' found, nothing to do.\"\n return\n }\n }\n\n if ([string]::IsNullOrWhiteSpace($OutputVariableName) -eq $False) {\n $CertificateJson = $ExportCertificateResponse | ConvertTo-Json -Compress -Depth 10 \n Set-OctopusVariable -Name $OutputVariableName -Value $CertificateJson -Sensitive\n Write-Highlight \"Created sensitive output variable: ##{Octopus.Action[$StepName].Output.$OutputVariableName}\"\n }\n}\n\nif ($RevokeToken -eq $true) {\n # Revoke TPP access token\n Write-Host \"Revoking access token with $Server\"\n Revoke-TppToken -AuthServer $Server -AccessToken $AccessToken -Force\n}"
},
"Category": "Venafi",
"HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates//opt/buildagent/work/75443764cd38076d/step-templates/venafi-tpp-import-certificate-into-octopus.json",
"Website": "/step-templates/e10820c2-ae6d-4030-8a8a-b73ed60a81fc",
"Logo": "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",
"$Meta": {
"Type": "ActionTemplate"
}
}
Page updated on Monday, August 23, 2021