Octopus.Script exported 2024-06-12 by idimov-keeper belongs to ‘Keeper Secrets Manager’ category.
This step retrieves one or more secrets from a Keeper Vault and creates sensitive output variables for each value retrieved. These values can be used in other steps in your deployment or runbook process.
You can retrieve secrets using Keeper Notation URIs, and you can choose a custom output variable name for each secret.
Required:
- A Keeper Secrets Manager application with permissions to retrieve secrets from the Keeper Vault.
- The
SecretManagement.Keeper.Extension
PowerShell module installed on the target or worker. If the module can’t be found, the step will fail. TheSecretManagement.Keeper
module(s) can be installed from the PowerShell gallery
Notes:
- Tested on Octopus
2022.4
. - 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.
Keeper Secrets Manager Configuration
Keeper.SecretsManager.RetrieveSecrets.Config =
Keeper Secrets Manager configuration for KSM Application with permissions to retrieve secrets from the Keeper Vault. To generate KSM Configuration in Web Vault: Secrets Manager - KSM Application Name - Devices - Edit - Add Device, and switch to Method: Configuration File, preferably in Base64 format
Vault Secrets to retrieve
Keeper.SecretsManager.RetrieveSecrets.VaultSecrets =
Use Secrets Manager Notation URIs to specify the Secrets to be returned from Keeper Vault, in the format SecretsManagerNotation URI | OutputVariableName
where:
OutputVariableName
is the optional Octopus output variable name to store the secret’s value in. If this value isn’t specified, an output name will be generated dynamically.
Note: Multiple fields can be retrieved by entering each one on a new line.
Print output variable names
Keeper.SecretsManager.RetrieveSecrets.PrintVariableNames = False
Write out the Octopus output variable names to the task log. Default: False
.
SecretManagement.Keeper.Extension PowerShell Module version (optional)
Keeper.SecretsManager.RetrieveSecrets.KsmModule.SpecificVersion =
If you wish to use a specific version of the SecretManagement.Keeper.Extension
PowerShell module (rather than the default), enter the version number here. e.g. 16.5.0
.
Note: The version specified must exist on the machine. Version 16.5.0 is the lowest supported version
SecretManagement.Keeper.Extension PowerShell Install Location (optional)
Keeper.SecretsManager.RetrieveSecrets.KsmModule.CustomInstallLocation =
If you wish to provide a custom path to the SecretManagement.Keeper.Extension
PowerShell module (rather than the default), enter the value here.
Note: The Module must exist at the specified location on the machine. This step template will not download the Module.
Script body
Steps based on this template will execute the following PowerShell script.
$ErrorActionPreference = 'Stop'
# Variables
$KsmModuleName = "SecretManagement.Keeper.Extension"
$KsmParentModuleName = "SecretManagement.Keeper"
$KsmConfig = $OctopusParameters["Keeper.SecretsManager.RetrieveSecrets.Config"]
$VaultSecrets = $OctopusParameters["Keeper.SecretsManager.RetrieveSecrets.VaultSecrets"]
$KsmModuleSpecificVersion = $OctopusParameters["Keeper.SecretsManager.RetrieveSecrets.KsmModule.SpecificVersion"]
$KsmModuleCustomInstallLocation = $OctopusParameters["Keeper.SecretsManager.RetrieveSecrets.KsmModule.CustomInstallLocation"]
$PrintVariableNames = $OctopusParameters["Keeper.SecretsManager.RetrieveSecrets.PrintVariableNames"]
# Validation
if ([string]::IsNullOrWhiteSpace($VaultSecrets)) {
throw "Required parameter Keeper.SecretsManager.RetrieveSecrets.VaultSecrets not specified"
}
if ([string]::IsNullOrWhiteSpace($KsmModuleSpecificVersion) -eq $False) {
$requiredVersion = [Version]$KdmModuleSpecificVersion
}
# Cross-platform bits
$WindowsPowerShell = $True
if ($PSEdition -eq "Core") {
$WindowsPowerShell = $False
}
### Helper functions
function Get-Module-CrossPlatform {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $true, Position = 0)]
[string] $Name
)
$module = Get-Module -Name $Name -ListAvailable
if($WindowsPowerShell -eq $True -and $null -eq $module) {
$module = Get-InstalledModule -Name $Name
}
return $module
}
function Load-Module {
Param(
[Parameter(Mandatory = $true)][string] $name
)
$retVal = $true
if (!(Get-Module -Name $name)) {
$isAvailable = Get-Module -ListAvailable | where { $_.Name -eq $name }
if ($isAvailable) {
try {
Import-Module $name -ErrorAction SilentlyContinue
} catch {
$retVal = $false
}
} else {
$retVal = $false
}
}
return $retVal
}
$PowerShellModuleName = $KsmModuleName
# Check for Custom install location specified for KsmModule
if ([string]::IsNullOrWhiteSpace($KsmModuleCustomInstallLocation) -eq $false) {
if ((Test-Path $KsmModuleCustomInstallLocation -IsValid) -eq $false) {
throw "The path $KsmModuleCustomInstallLocation is not valid, please use a relative or absolute path."
}
$KsmModulesFolder = [System.IO.Path]::GetFullPath($KsmModuleCustomInstallLocation)
$LocalModules = (New-Item "$KsmModulesFolder" -ItemType Directory -Force).FullName
$env:PSModulePath = $LocalModules + [System.IO.Path]::PathSeparator + $env:PSModulePath
# Check to see if there
if ((Test-Path -Path "$LocalModules/$KsmModuleName") -eq $true)
{
# Use specific location
$PowerShellModuleName = "$LocalModules/$PowerShellModuleName"
}
}
# Import module
if([string]::IsNullOrWhiteSpace($KsmModuleSpecificVersion)) {
Write-Host "Importing module $PowerShellModuleName ..."
if ((Load-Module -Name $PowerShellModuleName) -eq $false) {
Write-Host "Extension module not found $PowerShellModuleName - trying to find sub-module in parent $KsmParentModuleName"
if (Get-Module -ListAvailable -Name $KsmParentModuleName) {
$KsmParentModuleDir = Split-Path -Path (Get-Module -ListAvailable -Name $KsmParentModuleName).Path
$KsmModuleFolder = [System.IO.Path]::GetFullPath($KsmParentModuleDir)
$LocalModules = (New-Item "$KsmModuleFolder" -ItemType Directory -Force).FullName
$env:PSModulePath = $LocalModules + [System.IO.Path]::PathSeparator + $env:PSModulePath
if ((Test-Path -Path "$LocalModules/$KsmModuleName") -eq $true)
{
$PowerShellModuleName = "$LocalModules/$PowerShellModuleName"
try {
Import-Module -Name $PowerShellModuleName -ErrorAction SilentlyContinue
Write-Host "Imported sub-module $PowerShellModuleName ..."
} catch {
Write-Host "Failed to import sub-module $PowerShellModuleName ..."
}
}
} else {
Write-Host "Module does not exist"
}
}
}
else {
Write-Host "Importing module $PowerShellModuleName ($KsmModuleSpecificVersion)..."
Import-Module -Name $PowerShellModuleName -RequiredVersion $requiredVersion
}
# Check if SecretManagement.Keeper.Extension Module is installed.
$ksmVaultModule = Get-Module-CrossPlatform -Name $KsmModuleName
if ($null -eq $ksmVaultModule) {
throw "Cannot find the '$KsmModuleName' module on the machine. If you think it is installed, try restarting the Tentacle service for it to be detected."
}
$Secrets = @()
$VariablesCreated = 0
$StepName = $OctopusParameters["Octopus.Step.Name"]
# Extract lines and split into notations and variables
$index = 0
$usedNames = @()
@(($VaultSecrets -Split "`n").Trim()) | ForEach-Object {
if (![string]::IsNullOrWhiteSpace($_)) {
Write-Verbose "Working on: '$_'"
# Split 'Notation | VariableName' and generate new var name if needed
$notation = $_
$variableName = ""
$n = $_.LastIndexOf("|")
if ($n -ge 0) {
if ($n -lt $notation.Length-1) {
$variableName = $notation.SubString($n+1).Trim()
}
$notation = $notation.SubString(0, $n).Trim()
}
if ([string]::IsNullOrWhiteSpace($variableName)) {
do {
$index++
$variableName = "KsmSecret" + $index
} while ($usedNames.Contains($variableName))
}
# Duplicate var - either overlapping KsmSecretN or another user variable
if($usedNames.Contains($variableName)) {
throw "Duplicate variable name: '$variableName'"
}
$usedNames += $variableName
if([string]::IsNullOrWhiteSpace($notation)) {
throw "Unable to establish notation URI from: '$($_)'"
}
$secret = [PsCustomObject]@{
Notation = $notation
VariableName = $variableName
}
$Secrets += $secret
}
}
Write-Verbose "Print variables: $PrintVariableNames"
Write-Verbose "Secrets to retrieve: $($Secrets.Count)"
Write-Verbose "KSM Version specified: $KsmModuleSpecificVersion"
Write-Verbose "KSM Custom Install Dir: $KsmModuleCustomInstallLocation"
# Retrieve Secrets
foreach($secret in $secrets) {
$notation = $secret.Notation
$variableName = $secret.VariableName
$ksmSecretValue = Get-Notation -Notation $notation -Config $KsmConfig
Set-OctopusVariable -Name $variableName -Value $ksmSecretValue -Sensitive
if($PrintVariableNames -eq $True) {
Write-Host "Created output variable: ##{Octopus.Action[$StepName].Output.$variableName}"
}
$VariablesCreated += 1
}
Write-Host "Created $variablesCreated output variables"
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": "95a35cf6-ce95-4b81-b8de-0892cffca4c4",
"Name": "Keeper Secrets Manager - Retrieve Secrets",
"Description": "This step retrieves one or more secrets from a Keeper Vault and creates [sensitive output variables](https://octopus.com/docs/projects/variables/output-variables#sensitive-output-variables) for each value retrieved. These values can be used in other steps in your deployment or runbook process.\n\nYou can retrieve secrets using Keeper Notation URIs, and you can choose a custom output variable name for each secret.\n\n---\n\n**Required:** \n- A [Keeper Secrets Manager](https://docs.keeper.io/secrets-manager/) application with permissions to retrieve secrets from the Keeper Vault.\n- The `SecretManagement.Keeper.Extension` PowerShell module installed on the target or worker. If the module can't be found, the step will fail. *The `SecretManagement.Keeper` module(s) can be installed from the [PowerShell gallery](https://www.powershellgallery.com/packages/SecretManagement.Keeper)*\n\nNotes:\n\n- Tested on Octopus `2022.4`.\n- Tested with both Windows PowerShell and PowerShell Core on Linux.\n\n",
"Version": 2,
"ExportedAt": "2024-06-12T00:54:34.7240000Z",
"ActionType": "Octopus.Script",
"Author": "idimov-keeper",
"Packages": [],
"Parameters": [
{
"Id": "7daedc7d-7623-47b8-98ba-747290f04372",
"Name": "Keeper.SecretsManager.RetrieveSecrets.Config",
"Label": "Keeper Secrets Manager Configuration",
"HelpText": "Keeper Secrets Manager [configuration](https://docs.keeper.io/secrets-manager/secrets-manager/about/secrets-manager-configuration) for [KSM Application](https://docs.keeper.io/secrets-manager/secrets-manager/quick-start-guide) with permissions to retrieve secrets from the Keeper Vault. To generate KSM Configuration in Web Vault: Secrets Manager - KSM Application Name - Devices - Edit - Add Device, and switch to Method: Configuration File, preferably in Base64 format",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "Sensitive"
}
},
{
"Id": "10df4954-8683-434c-b708-cd25b3b395ff",
"Name": "Keeper.SecretsManager.RetrieveSecrets.VaultSecrets",
"Label": "Vault Secrets to retrieve",
"HelpText": "Use [Secrets Manager Notation URIs](https://docs.keeper.io/secrets-manager/secrets-manager/about/keeper-notation) to specify the Secrets to be returned from Keeper Vault, in the format `SecretsManagerNotation URI | OutputVariableName` where:\n\n- `OutputVariableName` is the _optional_ Octopus [output variable](https://octopus.com/docs/projects/variables/output-variables) name to store the secret's value in. *If this value isn't specified, an output name will be generated dynamically*.\n\n**Note:** Multiple fields can be retrieved by entering each one on a new line.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "MultiLineText"
}
},
{
"Id": "15bd51e5-72be-4600-85ba-7b4cf1a8e157",
"Name": "Keeper.SecretsManager.RetrieveSecrets.PrintVariableNames",
"Label": "Print output variable names",
"HelpText": "Write out the Octopus [output variable](https://octopus.com/docs/projects/variables/output-variables) names to the task log. Default: `False`.",
"DefaultValue": "False",
"DisplaySettings": {
"Octopus.ControlType": "Checkbox"
}
},
{
"Id": "6888b6b2-8916-4f88-9c7a-d811654e5a2b",
"Name": "Keeper.SecretsManager.RetrieveSecrets.KsmModule.SpecificVersion",
"Label": "SecretManagement.Keeper.Extension PowerShell Module version (optional)",
"HelpText": "If you wish to use a specific version of the `SecretManagement.Keeper.Extension` PowerShell module (rather than the default), enter the version number here. e.g. `16.5.0`.\n\n**Note:** The version specified must exist on the machine. Version 16.5.0 is the lowest supported version\n",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "0a2b750b-0ad3-48fc-9d68-e133746226a9",
"Name": "Keeper.SecretsManager.RetrieveSecrets.KsmModule.CustomInstallLocation",
"Label": "SecretManagement.Keeper.Extension PowerShell Install Location (optional)",
"HelpText": "If you wish to provide a custom path to the `SecretManagement.Keeper.Extension` PowerShell module (rather than the default), enter the value here.\n\n**Note:** The Module must exist at the specified location on the machine. This step template will not download the Module.\n",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
}
],
"Properties": {
"Octopus.Action.Script.ScriptSource": "Inline",
"Octopus.Action.Script.Syntax": "PowerShell",
"OctopusUseBundledTooling": "False",
"Octopus.Action.Script.ScriptBody": "$ErrorActionPreference = 'Stop'\n\n# Variables\n$KsmModuleName = \"SecretManagement.Keeper.Extension\"\n$KsmParentModuleName = \"SecretManagement.Keeper\"\n$KsmConfig = $OctopusParameters[\"Keeper.SecretsManager.RetrieveSecrets.Config\"]\n$VaultSecrets = $OctopusParameters[\"Keeper.SecretsManager.RetrieveSecrets.VaultSecrets\"]\n$KsmModuleSpecificVersion = $OctopusParameters[\"Keeper.SecretsManager.RetrieveSecrets.KsmModule.SpecificVersion\"]\n$KsmModuleCustomInstallLocation = $OctopusParameters[\"Keeper.SecretsManager.RetrieveSecrets.KsmModule.CustomInstallLocation\"]\n$PrintVariableNames = $OctopusParameters[\"Keeper.SecretsManager.RetrieveSecrets.PrintVariableNames\"]\n\n# Validation\nif ([string]::IsNullOrWhiteSpace($VaultSecrets)) {\n throw \"Required parameter Keeper.SecretsManager.RetrieveSecrets.VaultSecrets not specified\"\n}\n\nif ([string]::IsNullOrWhiteSpace($KsmModuleSpecificVersion) -eq $False) {\n $requiredVersion = [Version]$KdmModuleSpecificVersion\n}\n\n# Cross-platform bits\n$WindowsPowerShell = $True\nif ($PSEdition -eq \"Core\") {\n $WindowsPowerShell = $False\n}\n\n### Helper functions\nfunction Get-Module-CrossPlatform {\n [CmdletBinding()]\n Param(\n [Parameter(Mandatory = $true, Position = 0)]\n [string] $Name\n )\n\n $module = Get-Module -Name $Name -ListAvailable\n if($WindowsPowerShell -eq $True -and $null -eq $module) {\n $module = Get-InstalledModule -Name $Name\n }\n\n return $module\n}\n\nfunction Load-Module {\n Param(\n [Parameter(Mandatory = $true)][string] $name\n )\n\n $retVal = $true\n if (!(Get-Module -Name $name)) {\n $isAvailable = Get-Module -ListAvailable | where { $_.Name -eq $name }\n if ($isAvailable) {\n try {\n Import-Module $name -ErrorAction SilentlyContinue\n } catch {\n $retVal = $false\n }\n } else {\n $retVal = $false\n }\n }\n return $retVal\n}\n\n$PowerShellModuleName = $KsmModuleName\n\n# Check for Custom install location specified for KsmModule\nif ([string]::IsNullOrWhiteSpace($KsmModuleCustomInstallLocation) -eq $false) {\n if ((Test-Path $KsmModuleCustomInstallLocation -IsValid) -eq $false) {\n throw \"The path $KsmModuleCustomInstallLocation is not valid, please use a relative or absolute path.\"\n }\n \n $KsmModulesFolder = [System.IO.Path]::GetFullPath($KsmModuleCustomInstallLocation)\n $LocalModules = (New-Item \"$KsmModulesFolder\" -ItemType Directory -Force).FullName\n $env:PSModulePath = $LocalModules + [System.IO.Path]::PathSeparator + $env:PSModulePath\n\n # Check to see if there\n if ((Test-Path -Path \"$LocalModules/$KsmModuleName\") -eq $true)\n {\n # Use specific location\n $PowerShellModuleName = \"$LocalModules/$PowerShellModuleName\"\n }\n}\n\n# Import module\nif([string]::IsNullOrWhiteSpace($KsmModuleSpecificVersion)) {\n Write-Host \"Importing module $PowerShellModuleName ...\"\n if ((Load-Module -Name $PowerShellModuleName) -eq $false) {\n Write-Host \"Extension module not found $PowerShellModuleName - trying to find sub-module in parent $KsmParentModuleName\"\n if (Get-Module -ListAvailable -Name $KsmParentModuleName) {\n $KsmParentModuleDir = Split-Path -Path (Get-Module -ListAvailable -Name $KsmParentModuleName).Path\n $KsmModuleFolder = [System.IO.Path]::GetFullPath($KsmParentModuleDir)\n $LocalModules = (New-Item \"$KsmModuleFolder\" -ItemType Directory -Force).FullName\n $env:PSModulePath = $LocalModules + [System.IO.Path]::PathSeparator + $env:PSModulePath\n\n if ((Test-Path -Path \"$LocalModules/$KsmModuleName\") -eq $true)\n {\n $PowerShellModuleName = \"$LocalModules/$PowerShellModuleName\"\n try {\n Import-Module -Name $PowerShellModuleName -ErrorAction SilentlyContinue\n Write-Host \"Imported sub-module $PowerShellModuleName ...\"\n } catch {\n Write-Host \"Failed to import sub-module $PowerShellModuleName ...\"\n }\n }\n } else {\n Write-Host \"Module does not exist\"\n }\n }\n}\nelse {\n Write-Host \"Importing module $PowerShellModuleName ($KsmModuleSpecificVersion)...\"\n Import-Module -Name $PowerShellModuleName -RequiredVersion $requiredVersion\n}\n\n# Check if SecretManagement.Keeper.Extension Module is installed.\n$ksmVaultModule = Get-Module-CrossPlatform -Name $KsmModuleName\nif ($null -eq $ksmVaultModule) {\n throw \"Cannot find the '$KsmModuleName' module on the machine. If you think it is installed, try restarting the Tentacle service for it to be detected.\"\n}\n\n$Secrets = @()\n$VariablesCreated = 0\n$StepName = $OctopusParameters[\"Octopus.Step.Name\"]\n\n# Extract lines and split into notations and variables\n$index = 0\n$usedNames = @()\n@(($VaultSecrets -Split \"`n\").Trim()) | ForEach-Object {\n if (![string]::IsNullOrWhiteSpace($_)) {\n Write-Verbose \"Working on: '$_'\"\n\n # Split 'Notation | VariableName' and generate new var name if needed\n $notation = $_\n $variableName = \"\"\n $n = $_.LastIndexOf(\"|\")\n if ($n -ge 0) {\n if ($n -lt $notation.Length-1) {\n $variableName = $notation.SubString($n+1).Trim()\n }\n $notation = $notation.SubString(0, $n).Trim()\n }\n if ([string]::IsNullOrWhiteSpace($variableName)) {\n do {\n $index++\n $variableName = \"KsmSecret\" + $index\n } while ($usedNames.Contains($variableName))\n }\n # Duplicate var - either overlapping KsmSecretN or another user variable\n if($usedNames.Contains($variableName)) {\n throw \"Duplicate variable name: '$variableName'\"\n }\n $usedNames += $variableName\n\n if([string]::IsNullOrWhiteSpace($notation)) {\n throw \"Unable to establish notation URI from: '$($_)'\"\n }\n $secret = [PsCustomObject]@{\n Notation = $notation\n VariableName = $variableName\n }\n $Secrets += $secret\n }\n}\n\nWrite-Verbose \"Print variables: $PrintVariableNames\"\nWrite-Verbose \"Secrets to retrieve: $($Secrets.Count)\"\nWrite-Verbose \"KSM Version specified: $KsmModuleSpecificVersion\"\nWrite-Verbose \"KSM Custom Install Dir: $KsmModuleCustomInstallLocation\"\n\n# Retrieve Secrets\nforeach($secret in $secrets) {\n $notation = $secret.Notation\n $variableName = $secret.VariableName\n\n $ksmSecretValue = Get-Notation -Notation $notation -Config $KsmConfig\n\n Set-OctopusVariable -Name $variableName -Value $ksmSecretValue -Sensitive\n\n if($PrintVariableNames -eq $True) {\n Write-Host \"Created output variable: ##{Octopus.Action[$StepName].Output.$variableName}\"\n }\n $VariablesCreated += 1\n}\n\nWrite-Host \"Created $variablesCreated output variables\"\n"
},
"Category": "Keeper Secrets Manager",
"HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates//opt/buildagent/work/75443764cd38076d/step-templates/keeper-secretsmanager-retrieve-secrets.json",
"Website": "/step-templates/95a35cf6-ce95-4b81-b8de-0892cffca4c4",
"Logo": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAABmJLR0QAAAAAAAD5Q7t/AAAD5UlEQVR42u3cS24qMRBA0YB6wJLYAKtmAyyJmTMiihARHWjsqvK5ozd6wu46Md/etdbal6SH7W2BBIgEiASIBIgEiASIBIgEiASIJEAkQCRAJEAkQCRAJEAkQCRAJEAkASIBIgEiASIBIgEiASIBIgEiCRAJEAkQCRAJEAkQCRAJEAkQCRBJj1pswZiul9PPvw/Hsw0J2q611mzDGBj3gQIIGCsCBRAwQAEEjG0CBRAwQAEEDFAAAQMUQDQSBiiAgAEKIGCAAggYoAACBiiAgAEKIGDUDxRAwAAFkMwwfg9npMeiyYFEHkZQAAGj2GMFBIxhwwYKIGCAAggY1pY1t/1J1OF4Hjqk18tpurfFPcVK/NfWiQKIIbJGQECxRkBAAQUQUECpBcWXFUEBJROQ+4vZa3NBASU0kGcXDxRrnBLIfy8WKNY4BZB3Lw4o1lgSyNYXAxRrLAHk05sPijWmBNJ7s0GxxjRAZrixMyi1kZQ7QUDxbMBrEFBKQ5nqNQgooGSEMQwIKKBkgDEcCCig+CTdAIGSFEY4IKDUh+LbvAbIOosV/gdToIACiAECBRADZJ2AgGKdgIACCiAbXVQDVGedvZH0nJ+/Wnpd0E8v9Pb/jxqgXuucoUg3yO7+exAnipMj4ryEAQIKGBHnJBwQUMCINB9hgYACBiDJL1KPYQQDEFCClWGPy7/N++6mVn97GIzYLdEfIChgAAIKGICAAgYgoIABCChgzNJSZSEzQwEDEFDAAAQUMAABBQxAQNlyyMAABBQwAAEFDEBAeRkKGICA8gAKGICAMui0AOO99pEf3Mgfy1wvp/SDNXoNh+M5/W2Qwp8g7neV78SodG+wNE+xQAEDEFDAAAQUMAABBQxAQOkLBQxAQAEDEFDAAASUl6GAAQgoYAACyjooYAACSrDTAgxAUkABAxBQwAAEFDAAAQUMQJQdChiAgAIGIKCAAcjG9bpbyIw3r/Zt3mJD1OPCunl17ZNx6blQUMDI9pRxGbFwUMDI8lpqGbkRoIAR/bXNEmFjQAEDEFCerhEMQECZ+ObVGd8m3rXW2lehMr44zrInPgdR9xOl8okBCChgAKIsUMAABBQwAAEFDEBAASNB5d7mjTBAn4LicwxADBQYgIACBiCgvDxwYAACChiAgLJuIMEABJSAgQEIKGAAAgoYgIACBiCggAEIKGAAAgoYgIACBiCKCgUMQEABAxBQwAAEFDAA0ZZQwAAEFDAA0TooYAAipWpvCyRAJEAkQCRAJEAkQCRAJEAkQCQBIgEiASIBIgEiASIBIgEiASIBIgkQCRAJEAkQCRAJEAkQCRAJEEm3vgEajriFDSkxDAAAAABJRU5ErkJggg==",
"$Meta": {
"Type": "ActionTemplate"
}
}
Page updated on Wednesday, June 12, 2024