Keeper Secrets Manager - Retrieve Secrets

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. The SecretManagement.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.

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.

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

History

Page updated on Wednesday, June 12, 2024