Octopus - Import Certificate

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.

Report an issue

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

{
  "Id": "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"
  }
}

History

Page updated on Monday, November 14, 2022