Octopus.Script exported 2022-11-14 by twerthi belongs to ‘Octopus’ category.
Create or replace an Octopus Certificate from a certificate file
Parameters
When steps based on the template are included in a project’s deployment process, the parameters below can be set.
Octopus Url
StepTemplate_OctopusUrl = #{if Octopus.Web.ServerUri}#{Octopus.Web.ServerUri}#{else}#{Octopus.Web.BaseUrl}#{/if}
Provide the URL of your Octopus Server. The default is #{if Octopus.Web.ServerUri}#{Octopus.Web.ServerUri}#{else}#{Octopus.Web.BaseUrl}#{/if}
. Cloud instances should use Octopus.Web.ServerUri
. See System Variables - Server for more info.
API Key
StepTemplate_ApiKey =
Provide an Octopus API Key with appropriate permissions to save the certificate.
Certificate Name
StepTemplate_CertificateName =
A short, memorable, unique name for this certificate.
If the certificate already exists it will be replaced.
Certificate Encoding
StepTemplate_CertEncoding = file
Defines the format of the Certificate parameter.
Certificate
StepTemplate_Certificate =
The certificate to import into Octopus, either as a File Path to the certificate, or as a Base64 Encoded String representation depending on the Certificate Encoding chosen.
Supported formats: PFX (PKCS #12), DER, PEM
Password
StepTemplate_Password =
The password protecting the certificate (if required).
Environments
StepTemplate_Environments =
Comma-delimited list of environments to restrict certificate to. A blank value will not restrict the certificate.
Tenant Participation
StepTemplate_TenantParticipation = untenanted
Select the tenant participation level.
Tenants
StepTemplate_Tenants =
Comma-delimited list of tenants that can use this certificate. Used with Tenant Participation
values of Tenanted
or Tenanted or untenanted
.
Tenant Tags
StepTemplate_TenantTags =
Comma-delimited list of tenant tags to apply to the certificate.
Script body
Steps based on this template will execute the following PowerShell script.
<#
----- Octopus - Import Certificate -----
Paul Marston @paulmarsy (paul@marston.me)
Links
https://github.com/OctopusDeploy/Library/commits/master/step-templates/octopus-import-certificate.json
#>
$securityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12
[Net.ServicePointManager]::SecurityProtocol = $securityProtocol
$ErrorActionPreference = 'Stop'
$StepTemplate_BaseUrl = $StepTemplate_OctopusUrl.Trim('/')
if ([string]::IsNullOrWhiteSpace($StepTemplate_ApiKey)) {
throw "The step parameter 'API Key' was not found. This step requires an API Key to function, please provide one and try again."
}
filter Out-Verbose {
Write-Verbose ($_ | Out-String)
}
filter Out-Indented {
$_ | Out-String | % Trim | % Split "`n" | % { "`t$_" }
}
function Invoke-OctopusApi {
param(
[Parameter(Position = 0, Mandatory)]$Uri,
[ValidateSet("Get", "Post")]$Method = 'Get',
$Body
)
$requestParameters = @{
Uri = ('{0}/{1}' -f $StepTemplate_BaseUrl, $Uri.TrimStart('/'))
Method = $Method
Headers = @{ "X-Octopus-ApiKey" = $StepTemplate_ApiKey }
UseBasicParsing = $true
}
Write-Verbose "$($Method.ToUpperInvariant()) $($requestParameters.Uri)"
if ($null -ne $Body) { $requestParameters.Add('Body', ($Body | ConvertTo-Json -Depth 10)) }
try {
Invoke-WebRequest @requestParameters | % Content | ConvertFrom-Json | Write-Output
}
catch [System.Net.WebException] {
if ($_.Exception.Response) {
$errorResponse = [System.IO.StreamReader]::new($_.Exception.Response.GetResponseStream()).ReadToEnd()
throw ("$($_.Exception.Message)`n{0}" -f $errorResponse)
}
if ($_.Exception.Message) {
$message = $_.Exception.Message
Write-Highlight $message
throw "$message"
}
}
}
function Test-SpacesApi {
Write-Verbose "Checking API compatibility";
$rootDocument = Invoke-OctopusApi 'api/';
if($rootDocument.Links -ne $null -and $rootDocument.Links.Spaces -ne $null) {
Write-Verbose "Spaces API found"
return $true;
}
Write-Verbose "Pre-spaces API found"
return $false;
}
function Get-OctopusItems
{
# Define parameters
param(
$OctopusUri,
$ApiKey,
$SkipCount = 0
)
# Define working variables
$items = @()
$skipQueryString = ""
$headers = @{"X-Octopus-ApiKey"="$ApiKey"}
# Check to see if there there is already a querystring
if ($octopusUri.Contains("?"))
{
$skipQueryString = "&skip="
}
else
{
$skipQueryString = "?skip="
}
$skipQueryString += $SkipCount
# Get intial set
$resultSet = Invoke-RestMethod -Uri "$($OctopusUri)$skipQueryString" -Method GET -Headers $headers
# Check to see if it returned an item collection
if ($resultSet.Items)
{
# Store call results
$items += $resultSet.Items
# Check to see if resultset is bigger than page amount
if (($resultSet.Items.Count -gt 0) -and ($resultSet.Items.Count -eq $resultSet.ItemsPerPage))
{
# Increment skip count
$SkipCount += $resultSet.ItemsPerPage
# Recurse
$items += Get-OctopusItems -OctopusUri $OctopusUri -ApiKey $ApiKey -SkipCount $SkipCount
}
}
else
{
return $resultSet
}
# Return results
return $items
}
function Get-OctopusIds
{
# Define parameters
param (
$OctopusCollection,
$NamesArray
)
$returnList = @()
foreach ($item in $NamesArray)
{
# Trim item
$item = $item.Trim()
# Compare
$octopusItem = $OctopusCollection | Where-Object {$_.Name -eq $item}
if ($null -ne $octopusItem)
{
# Add to array
$returnList += $item.Id
}
}
# Return list
return $returnList
}
if(Test-SpacesApi) {
$spaceId = $OctopusParameters['Octopus.Space.Id'];
if([string]::IsNullOrWhiteSpace($spaceId)) {
throw "This step needs to be run in a context that provides a value for the 'Octopus.Space.Id' system variable. In this case, we received a blank value, which isn't expected - please reach out to our support team at https://help.octopus.com if you encounter this error.";
}
$baseApiUrl = "/api/$spaceId" ;
} else {
$baseApiUrl = "/api" ;
}
# Get all environments
Write-Host "Getting list of Environments ...$($StepTemplate_BaseUrl)$($baseApiUrl)/environments"
$environmentList = Get-OctopusItems -OctopusUri "$($StepTemplate_BaseUrl)$($baseApiUrl)/environments" -ApiKey $StepTemplate_ApiKey
$environmentIds = Get-OctopusIds -OctopusCollection $environmentList -NamesArray $StepTemplate_Environments.Split(",")
# Get tenants
Write-Host "Getting list of Tenants ..."
$tenantList = Get-OctopusItems -OctopusUri "$($StepTemplate_BaseUrl)$($baseApiUrl)/tenants" -ApiKey $StepTemplate_ApiKey
$tenantIds = Get-OctopusIds -OctopusCollection $tenantList -NamesArray $StepTemplate_Tenants.Split(",")
# Get tenant tags
Write-Host "Getting list of Tenant Tags ..."
$tenantTagList = Get-OctopusItems -OctopusUri "$($StepTemplate_BaseUrl)$($baseApiUrl)/tagsets" -ApiKey $StepTemplate_ApiKey
$tenantTagIds = Get-OctopusIds -OctopusCollection $tenantTagList -NamesArray $StepTemplate_TenantTags.Split(",")
$certificate = switch ($StepTemplate_CertEncoding) {
'file' {
if (!(Test-Path $StepTemplate_Certificate)) {
throw "Certificate file $StepTemplate_Certificate does not exist"
}
$certificateBytes = Get-Content -Path $StepTemplate_Certificate -Encoding Byte
[System.Convert]::ToBase64String($certificateBytes)
}
'base64' {
$StepTemplate_Certificate
}
}
$existingCert = Invoke-OctopusApi "$baseApiUrl/certificates" | % Items | ? Name -eq $StepTemplate_CertificateName
if ($existingCert) {
Write-Host 'Existing certificate will be archived & replaced...'
Invoke-OctopusApi ("$baseApiUrl/certificates/{0}/replace" -f $existingCert.Id) -Method Post -Body @{
certificateData = $certificate
password = $StepTemplate_Password
} | % {
$_.CertificateData = $null
$_.Password = $null
$_
} | Out-Verbose
} else {
Write-Host 'Creating & importing new certificate...'
Invoke-OctopusApi "$baseApiUrl/certificates" -Method Post -Body @{
Name = $StepTemplate_CertificateName
CertificateData = @{
HasValue = $true
NewValue = $certificate
}
Password = @{
HasValue = $true
NewValue = $StepTemplate_Password
}
TenantedDeploymentParticipation = $StepTemplate_TenantParticipation
EnvironmentIds = $environmentIds
TenantIds = $tenantIds
TenantTags = $tenantTagIds
} | Out-Verbose
}
Write-Host 'Certificate has been imported:'
Invoke-OctopusApi "$baseApiUrl/certificates" | % Items | ? Name -eq $StepTemplate_CertificateName | Out-Indented
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": "3b1f6c62-c2cb-480b-9b14-435686b9f2cc",
"Name": "Octopus - Import Certificate",
"Description": "Create or replace an [Octopus Certificate](https://octopus.com/docs/deploying-applications/certificates) from a certificate file",
"Version": 5,
"ExportedAt": "2022-11-14T23:22:38.482Z",
"ActionType": "Octopus.Script",
"Author": "twerthi",
"Parameters": [
{
"Id": "6a723531-1272-4c7f-ae04-9576051396ad",
"Name": "StepTemplate_OctopusUrl",
"Label": "Octopus Url",
"HelpText": "Provide the URL of your Octopus Server. The default is `#{if Octopus.Web.ServerUri}#{Octopus.Web.ServerUri}#{else}#{Octopus.Web.BaseUrl}#{/if}`. Cloud instances should use `Octopus.Web.ServerUri`. See [System Variables - Server](https://octopus.com/docs/projects/variables/system-variables#Systemvariables-Server) for more info.",
"DefaultValue": "#{if Octopus.Web.ServerUri}#{Octopus.Web.ServerUri}#{else}#{Octopus.Web.BaseUrl}#{/if}",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "9a84f62c-99f7-4349-bf6d-f42397f4de73",
"Name": "StepTemplate_ApiKey",
"Label": "API Key",
"HelpText": "Provide an Octopus API Key with appropriate permissions to save the certificate.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "Sensitive"
},
"Links": {}
},
{
"Id": "4fcb5ddf-14a9-42b1-8e77-d8d68e69b2fe",
"Name": "StepTemplate_CertificateName",
"Label": "Certificate Name",
"HelpText": "A short, memorable, unique name for this certificate.\n\nIf the certificate already exists it [will be replaced](https://octopus.com/docs/deployments/certificates/replace-certificate).",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
},
"Links": {}
},
{
"Id": "0664b204-c11e-47d1-b388-58ef0b0a7b1a",
"Name": "StepTemplate_CertEncoding",
"Label": "Certificate Encoding",
"HelpText": "Defines the format of the **Certificate** parameter.",
"DefaultValue": "file",
"DisplaySettings": {
"Octopus.ControlType": "Select",
"Octopus.SelectOptions": "file|File Path\nbase64|Base64 Encoded String"
},
"Links": {}
},
{
"Id": "df336e72-328a-4bad-92b1-374155ec3fb4",
"Name": "StepTemplate_Certificate",
"Label": "Certificate",
"HelpText": "The certificate to import into Octopus, either as a **File Path** to the certificate, or as a **Base64 Encoded String** representation depending on the _Certificate Encoding_ chosen.\n\nSupported formats: [PFX (PKCS #12), DER, PEM](https://octopus.com/docs/deployments/certificates)",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "MultiLineText"
},
"Links": {}
},
{
"Id": "b875e962-5edc-44e8-be03-51f8a87eca5d",
"Name": "StepTemplate_Password",
"Label": "Password",
"HelpText": "The password protecting the certificate (if required).",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "Sensitive"
},
"Links": {}
},
{
"Id": "9d87e43f-d17a-40ea-affc-a3755f1cc16a",
"Name": "StepTemplate_Environments",
"Label": "Environments",
"HelpText": "Comma-delimited list of environments to restrict certificate to. A blank value will not restrict the certificate.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "014474f8-d7a2-4d67-b57f-364ba723ece2",
"Name": "StepTemplate_TenantParticipation",
"Label": "Tenant Participation",
"HelpText": "Select the tenant participation level.",
"DefaultValue": "untenanted",
"DisplaySettings": {
"Octopus.ControlType": "Select",
"Octopus.SelectOptions": "untenanted|Untenanted\ntenanted|Tenanted\ntenantedoruntenanted|Tenanted or untenanted"
}
},
{
"Id": "bf9a1f70-0c67-4070-b4ff-e38f159ff701",
"Name": "StepTemplate_Tenants",
"Label": "Tenants",
"HelpText": "Comma-delimited list of tenants that can use this certificate. Used with `Tenant Participation` values of `Tenanted` or `Tenanted or untenanted`.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "e041fbd8-66da-4b6a-ae3e-90d20f110a48",
"Name": "StepTemplate_TenantTags",
"Label": "Tenant Tags",
"HelpText": "Comma-delimited list of tenant tags to apply to the certificate.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
}
],
"Properties": {
"Octopus.Action.Script.Syntax": "PowerShell",
"Octopus.Action.Script.ScriptSource": "Inline",
"Octopus.Action.RunOnServer": "false",
"Octopus.Action.Script.ScriptBody": "\n\n<#\n ----- Octopus - Import Certificate ----- \n Paul Marston @paulmarsy (paul@marston.me)\nLinks\n https://github.com/OctopusDeploy/Library/commits/master/step-templates/octopus-import-certificate.json\n#>\n\n$securityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12\n[Net.ServicePointManager]::SecurityProtocol = $securityProtocol\n\n$ErrorActionPreference = 'Stop'\n\n$StepTemplate_BaseUrl = $StepTemplate_OctopusUrl.Trim('/')\n\nif ([string]::IsNullOrWhiteSpace($StepTemplate_ApiKey)) {\n throw \"The step parameter 'API Key' was not found. This step requires an API Key to function, please provide one and try again.\"\n}\nfilter Out-Verbose {\n Write-Verbose ($_ | Out-String)\n}\nfilter Out-Indented {\n $_ | Out-String | % Trim | % Split \"`n\" | % { \"`t$_\" } \n}\nfunction Invoke-OctopusApi {\n param(\n [Parameter(Position = 0, Mandatory)]$Uri,\n [ValidateSet(\"Get\", \"Post\")]$Method = 'Get',\n $Body\n )\n $requestParameters = @{\n Uri = ('{0}/{1}' -f $StepTemplate_BaseUrl, $Uri.TrimStart('/'))\n Method = $Method\n Headers = @{ \"X-Octopus-ApiKey\" = $StepTemplate_ApiKey }\n UseBasicParsing = $true\n }\n Write-Verbose \"$($Method.ToUpperInvariant()) $($requestParameters.Uri)\" \n if ($null -ne $Body) { $requestParameters.Add('Body', ($Body | ConvertTo-Json -Depth 10)) }\n try {\n Invoke-WebRequest @requestParameters | % Content | ConvertFrom-Json | Write-Output\n }\n catch [System.Net.WebException] {\n if ($_.Exception.Response) {\n $errorResponse = [System.IO.StreamReader]::new($_.Exception.Response.GetResponseStream()).ReadToEnd()\n throw (\"$($_.Exception.Message)`n{0}\" -f $errorResponse)\n }\n \n if ($_.Exception.Message) {\n \t$message = $_.Exception.Message\n \tWrite-Highlight $message\n throw \"$message\"\n }\n }\n}\n\nfunction Test-SpacesApi {\n\tWrite-Verbose \"Checking API compatibility\";\n\t$rootDocument = Invoke-OctopusApi 'api/';\n if($rootDocument.Links -ne $null -and $rootDocument.Links.Spaces -ne $null) {\n \tWrite-Verbose \"Spaces API found\"\n \treturn $true;\n }\n Write-Verbose \"Pre-spaces API found\"\n return $false;\n}\n\nfunction Get-OctopusItems\n{\n\t# Define parameters\n param(\n \t$OctopusUri,\n $ApiKey,\n $SkipCount = 0\n )\n \n # Define working variables\n $items = @()\n $skipQueryString = \"\"\n $headers = @{\"X-Octopus-ApiKey\"=\"$ApiKey\"}\n\n # Check to see if there there is already a querystring\n if ($octopusUri.Contains(\"?\"))\n {\n $skipQueryString = \"&skip=\"\n }\n else\n {\n $skipQueryString = \"?skip=\"\n }\n\n $skipQueryString += $SkipCount\n \n # Get intial set\n $resultSet = Invoke-RestMethod -Uri \"$($OctopusUri)$skipQueryString\" -Method GET -Headers $headers\n\n # Check to see if it returned an item collection\n if ($resultSet.Items)\n {\n # Store call results\n $items += $resultSet.Items\n \n # Check to see if resultset is bigger than page amount\n if (($resultSet.Items.Count -gt 0) -and ($resultSet.Items.Count -eq $resultSet.ItemsPerPage))\n {\n # Increment skip count\n $SkipCount += $resultSet.ItemsPerPage\n\n # Recurse\n $items += Get-OctopusItems -OctopusUri $OctopusUri -ApiKey $ApiKey -SkipCount $SkipCount\n }\n }\n else\n {\n return $resultSet\n }\n \n\n # Return results\n return $items\n}\n\nfunction Get-OctopusIds \n{\n\t# Define parameters\n param (\n \t$OctopusCollection,\n $NamesArray\n )\n \n $returnList = @()\n \n foreach ($item in $NamesArray)\n {\n \t# Trim item\n $item = $item.Trim()\n \n # Compare\n $octopusItem = $OctopusCollection | Where-Object {$_.Name -eq $item}\n \n if ($null -ne $octopusItem)\n {\n \t# Add to array\n $returnList += $item.Id\n }\n }\n \n # Return list\n return $returnList\n}\n\nif(Test-SpacesApi) {\n\t$spaceId = $OctopusParameters['Octopus.Space.Id'];\n if([string]::IsNullOrWhiteSpace($spaceId)) {\n throw \"This step needs to be run in a context that provides a value for the 'Octopus.Space.Id' system variable. In this case, we received a blank value, which isn't expected - please reach out to our support team at https://help.octopus.com if you encounter this error.\";\n }\n\t$baseApiUrl = \"/api/$spaceId\" ;\n} else {\n\t$baseApiUrl = \"/api\" ;\n}\n\n# Get all environments\nWrite-Host \"Getting list of Environments ...$($StepTemplate_BaseUrl)$($baseApiUrl)/environments\"\n$environmentList = Get-OctopusItems -OctopusUri \"$($StepTemplate_BaseUrl)$($baseApiUrl)/environments\" -ApiKey $StepTemplate_ApiKey\n$environmentIds = Get-OctopusIds -OctopusCollection $environmentList -NamesArray $StepTemplate_Environments.Split(\",\")\n\n# Get tenants\nWrite-Host \"Getting list of Tenants ...\"\n$tenantList = Get-OctopusItems -OctopusUri \"$($StepTemplate_BaseUrl)$($baseApiUrl)/tenants\" -ApiKey $StepTemplate_ApiKey\n$tenantIds = Get-OctopusIds -OctopusCollection $tenantList -NamesArray $StepTemplate_Tenants.Split(\",\")\n\n# Get tenant tags\nWrite-Host \"Getting list of Tenant Tags ...\"\n$tenantTagList = Get-OctopusItems -OctopusUri \"$($StepTemplate_BaseUrl)$($baseApiUrl)/tagsets\" -ApiKey $StepTemplate_ApiKey\n$tenantTagIds = Get-OctopusIds -OctopusCollection $tenantTagList -NamesArray $StepTemplate_TenantTags.Split(\",\")\n\n$certificate = switch ($StepTemplate_CertEncoding) {\n 'file' { \n if (!(Test-Path $StepTemplate_Certificate)) {\n throw \"Certificate file $StepTemplate_Certificate does not exist\"\n }\n $certificateBytes = Get-Content -Path $StepTemplate_Certificate -Encoding Byte\n [System.Convert]::ToBase64String($certificateBytes)\n }\n 'base64' {\n $StepTemplate_Certificate\n }\n}\n\n$existingCert = Invoke-OctopusApi \"$baseApiUrl/certificates\" | % Items | ? Name -eq $StepTemplate_CertificateName\nif ($existingCert) {\n Write-Host 'Existing certificate will be archived & replaced...'\n Invoke-OctopusApi (\"$baseApiUrl/certificates/{0}/replace\" -f $existingCert.Id) -Method Post -Body @{\n certificateData = $certificate\n password = $StepTemplate_Password\n } | % {\n $_.CertificateData = $null\n $_.Password = $null\n $_\n } | Out-Verbose\n} else {\n Write-Host 'Creating & importing new certificate...'\n Invoke-OctopusApi \"$baseApiUrl/certificates\" -Method Post -Body @{\n Name = $StepTemplate_CertificateName\n CertificateData = @{\n HasValue = $true\n NewValue = $certificate\n }\n Password = @{\n HasValue = $true\n NewValue = $StepTemplate_Password\n }\n TenantedDeploymentParticipation = $StepTemplate_TenantParticipation\n EnvironmentIds = $environmentIds\n TenantIds = $tenantIds\n TenantTags = $tenantTagIds\n } | Out-Verbose\n}\nWrite-Host 'Certificate has been imported:'\nInvoke-OctopusApi \"$baseApiUrl/certificates\" | % Items | ? Name -eq $StepTemplate_CertificateName | Out-Indented",
"Octopus.Action.Script.ScriptFileName": null,
"Octopus.Action.Package.FeedId": null,
"Octopus.Action.Package.PackageId": null
},
"Category": "Octopus",
"HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates//opt/buildagent/work/75443764cd38076d/step-templates/octopus-import-certificate.json",
"Website": "/step-templates/3b1f6c62-c2cb-480b-9b14-435686b9f2cc",
"Logo": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAC1QTFRFT6Tl////L5Pg8vj9Y67omsvwPJrisdfzfbzs5fL7y+T32Ov5isLucLXqvt31CJPHWwAABMJJREFUeNrs3deW4jAMAFDF3U75/89dlp0ZhiU4blJEjvQ8hYubLJsA00UCBCIQgQhEIAIRiEAEIhCBCEQgAhGIQAQiEIEIhD8kJm+t+QprfdKfB9HbYpx6CWfspj8HMi+gMgHL/AmQA8W3JTKH+ALFvzCeL0RbpyoCPE9IJeNOSQwh5Z3qd6yRGWQ2qi2cZQWxqj1WzQYSjeoJmJlAklOd4VlArOqPhQEkqBERToeMcfRJBkC0Uep8CfBpjz4JsHJ0zF3dkEWNje0kiB/sUC6eApndaIiCMyAa1PiwJ0AWhRGJHJJQHG2dC7h1rNbO1QOxSA7lNCkkKrQIpJCAB1GREILYIC1NAiwbpKFJgGWDNExcwGstfExcZBCHC6nOglshHtmhViLIig1RNBCN7qjtW8C0Z1UvJcC1Z9XmwMBzzvobmgAyEzgq91dtEEsBsQSQQAFZCSBAATEEEApHZbrVBIkkEIUPSVeB+KtALA0kXQUSrwKZBCIQBnk8Y4i5CsReBeKvkqLM+BCSDWJlrZFvGk9SRTHshkgjZCGAaArIxm3H3grhVzFlW2msfl1ca79UJ1bofYvsDHHlNdTZnlh5MghuPd5NdBDUNZHyCkfktIh03XzALGRPlBDPac7qgWjHZzWcmF5zmmkhidMQ6boKiDXcDTUEaylZqCGJ0Vjvu/fLJtHqhSANEvqb2OYqkOUqEHuVMbJcZdZCGiPhKhC4yjqiIjEE7XThMp8fAWII3mY3kUIQD+AMKQTzPiBhgQ63HlT/KSvgtoi0dq5mCPah1UIE0eh3sT0NhOByvKeAkFzi8PgQomumFhsyOxpIzZN4gLOj5plVwNpR0b2AuePWKBEHQu24pSsJA+LVCeHHQxZ1SiyDIdqok8IOhSSnTottHEQTdyt4ettAj4KkzA4dMikk2Dht2S5ptm1vswnPDxn0YyDZ5oDM3iToo2T5voWaYe+Q+vdjH80QyAzZhCgcDtLMI1Tmtz9w++XHgziHQHJJu/OZ3bs9Xn8gQ72NcP3dKqEfkp10F51xhoIi2I91R+LurXV/5q7pH+wx061CzO16oSQleMyr8fXvwMA0Pro8432DPD/ySx8XrHfSuDAM8n6UhnjQabaiXf5Bq/lREHvEeNtn1rJ08+C/uXkQZHeguxAPC3UvtcJYUogLzZX5hhZZvS6onG5lxXtzWGaygwb79vT/IXhdlNibwlKYOR6T8xjI7W8n+xV7T+GH4tMzWwR+lZhRkJYSsC0thpmCYqyngOz3rN2FLBZ2wZflBCggUHF0Vnp88JKienzIXLSEZCZqU7IKr/gQW9yx3pzV7Y9kvWZWTRRIqDmTtRUnU7b2lLcTYmoqHqnmiO1poER0SPkAeZMAZxaJx0Y3TCdAclsIqDz03ALcyxfTCZBsthoGXWmigGyVhWPLFJJfuuKQWycoEFdXbH4dJJoJxNR1eD/kshz6yn48cF8yW8sFoitflB1w6Q8n+/15Za7oA17/pYNmYgP5fmWm8L1NOHPWgK8kuFew1/JXtOA0yJCv7ah7X8ObUuT5kObU30+fDZm8+zqP+HTIpK0xQ796b5Kv2hSIQAQiEIEIRCACEYhABCIQgQhEIAIRiEAEIpBf8UeAAQAEjtYmlDTcCgAAAABJRU5ErkJggg==",
"$Meta": {
"Type": "ActionTemplate"
}
}
Page updated on Monday, November 14, 2022