Octopus.Script exported 2026-08-12 by harrisonmeister belongs to ‘Lets Encrypt’ category.
Request (or renew) a X.509 SSL Certificate from the Let’s Encrypt Certificate Authority.
Features
- ACME v2 protocol support which allows generating wildcard certificates (*.example.com)
- Azure DNS Challenge for TLD, CNAME and Wildcard domains.
- Publishes/Updates SSL Certificates in the Octopus Deploy Certificate Store.
- Verified to work on both Windows (PowerShell 5+) and Linux (PowerShell 6+) deployment Targets or Workers.
Parameters
When steps based on the template are included in a project’s deployment process, the parameters below can be set.
Certificate Domain
LE_AzureDNS_CertificateDomain =
Domain (TLD, CNAME or Wildcard) to create a certificate for.
PFX Password
LE_AzureDNS_PfxPassword =
Password to use when converting to / from PFX.
Replace expiring certificate before N days
LE_AzureDNS_ReplaceIfExpiresInDays = 30
Replace the certificate if it expiries within N days
Azure account
LE_AzureDNS_AzureAccount =
An Azure Account that has API access to make DNS changes.
Octopus Deploy API key
LE_AzureDNS_Octopus_APIKey =
A Octopus Deploy API key with access to change Certificates in the Certificate Store.
Use Lets Encrypt Staging
LE_AzureDNS_Use_Staging = false
Should the Certificate be generated using the Lets Encrypt Staging infrastructure?
Contact Email Address
LE_AzureDNS_ContactEmailAddress = #{Octopus.Deployment.CreatedBy.EmailAddress}
Email Address
Create Wildcard SAN
LE_AzureDNS_CreateWildcardSAN = false
Should the certificate have a Subject Alternative Name (SAN) excluding the wildcard?
e.g. a certificate domain of *.internal.example-domain.com could also have a SAN of internal.example-domain.com
DNS Alias
LE_AzureDNS_DnsAlias =
Use a CNAME alias for the TXT challenge.
Script body
Steps based on this template will execute the following PowerShell script.
###############################################################################
# TLS 1.2
###############################################################################
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
###############################################################################
# Required Modules folder
###############################################################################
Write-Host "Checking for required powershell modules folder"
$ModulesFolder = "$HOME\Documents\WindowsPowerShell\Modules"
if ($PSEdition -eq "Core") {
if ($PSVersionTable.Platform -eq "Unix") {
$ModulesFolder = "$HOME/.local/share/powershell/Modules"
}
else {
$ModulesFolder = "$HOME\Documents\PowerShell\Modules"
}
}
$PSModuleFolderExists = (Test-Path $ModulesFolder)
if ($PSModuleFolderExists -eq $False) {
Write-Host "Creating directory: $ModulesFolder"
New-Item $ModulesFolder -ItemType Directory -Force
$env:PSModulePath = $ModulesFolder + [System.IO.Path]::PathSeparator + $env:PSModulePath
}
###############################################################################
# Required Modules
###############################################################################
Write-Host "Checking for required modules."
$required_posh_acme_version = 3.12.0
$module_check = Get-Module -ListAvailable -Name Posh-Acme | Where-Object { $_.Version -ge $required_posh_acme_version }
if (-not ($module_check)) {
Write-Host "Ensuring NuGet provider is bootstrapped."
Get-PackageProvider NuGet -ForceBootstrap | Out-Null
Write-Host "Installing Posh-ACME."
Install-Module -Name Posh-ACME -MinimumVersion 3.12.0 -Scope CurrentUser -Force
}
Import-Module Posh-ACME
###############################################################################
# Constants
###############################################################################
$LE_AzureDNS_CertificateDomain = $OctopusParameters["LE_AzureDNS_CertificateDomain"]
$LE_AzureDNS_CertificateName = "Lets Encrypt - $($LE_AzureDNS_CertificateDomain)"
# Let's Encrypt rotates its intermediate CAs and the Common Name of each intermediate is
# short lived (Let's Encrypt Authority X3 -> R3 -> R10 -> YR1 and so on), so matching on a
# list of Common Names goes stale every time a new intermediate appears. Match on the issuer
# Organization instead, which has been stable since 2015, and use the "(STAGING) " prefix on
# the Common Name to tell staging and production apart. The prefix is what separates the two
# environments: staging intermediates in the Generation Y hierarchy carry the production
# Organization, so the Organization alone cannot be used to distinguish them.
$LE_AzureDNS_Issuer_Organizations = @("Let's Encrypt", "(STAGING) Let's Encrypt")
$LE_AzureDNS_Staging_Issuer_CommonNamePattern = "(STAGING) *"
# The original staging intermediate carries no Organization, so it is matched on Common Name.
$LE_AzureDNS_Legacy_Staging_Issuer_CommonName = "Fake LE Intermediate X1"
# (Optional) CNAME DNS alias. If specified, the alias will be used for the TXT challenge.
# https://poshac.me/docs/v4/Guides/Using-DNS-Challenge-Aliases/
$LE_AzureDNS_DnsAlias = $OctopusParameters["LE_AzureDNS_DnsAlias"]
###############################################################################
# Helpers
###############################################################################
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()
$response = $reader.ReadToEnd()
return $response | ConvertFrom-Json
}
}
else {
return $RequestError.ErrorDetails.Message
}
}
function Test-IsLetsEncryptIssuer {
[OutputType([bool])]
param (
$Certificate,
[bool] $Staging
)
$issuer_organization = $Certificate.IssuerOrganization
$issuer_common_name = $Certificate.IssuerCommonName
# Fall back to the Distinguished Name if the Octopus Server did not populate these fields.
if ([string]::IsNullOrWhiteSpace($issuer_organization) -and $Certificate.IssuerDistinguishedName -match '(?:^|,)\s*O\s*=\s*([^,]+)') {
$issuer_organization = $Matches[1].Trim()
}
if ([string]::IsNullOrWhiteSpace($issuer_common_name) -and $Certificate.IssuerDistinguishedName -match '(?:^|,)\s*CN\s*=\s*([^,]+)') {
$issuer_common_name = $Matches[1].Trim()
}
# The original staging intermediate carries no Organization, so it is matched on Common Name.
$is_legacy_staging_issuer = ($issuer_common_name -eq $LE_AzureDNS_Legacy_Staging_Issuer_CommonName)
# Did Let's Encrypt issue this certificate, production or staging?
$issued_by_lets_encrypt = ($LE_AzureDNS_Issuer_Organizations -contains $issuer_organization) -or $is_legacy_staging_issuer
if (-not $issued_by_lets_encrypt) {
Write-Debug "Issuer '$issuer_common_name' is not Let's Encrypt. Skipping this certificate."
return $false
}
# Did a staging intermediate issue it? Staging Common Names are prefixed with "(STAGING) ".
# The Organization cannot answer this: Generation Y staging intermediates carry the
# production Organization of "Let's Encrypt".
$issued_by_staging = ($issuer_common_name -like $LE_AzureDNS_Staging_Issuer_CommonNamePattern) -or $is_legacy_staging_issuer
if ($Staging -and $issued_by_staging) {
return $true
}
if ((-not $Staging) -and (-not $issued_by_staging)) {
return $true
}
Write-Debug "Issuer '$issuer_common_name' is not from the Let's Encrypt environment we want. Skipping this certificate."
return $false
}
###############################################################################
# Functions
###############################################################################
function Get-LetsEncryptCertificate {
Write-Debug "Entering: Get-LetsEncryptCertificate"
if ($OctopusParameters["LE_AzureDNS_Use_Staging"] -eq $True) {
Write-Host "Using Lets Encrypt Server: Staging"
Set-PAServer LE_STAGE;
}
else {
Write-Host "Using Lets Encrypt Server: Production"
Set-PAServer LE_PROD;
}
# Clobber account if it exists.
$le_account = Get-PAAccount
if ($le_account) {
Remove-PAAccount $le_account.Id -Force
}
$azure_password = ConvertTo-SecureString -String $OctopusParameters["LE_AzureDNS_AzureAccount.Password"] -AsPlainText -Force
$azure_credential = New-Object System.Management.Automation.PSCredential($OctopusParameters["LE_AzureDNS_AzureAccount.Client"], $azure_password)
$azure_params = @{
AZSubscriptionId = $OctopusParameters["LE_AzureDNS_AzureAccount.SubscriptionNumber"];
AZTenantId = $OctopusParameters["LE_AzureDNS_AzureAccount.TenantId"];
AZAppCred = $azure_credential
}
try {
$DnsPlugins = @("Azure")
$DomainList = @($LE_AzureDNS_CertificateDomain)
# If domain is a wildcard e.g. *.example-domain.com, check if a SAN has been requested e.g. example-domain.com.
if ($LE_AzureDNS_CertificateDomain -match "\*." -and $OctopusParameters["LE_AzureDNS_CreateWildcardSAN"] -eq $True) {
$LE_AzureDNS_Certificate_SAN = $LE_AzureDNS_CertificateDomain.Replace("*.","")
$DomainList += $LE_AzureDNS_Certificate_SAN
# Include additional DnsPlugin of same type to suppress warning.
$DnsPlugins += "Azure"
}
$Cert_Params = @{
Domain = $DomainList
AcceptTOS = $True;
Contact = $OctopusParameters["LE_AzureDNS_ContactEmailAddress"];
DnsPlugin = $DnsPlugins;
PluginArgs = $azure_params;
PfxPass = $OctopusParameters["LE_AzureDNS_PfxPassword"];
Force = $True;
}
if ($LE_AzureDNS_DnsAlias) {
$Cert_Params += @{DnsAlias = @($LE_AzureDNS_DnsAlias, $LE_AzureDNS_DnsAlias)} # Adding the value twice to avoid the warning "Fewer DnsAlias values than names in the order."
}
return New-PACertificate @Cert_Params
}
catch {
Write-Host "Failed to Create Certificate. Error Message: $($_.Exception.Message). See Debug output for details."
Write-Debug (Get-WebRequestErrorBody -RequestError $_)
exit 1
}
}
function Get-OctopusCertificates {
Write-Debug "Entering: Get-OctopusCertificates"
$octopus_uri = $OctopusParameters["Octopus.Web.ServerUri"]
$octopus_space_id = $OctopusParameters["Octopus.Space.Id"]
$octopus_headers = @{ "X-Octopus-ApiKey" = $OctopusParameters["LE_AzureDNS_Octopus_APIKey"] }
$octopus_certificates_uri = "$octopus_uri/api/$octopus_space_id/certificates?search=$($LE_AzureDNS_CertificateDomain)"
try {
# Get a list of certificates that match our domain search criteria.
$certificates_search = Invoke-WebRequest -Uri $octopus_certificates_uri -Method Get -Headers $octopus_headers -UseBasicParsing -ErrorAction Stop | ConvertFrom-Json | Select-Object -ExpandProperty Items
# We don't want to confuse Production and Staging Lets Encrypt Certificates.
$use_staging = ($OctopusParameters["LE_AzureDNS_Use_Staging"] -eq $True)
return $certificates_search | Where-Object {
$_.SubjectCommonName -eq $LE_AzureDNS_CertificateDomain -and
(Test-IsLetsEncryptIssuer -Certificate $_ -Staging $use_staging) -and
$null -eq $_.ReplacedBy -and
$null -eq $_.Archived
}
}
catch {
Write-Host "Could not retrieve certificates from Octopus Deploy. Error: $($_.Exception.Message). See Debug output for details."
Write-Debug (Get-WebRequestErrorBody -RequestError $_)
exit 1
}
}
function Publish-OctopusCertificate {
param (
[string] $JsonBody
)
Write-Debug "Entering: Publish-OctopusCertificate"
if (-not ($JsonBody)) {
Write-Host "Existing Certificate is required."
exit 1
}
$octopus_uri = $OctopusParameters["Octopus.Web.ServerUri"]
$octopus_space_id = $OctopusParameters["Octopus.Space.Id"]
$octopus_headers = @{ "X-Octopus-ApiKey" = $OctopusParameters["LE_AzureDNS_Octopus_APIKey"] }
$octopus_certificates_uri = "$octopus_uri/api/$octopus_space_id/certificates"
try {
Invoke-WebRequest -Uri $octopus_certificates_uri -Method Post -Headers $octopus_headers -Body $JsonBody -UseBasicParsing
Write-Host "Published $($LE_AzureDNS_CertificateDomain) certificate to the Octopus Deploy Certificate Store."
}
catch {
Write-Host "Failed to publish $($LE_AzureDNS_CertificateDomain) certificate. Error: $($_.Exception.Message). See Debug output for details."
Write-Debug (Get-WebRequestErrorBody -RequestError $_)
exit 1
}
}
function Update-OctopusCertificate {
param (
[string]$Certificate_Id,
[string]$JsonBody
)
Write-Debug "Entering: Update-OctopusCertificate"
if (-not ($Certificate_Id -and $JsonBody)) {
Write-Host "Existing Certificate Id and a replace Certificate are required."
exit 1
}
$octopus_uri = $OctopusParameters["Octopus.Web.ServerUri"]
$octopus_space_id = $OctopusParameters["Octopus.Space.Id"]
$octopus_headers = @{ "X-Octopus-ApiKey" = $OctopusParameters["LE_AzureDNS_Octopus_APIKey"] }
$octopus_certificates_uri = "$octopus_uri/api/$octopus_space_id/certificates/$Certificate_Id/replace"
try {
Invoke-WebRequest -Uri $octopus_certificates_uri -Method Post -Headers $octopus_headers -Body $JsonBody -UseBasicParsing
Write-Host "Replaced $($LE_AzureDNS_CertificateDomain) certificate in the Octopus Deploy Certificate Store."
}
catch {
Write-Error "Failed to replace $($LE_AzureDNS_CertificateDomain) certificate. Error: $($_.Exception.Message)"
exit 1
}
}
function Get-NewCertificatePFXAsJson {
param (
$Certificate
)
Write-Debug "Entering: Get-NewCertificatePFXAsJson"
if (-not ($Certificate)) {
Write-Host "Certificate is required."
Exit 1
}
[Byte[]]$certificate_buffer = [System.IO.File]::ReadAllBytes($Certificate.PfxFullChain)
$certificate_base64 = [convert]::ToBase64String($certificate_buffer)
$certificate_body = @{
Name = "$LE_AzureDNS_CertificateName";
Notes = "";
CertificateData = @{
HasValue = $true;
NewValue = $certificate_base64;
};
Password = @{
HasValue = $true;
NewValue = $OctopusParameters["LE_AzureDNS_PfxPassword"];
};
}
return $certificate_body | ConvertTo-Json
}
function Get-ReplaceCertificatePFXAsJson {
param (
$Certificate
)
Write-Debug "Entering: Get-ReplaceCertificatePFXAsJson"
if (-not ($Certificate)) {
Write-Host "Certificate is required."
Exit 1
}
[Byte[]]$certificate_buffer = [System.IO.File]::ReadAllBytes($Certificate.PfxFullChain)
$certificate_base64 = [convert]::ToBase64String($certificate_buffer)
$certificate_body = @{
CertificateData = $certificate_base64;
Password = $OctopusParameters["LE_AzureDNS_PfxPassword"];
}
return $certificate_body | ConvertTo-Json
}
###############################################################################
# DO THE THING | MAIN |
###############################################################################
Write-Debug "Do the Thing"
Write-Host "Checking for existing Lets Encrypt Certificates in the Octopus Deploy Certificates Store."
$certificates = Get-OctopusCertificates
# Check for PFX & PEM
if ($certificates) {
# Handle weird behavior between Powershell 5 and Powershell 6+
$certificate_count = 1
if ($certificates.Count -ge 1) {
$certificate_count = $certificates.Count
}
Write-Host "Found $certificate_count for $($LE_AzureDNS_CertificateDomain)."
Write-Host "Checking to see if any expire within $($OctopusParameters["LE_AzureDNS_ReplaceIfExpiresInDays"]) days."
# Check Expiry Dates
$expiring_certificates = $certificates | Where-Object { [DateTime]$_.NotAfter -lt (Get-Date).AddDays($OctopusParameters["LE_AzureDNS_ReplaceIfExpiresInDays"]) }
if ($expiring_certificates) {
Write-Host "Found certificates that expire with $($OctopusParameters["LE_AzureDNS_ReplaceIfExpiresInDays"]) days. Requesting new certificates for $($LE_AzureDNS_CertificateDomain) from Lets Encrypt"
$le_certificate = Get-LetsEncryptCertificate
# PFX
$existing_certificate = $expiring_certificates | Where-Object { $_.CertificateDataFormat -eq "Pkcs12" } | Sort-Object { [DateTime]$_.NotAfter } | Select-Object -First 1
Write-Host "Replacing certificate $($existing_certificate.Id), which expires $(([DateTime]$existing_certificate.NotAfter).ToString('u'))."
$certificate_as_json = Get-ReplaceCertificatePFXAsJson -Certificate $le_certificate
Update-OctopusCertificate -Certificate_Id $existing_certificate.Id -JsonBody $certificate_as_json
}
else {
Write-Host "Nothing to do here..."
}
exit 0
}
# No existing Certificates - Lets get some new ones.
Write-Host "No existing certificates found for $($LE_AzureDNS_CertificateDomain)."
Write-Host "Request New Certificate for $($LE_AzureDNS_CertificateDomain) from Lets Encrypt"
# New Certificate..
$le_certificate = Get-LetsEncryptCertificate
Write-Host "Publishing: LetsEncrypt - $($LE_AzureDNS_CertificateDomain) (PFX)"
$certificate_as_json = Get-NewCertificatePFXAsJson -Certificate $le_certificate
Publish-OctopusCertificate -JsonBody $certificate_as_json
Write-Host "GREAT SUCCESS"
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": "79e0dd12-6222-4f8a-a8dc-bcbe579ed729",
"Name": "Lets Encrypt - Azure DNS",
"Description": "Request (or renew) a X.509 SSL Certificate from the [Let's Encrypt Certificate Authority](https://letsencrypt.org/). \n\n#### Features\n\n- ACME v2 protocol support which allows generating wildcard certificates (*.example.com)\n- [Azure DNS](https://azure.microsoft.com/en-us/services/dns/) Challenge for TLD, CNAME and Wildcard domains. \n- Publishes/Updates SSL Certificates in the [Octopus Deploy Certificate Store](https://octopus.com/docs/deployment-examples/certificates). \n- Verified to work on both Windows (PowerShell 5+) and Linux (PowerShell 6+) deployment Targets or Workers.",
"Version": 17,
"ExportedAt": "2026-08-12T15:16:59.552Z",
"ActionType": "Octopus.Script",
"Author": "harrisonmeister",
"Packages": [],
"Parameters": [
{
"Id": "f1739a56-2603-42e0-b629-801dd71b0b0c",
"Name": "LE_AzureDNS_CertificateDomain",
"Label": "Certificate Domain",
"HelpText": "Domain (TLD, CNAME or Wildcard) to create a certificate for. ",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "c1f44b38-8025-4b12-b010-df48c02b3da4",
"Name": "LE_AzureDNS_PfxPassword",
"Label": "PFX Password",
"HelpText": "Password to use when converting to / from PFX. ",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "Sensitive"
}
},
{
"Id": "c258ee0e-e298-4fa1-9c66-5ac0749409c5",
"Name": "LE_AzureDNS_ReplaceIfExpiresInDays",
"Label": "Replace expiring certificate before N days",
"HelpText": "Replace the certificate if it expiries within N days",
"DefaultValue": "30",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "2935998d-d030-4af6-ad42-39e8b85e2dce",
"Name": "LE_AzureDNS_AzureAccount",
"Label": "Azure account",
"HelpText": "An Azure Account that has API access to make DNS changes. ",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "AzureAccount"
}
},
{
"Id": "85af482d-e577-40b8-94e5-626e545adab5",
"Name": "LE_AzureDNS_Octopus_APIKey",
"Label": "Octopus Deploy API key",
"HelpText": "A Octopus Deploy API key with access to change Certificates in the Certificate Store. ",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "Sensitive"
}
},
{
"Id": "00d513ed-3d75-48d2-954a-0a0165d85530",
"Name": "LE_AzureDNS_Use_Staging",
"Label": "Use Lets Encrypt Staging",
"HelpText": "Should the Certificate be generated using the Lets Encrypt Staging infrastructure?",
"DefaultValue": "false",
"DisplaySettings": {
"Octopus.ControlType": "Checkbox"
}
},
{
"Id": "f1fd315d-9fc5-4b15-b53c-9381ecc5cb88",
"Name": "LE_AzureDNS_ContactEmailAddress",
"Label": "Contact Email Address",
"HelpText": "Email Address",
"DefaultValue": "#{Octopus.Deployment.CreatedBy.EmailAddress}",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "2dc7d9bc-9eee-4ee0-a33c-ef9371ed69f1",
"Name": "LE_AzureDNS_CreateWildcardSAN",
"Label": "Create Wildcard SAN",
"HelpText": "Should the certificate have a Subject Alternative Name (SAN) excluding the wildcard?\n\ne.g. a certificate domain of `*.internal.example-domain.com` could also have a SAN of `internal.example-domain.com`",
"DefaultValue": "false",
"DisplaySettings": {
"Octopus.ControlType": "Checkbox"
}
},
{
"Id": "36451c6b-f61d-4e00-b1f6-956341c9691d",
"Name": "LE_AzureDNS_DnsAlias",
"Label": "DNS Alias",
"HelpText": "Use a CNAME alias for the TXT challenge.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
}
],
"Properties": {
"Octopus.Action.Script.ScriptSource": "Inline",
"Octopus.Action.Script.Syntax": "PowerShell",
"Octopus.Action.Script.ScriptBody": "###############################################################################\n# TLS 1.2\n###############################################################################\n[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12\n\n###############################################################################\n# Required Modules folder\n###############################################################################\nWrite-Host \"Checking for required powershell modules folder\"\n$ModulesFolder = \"$HOME\\Documents\\WindowsPowerShell\\Modules\"\nif ($PSEdition -eq \"Core\") {\n if ($PSVersionTable.Platform -eq \"Unix\") {\n $ModulesFolder = \"$HOME/.local/share/powershell/Modules\"\n }\n else {\n $ModulesFolder = \"$HOME\\Documents\\PowerShell\\Modules\"\n }\n}\n$PSModuleFolderExists = (Test-Path $ModulesFolder)\nif ($PSModuleFolderExists -eq $False) {\n\tWrite-Host \"Creating directory: $ModulesFolder\"\n\tNew-Item $ModulesFolder -ItemType Directory -Force\n $env:PSModulePath = $ModulesFolder + [System.IO.Path]::PathSeparator + $env:PSModulePath\n}\n\n###############################################################################\n# Required Modules\n###############################################################################\nWrite-Host \"Checking for required modules.\"\n$required_posh_acme_version = 3.12.0\n$module_check = Get-Module -ListAvailable -Name Posh-Acme | Where-Object { $_.Version -ge $required_posh_acme_version }\n\nif (-not ($module_check)) {\n Write-Host \"Ensuring NuGet provider is bootstrapped.\"\n Get-PackageProvider NuGet -ForceBootstrap | Out-Null\n Write-Host \"Installing Posh-ACME.\"\n Install-Module -Name Posh-ACME -MinimumVersion 3.12.0 -Scope CurrentUser -Force\n}\n\nImport-Module Posh-ACME\n\n###############################################################################\n# Constants\n###############################################################################\n$LE_AzureDNS_CertificateDomain = $OctopusParameters[\"LE_AzureDNS_CertificateDomain\"]\n$LE_AzureDNS_CertificateName = \"Lets Encrypt - $($LE_AzureDNS_CertificateDomain)\"\n\n# Let's Encrypt rotates its intermediate CAs and the Common Name of each intermediate is\n# short lived (Let's Encrypt Authority X3 -> R3 -> R10 -> YR1 and so on), so matching on a\n# list of Common Names goes stale every time a new intermediate appears. Match on the issuer\n# Organization instead, which has been stable since 2015, and use the \"(STAGING) \" prefix on\n# the Common Name to tell staging and production apart. The prefix is what separates the two\n# environments: staging intermediates in the Generation Y hierarchy carry the production\n# Organization, so the Organization alone cannot be used to distinguish them.\n$LE_AzureDNS_Issuer_Organizations = @(\"Let's Encrypt\", \"(STAGING) Let's Encrypt\")\n$LE_AzureDNS_Staging_Issuer_CommonNamePattern = \"(STAGING) *\"\n# The original staging intermediate carries no Organization, so it is matched on Common Name.\n$LE_AzureDNS_Legacy_Staging_Issuer_CommonName = \"Fake LE Intermediate X1\"\n\n# (Optional) CNAME DNS alias. If specified, the alias will be used for the TXT challenge.\n# https://poshac.me/docs/v4/Guides/Using-DNS-Challenge-Aliases/\n$LE_AzureDNS_DnsAlias = $OctopusParameters[\"LE_AzureDNS_DnsAlias\"]\n\n###############################################################################\n# Helpers\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 $response = $reader.ReadToEnd()\n\n return $response | ConvertFrom-Json\n }\n }\n else {\n return $RequestError.ErrorDetails.Message\n }\n}\n\nfunction Test-IsLetsEncryptIssuer {\n [OutputType([bool])]\n param (\n $Certificate,\n [bool] $Staging\n )\n\n $issuer_organization = $Certificate.IssuerOrganization\n $issuer_common_name = $Certificate.IssuerCommonName\n\n # Fall back to the Distinguished Name if the Octopus Server did not populate these fields.\n if ([string]::IsNullOrWhiteSpace($issuer_organization) -and $Certificate.IssuerDistinguishedName -match '(?:^|,)\\s*O\\s*=\\s*([^,]+)') {\n $issuer_organization = $Matches[1].Trim()\n }\n\n if ([string]::IsNullOrWhiteSpace($issuer_common_name) -and $Certificate.IssuerDistinguishedName -match '(?:^|,)\\s*CN\\s*=\\s*([^,]+)') {\n $issuer_common_name = $Matches[1].Trim()\n }\n\n # The original staging intermediate carries no Organization, so it is matched on Common Name.\n $is_legacy_staging_issuer = ($issuer_common_name -eq $LE_AzureDNS_Legacy_Staging_Issuer_CommonName)\n\n # Did Let's Encrypt issue this certificate, production or staging?\n $issued_by_lets_encrypt = ($LE_AzureDNS_Issuer_Organizations -contains $issuer_organization) -or $is_legacy_staging_issuer\n\n if (-not $issued_by_lets_encrypt) {\n Write-Debug \"Issuer '$issuer_common_name' is not Let's Encrypt. Skipping this certificate.\"\n return $false\n }\n\n # Did a staging intermediate issue it? Staging Common Names are prefixed with \"(STAGING) \".\n # The Organization cannot answer this: Generation Y staging intermediates carry the\n # production Organization of \"Let's Encrypt\".\n $issued_by_staging = ($issuer_common_name -like $LE_AzureDNS_Staging_Issuer_CommonNamePattern) -or $is_legacy_staging_issuer\n\n if ($Staging -and $issued_by_staging) {\n return $true\n }\n\n if ((-not $Staging) -and (-not $issued_by_staging)) {\n return $true\n }\n\n Write-Debug \"Issuer '$issuer_common_name' is not from the Let's Encrypt environment we want. Skipping this certificate.\"\n return $false\n}\n\n###############################################################################\n# Functions\n###############################################################################\nfunction Get-LetsEncryptCertificate {\n Write-Debug \"Entering: Get-LetsEncryptCertificate\"\n\n if ($OctopusParameters[\"LE_AzureDNS_Use_Staging\"] -eq $True) {\n Write-Host \"Using Lets Encrypt Server: Staging\"\n Set-PAServer LE_STAGE;\n }\n else {\n Write-Host \"Using Lets Encrypt Server: Production\"\n Set-PAServer LE_PROD;\n }\n\n # Clobber account if it exists.\n $le_account = Get-PAAccount\n if ($le_account) {\n Remove-PAAccount $le_account.Id -Force\n }\n\n $azure_password = ConvertTo-SecureString -String $OctopusParameters[\"LE_AzureDNS_AzureAccount.Password\"] -AsPlainText -Force\n $azure_credential = New-Object System.Management.Automation.PSCredential($OctopusParameters[\"LE_AzureDNS_AzureAccount.Client\"], $azure_password)\n $azure_params = @{\n AZSubscriptionId = $OctopusParameters[\"LE_AzureDNS_AzureAccount.SubscriptionNumber\"];\n AZTenantId = $OctopusParameters[\"LE_AzureDNS_AzureAccount.TenantId\"];\n AZAppCred = $azure_credential\n }\n\n try {\n\n $DnsPlugins = @(\"Azure\")\n $DomainList = @($LE_AzureDNS_CertificateDomain)\n \n # If domain is a wildcard e.g. *.example-domain.com, check if a SAN has been requested e.g. example-domain.com.\n if ($LE_AzureDNS_CertificateDomain -match \"\\*.\" -and $OctopusParameters[\"LE_AzureDNS_CreateWildcardSAN\"] -eq $True) {\n $LE_AzureDNS_Certificate_SAN = $LE_AzureDNS_CertificateDomain.Replace(\"*.\",\"\")\n $DomainList += $LE_AzureDNS_Certificate_SAN\n # Include additional DnsPlugin of same type to suppress warning.\n $DnsPlugins += \"Azure\"\n }\n\n $Cert_Params = @{\n Domain = $DomainList\n AcceptTOS = $True;\n Contact = $OctopusParameters[\"LE_AzureDNS_ContactEmailAddress\"];\n DnsPlugin = $DnsPlugins;\n PluginArgs = $azure_params;\n PfxPass = $OctopusParameters[\"LE_AzureDNS_PfxPassword\"];\n Force = $True;\n }\n \n if ($LE_AzureDNS_DnsAlias) {\n $Cert_Params += @{DnsAlias = @($LE_AzureDNS_DnsAlias, $LE_AzureDNS_DnsAlias)} # Adding the value twice to avoid the warning \"Fewer DnsAlias values than names in the order.\"\n }\n\n return New-PACertificate @Cert_Params\n }\n catch {\n Write-Host \"Failed to Create Certificate. Error Message: $($_.Exception.Message). See Debug output for details.\"\n Write-Debug (Get-WebRequestErrorBody -RequestError $_)\n exit 1\n }\n}\n\nfunction Get-OctopusCertificates {\n Write-Debug \"Entering: Get-OctopusCertificates\"\n\n $octopus_uri = $OctopusParameters[\"Octopus.Web.ServerUri\"]\n $octopus_space_id = $OctopusParameters[\"Octopus.Space.Id\"]\n $octopus_headers = @{ \"X-Octopus-ApiKey\" = $OctopusParameters[\"LE_AzureDNS_Octopus_APIKey\"] }\n $octopus_certificates_uri = \"$octopus_uri/api/$octopus_space_id/certificates?search=$($LE_AzureDNS_CertificateDomain)\"\n\n try {\n # Get a list of certificates that match our domain search criteria.\n $certificates_search = Invoke-WebRequest -Uri $octopus_certificates_uri -Method Get -Headers $octopus_headers -UseBasicParsing -ErrorAction Stop | ConvertFrom-Json | Select-Object -ExpandProperty Items\n\n # We don't want to confuse Production and Staging Lets Encrypt Certificates.\n $use_staging = ($OctopusParameters[\"LE_AzureDNS_Use_Staging\"] -eq $True)\n\n return $certificates_search | Where-Object {\n $_.SubjectCommonName -eq $LE_AzureDNS_CertificateDomain -and\n (Test-IsLetsEncryptIssuer -Certificate $_ -Staging $use_staging) -and\n $null -eq $_.ReplacedBy -and\n $null -eq $_.Archived\n }\n }\n catch {\n Write-Host \"Could not retrieve certificates from Octopus Deploy. Error: $($_.Exception.Message). See Debug output for details.\"\n Write-Debug (Get-WebRequestErrorBody -RequestError $_)\n exit 1\n }\n}\n\nfunction Publish-OctopusCertificate {\n param (\n [string] $JsonBody\n )\n\n Write-Debug \"Entering: Publish-OctopusCertificate\"\n\n if (-not ($JsonBody)) {\n Write-Host \"Existing Certificate is required.\"\n exit 1\n }\n\n $octopus_uri = $OctopusParameters[\"Octopus.Web.ServerUri\"]\n $octopus_space_id = $OctopusParameters[\"Octopus.Space.Id\"]\n $octopus_headers = @{ \"X-Octopus-ApiKey\" = $OctopusParameters[\"LE_AzureDNS_Octopus_APIKey\"] }\n $octopus_certificates_uri = \"$octopus_uri/api/$octopus_space_id/certificates\"\n\n try {\n Invoke-WebRequest -Uri $octopus_certificates_uri -Method Post -Headers $octopus_headers -Body $JsonBody -UseBasicParsing\n Write-Host \"Published $($LE_AzureDNS_CertificateDomain) certificate to the Octopus Deploy Certificate Store.\"\n }\n catch {\n Write-Host \"Failed to publish $($LE_AzureDNS_CertificateDomain) certificate. Error: $($_.Exception.Message). See Debug output for details.\"\n Write-Debug (Get-WebRequestErrorBody -RequestError $_)\n exit 1\n }\n}\n\nfunction Update-OctopusCertificate {\n param (\n [string]$Certificate_Id,\n [string]$JsonBody\n )\n\n Write-Debug \"Entering: Update-OctopusCertificate\"\n\n if (-not ($Certificate_Id -and $JsonBody)) {\n Write-Host \"Existing Certificate Id and a replace Certificate are required.\"\n exit 1\n }\n\n $octopus_uri = $OctopusParameters[\"Octopus.Web.ServerUri\"]\n $octopus_space_id = $OctopusParameters[\"Octopus.Space.Id\"]\n $octopus_headers = @{ \"X-Octopus-ApiKey\" = $OctopusParameters[\"LE_AzureDNS_Octopus_APIKey\"] }\n $octopus_certificates_uri = \"$octopus_uri/api/$octopus_space_id/certificates/$Certificate_Id/replace\"\n\n try {\n Invoke-WebRequest -Uri $octopus_certificates_uri -Method Post -Headers $octopus_headers -Body $JsonBody -UseBasicParsing\n Write-Host \"Replaced $($LE_AzureDNS_CertificateDomain) certificate in the Octopus Deploy Certificate Store.\"\n }\n catch {\n Write-Error \"Failed to replace $($LE_AzureDNS_CertificateDomain) certificate. Error: $($_.Exception.Message)\"\n exit 1\n }\n}\n\nfunction Get-NewCertificatePFXAsJson {\n param (\n $Certificate\n )\n\n Write-Debug \"Entering: Get-NewCertificatePFXAsJson\"\n\n if (-not ($Certificate)) {\n Write-Host \"Certificate is required.\"\n Exit 1\n }\n\n [Byte[]]$certificate_buffer = [System.IO.File]::ReadAllBytes($Certificate.PfxFullChain)\n $certificate_base64 = [convert]::ToBase64String($certificate_buffer)\n\n $certificate_body = @{\n Name = \"$LE_AzureDNS_CertificateName\";\n Notes = \"\";\n CertificateData = @{\n HasValue = $true;\n NewValue = $certificate_base64;\n };\n Password = @{\n HasValue = $true;\n NewValue = $OctopusParameters[\"LE_AzureDNS_PfxPassword\"];\n };\n }\n\n return $certificate_body | ConvertTo-Json\n}\n\nfunction Get-ReplaceCertificatePFXAsJson {\n param (\n $Certificate\n )\n\n Write-Debug \"Entering: Get-ReplaceCertificatePFXAsJson\"\n\n if (-not ($Certificate)) {\n Write-Host \"Certificate is required.\"\n Exit 1\n }\n\n [Byte[]]$certificate_buffer = [System.IO.File]::ReadAllBytes($Certificate.PfxFullChain)\n $certificate_base64 = [convert]::ToBase64String($certificate_buffer)\n\n $certificate_body = @{\n CertificateData = $certificate_base64;\n Password = $OctopusParameters[\"LE_AzureDNS_PfxPassword\"];\n }\n\n return $certificate_body | ConvertTo-Json\n}\n\n###############################################################################\n# DO THE THING | MAIN |\n###############################################################################\nWrite-Debug \"Do the Thing\"\n\nWrite-Host \"Checking for existing Lets Encrypt Certificates in the Octopus Deploy Certificates Store.\"\n$certificates = Get-OctopusCertificates\n\n# Check for PFX & PEM\nif ($certificates) {\n\n # Handle weird behavior between Powershell 5 and Powershell 6+\n $certificate_count = 1\n if ($certificates.Count -ge 1) {\n $certificate_count = $certificates.Count\n }\n\n Write-Host \"Found $certificate_count for $($LE_AzureDNS_CertificateDomain).\"\n Write-Host \"Checking to see if any expire within $($OctopusParameters[\"LE_AzureDNS_ReplaceIfExpiresInDays\"]) days.\"\n\n # Check Expiry Dates\n $expiring_certificates = $certificates | Where-Object { [DateTime]$_.NotAfter -lt (Get-Date).AddDays($OctopusParameters[\"LE_AzureDNS_ReplaceIfExpiresInDays\"]) }\n\n if ($expiring_certificates) {\n Write-Host \"Found certificates that expire with $($OctopusParameters[\"LE_AzureDNS_ReplaceIfExpiresInDays\"]) days. Requesting new certificates for $($LE_AzureDNS_CertificateDomain) from Lets Encrypt\"\n $le_certificate = Get-LetsEncryptCertificate\n\n # PFX\n $existing_certificate = $expiring_certificates | Where-Object { $_.CertificateDataFormat -eq \"Pkcs12\" } | Sort-Object { [DateTime]$_.NotAfter } | Select-Object -First 1\n Write-Host \"Replacing certificate $($existing_certificate.Id), which expires $(([DateTime]$existing_certificate.NotAfter).ToString('u')).\"\n $certificate_as_json = Get-ReplaceCertificatePFXAsJson -Certificate $le_certificate\n Update-OctopusCertificate -Certificate_Id $existing_certificate.Id -JsonBody $certificate_as_json\n }\n else {\n Write-Host \"Nothing to do here...\"\n }\n\n exit 0\n}\n\n# No existing Certificates - Lets get some new ones.\nWrite-Host \"No existing certificates found for $($LE_AzureDNS_CertificateDomain).\"\nWrite-Host \"Request New Certificate for $($LE_AzureDNS_CertificateDomain) from Lets Encrypt\"\n\n# New Certificate..\n$le_certificate = Get-LetsEncryptCertificate\n\nWrite-Host \"Publishing: LetsEncrypt - $($LE_AzureDNS_CertificateDomain) (PFX)\"\n$certificate_as_json = Get-NewCertificatePFXAsJson -Certificate $le_certificate\nPublish-OctopusCertificate -JsonBody $certificate_as_json\n\nWrite-Host \"GREAT SUCCESS\"\n",
"Octopus.Action.SubstituteInFiles.Enabled": "True"
},
"Category": "Lets Encrypt",
"HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates/letsencrypt-azure-dns.json",
"Website": "/step-templates/79e0dd12-6222-4f8a-a8dc-bcbe579ed729",
"Logo": "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",
"$Meta": {
"Type": "ActionTemplate"
}
}
Page updated on Wednesday, August 12, 2026