Octopus.Script exported 2016-07-11 by roberto-mardeni belongs to ‘Akamai’ category.
Allows to purge content using the Content Control Utility (CCU) v3 REST API.
Parameters
When steps based on the template are included in a project’s deployment process, the parameters below can be set.
Client Token
AkamaiClientToken
Authentication token used in client authentication. Available in Luna Portal.
Client Access Token
AkamaiClientAccessToken
Authentication token used in client authentication. Available in Luna Portal.
Secret
AkamaiSecret
Authentication password used in client authentication. Available in Luna Portal.
Hostname
AkamaiHostname
The hostname for which to execute the purge operation
Objects
AkamaiObjects
A comma separated list of objects to purge, only URLs
Action
AkamaiAction = invalidate
The action to execute on the purge operation
Domain
AkamaiDomain = production
The Akamai domain to perform the purge operation on
Proxy User
ProxyUser
Optional, a user name for the proxy if required in the network
Proxy Password
ProxyPassword
Optional, the password for the account to use if a Proxy User was specified
Script body
Steps based on this template will execute the following PowerShell script.
$clientToken = $OctopusParameters['AkamaiClientToken']
$clientAccessToken = $OctopusParameters['AkamaiClientAccessToken']
$clientSecret = $OctopusParameters['AkamaiSecret']
$hostname = $OctopusParameters['AkamaiHostname']
$objects = $OctopusParameters['AkamaiObjects'] -split ","
$action = $OctopusParameters['AkamaiAction']
$domain = $OctopusParameters['AkamaiDomain']
$proxyUser = $OctopusParameters['ProxyUser']
$proxyPassword = $OctopusParameters['ProxyPassword']
if ($proxyUser) {
$securePassword = ConvertTo-SecureString $proxyPassword -AsPlainText -Force
$proxyCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $proxyUser,$securePassword
(New-Object System.Net.WebClient).Proxy.Credentials=$proxyCredential
}
# Copied from https://github.com/akamai-open/AkamaiOPEN-powershell/blob/master/Invoke-AkamaiOPEN.ps1
function Invoke-AkamaiOpenRequest {
param(
[Parameter(Mandatory=$true)][string]$Method,
[Parameter(Mandatory=$true)][string]$ClientToken,
[Parameter(Mandatory=$true)][string]$ClientAccessToken,
[Parameter(Mandatory=$true)][string]$ClientSecret,
[Parameter(Mandatory=$true)][string]$ReqURL,
[Parameter(Mandatory=$false)][string]$Body)
#Function to generate HMAC SHA256 Base64
Function Crypto ($secret, $message)
{
[byte[]] $keyByte = [System.Text.Encoding]::ASCII.GetBytes($secret)
[byte[]] $messageBytes = [System.Text.Encoding]::ASCII.GetBytes($message)
$hmac = new-object System.Security.Cryptography.HMACSHA256((,$keyByte))
[byte[]] $hashmessage = $hmac.ComputeHash($messageBytes)
$Crypt = [System.Convert]::ToBase64String($hashmessage)
return $Crypt
}
#ReqURL Verification
If (($ReqURL -as [System.URI]).AbsoluteURI -eq $null -or $ReqURL -notmatch "akamai.com")
{
throw "Error: Ivalid Request URI"
}
#Sanitize Method param
$Method = $Method.ToUpper()
#Split $ReqURL for inclusion in SignatureData
$ReqArray = $ReqURL -split "(.*\/{2})(.*?)(\/)(.*)"
#Timestamp for request signing
$TimeStamp = [DateTime]::UtcNow.ToString("yyyyMMddTHH:mm:sszz00")
#GUID for request signing
$Nonce = [GUID]::NewGuid()
#Build data string for signature generation
$SignatureData = $Method + "`thttps`t"
$SignatureData += $ReqArray[2] + "`t" + $ReqArray[3] + $ReqArray[4]
if (($Body -ne $null) -and ($Method -ceq "POST"))
{
$Body_SHA256 = [System.Security.Cryptography.SHA256]::Create()
$Post_Hash = [System.Convert]::ToBase64String($Body_SHA256.ComputeHash([System.Text.Encoding]::ASCII.GetBytes($Body.ToString())))
$SignatureData += "`t`t" + $Post_Hash + "`t"
}
else
{
$SignatureData += "`t`t`t"
}
$SignatureData += "EG1-HMAC-SHA256 "
$SignatureData += "client_token=" + $ClientToken + ";"
$SignatureData += "access_token=" + $ClientAccessToken + ";"
$SignatureData += "timestamp=" + $TimeStamp + ";"
$SignatureData += "nonce=" + $Nonce + ";"
#Generate SigningKey
$SigningKey = Crypto -secret $ClientSecret -message $TimeStamp
#Generate Auth Signature
$Signature = Crypto -secret $SigningKey -message $SignatureData
#Create AuthHeader
$AuthorizationHeader = "EG1-HMAC-SHA256 "
$AuthorizationHeader += "client_token=" + $ClientToken + ";"
$AuthorizationHeader += "access_token=" + $ClientAccessToken + ";"
$AuthorizationHeader += "timestamp=" + $TimeStamp + ";"
$AuthorizationHeader += "nonce=" + $Nonce + ";"
$AuthorizationHeader += "signature=" + $Signature
#Create IDictionary to hold request headers
$Headers = @{}
#Add Auth header
$Headers.Add('Authorization',$AuthorizationHeader)
#Add additional headers if POSTing or PUTing
If (($Method -ceq "POST") -or ($Method -ceq "PUT"))
{
$Body_Size = [System.Text.Encoding]::UTF8.GetByteCount($Body)
$Headers.Add('max-body',$Body_Size.ToString())
# turn off the "Expect: 100 Continue" header
# as it's not supported on the Akamai side.
[System.Net.ServicePointManager]::Expect100Continue = $false
}
#Check for valid Methods and required switches
If (($Method -ceq "POST") -and ($Body -ne $null))
{
Invoke-RestMethod -Method $Method -Uri $ReqURL -Headers $Headers -Body $Body -ContentType 'application/json'
}
elseif (($Method -ceq "PUT") -and ($Body -ne $null))
{
#Invoke API call with PUT and return
Invoke-RestMethod -Method $Method -Uri $ReqURL -Headers $Headers -Body $Body -ContentType 'application/json'
}
elseif (($Method -ceq "GET") -or ($Method -ceq "DELETE"))
{
#Invoke API call with GET or DELETE and return
Invoke-RestMethod -Method $Method -Uri $ReqURL -Headers $Headers
}
else
{
throw "Error: Invalid -Method specified or missing required parameter"
}
}
function Perform-AkamaiRequest {
param (
[string]$request,
[string]$method="Get",
[int]$expectedStatusCode=200,
$body)
$baseUrl = "http://private-anon-3934daf8d-akamaiopen2purgeccuv3production.apiary-mock.com"
# $baseUrl = "https://api.ccu.akamai.com"
$uri = "{0}{1}" -f $baseUrl,$request
if ($uri -match "mock"){
$requestHeaders = @{'Cache-Control'='no-cache,proxy-revalidate'}
$response = Invoke-RestMethod -Uri $uri -Method $method -DisableKeepAlive -Headers $requestHeaders -Body $body
} else {
$json = ConvertTo-Json $body -Compress
$response = Invoke-AkamaiOpenRequest -Method $method -ClientToken $clientToken -ClientAccessToken $clientAccessToken -ClientSecret $clientSecret -ReqURL $uri -Body $json
}
if ($response.httpStatus -ne $expectedStatusCode){
Write-Error "Request not processed correctly: $($response.detail)"
} elseif ($response.detail) {
Write-Verbose $response.detail
}
Write-Verbose $response
$response
}
function Request-Purge {
param ($objects,[string]$hostname,[string]$action="remove",[string]$domain="production")
$body = @{
objects = $objects
}
if ($hostname -ne $null -and $hostname -ne "") {
$body = @{
hostname = $hostname
objects = $objects
}
}
Perform-AkamaiRequest "/ccu/v3/$action/$domain" "Post" 201 $body
}
$purge = Request-Purge $objects $hostname $action $domain
Write-Output "Purge request created"
Write-Output "PurgeId: $($purge.purgeId)"
Write-Output "SupportId: $($purge.supportId)"
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": "f8e2e47b-62ba-44a0-881c-d1911dc14428",
"Name": "Akamai - Content Fast Purge",
"Description": "Allows to purge content using the Content Control Utility (CCU) v3 REST API.",
"Version": 1,
"ExportedAt": "2016-07-11T14:30:28.569+00:00",
"ActionType": "Octopus.Script",
"Author": "roberto-mardeni",
"Parameters": [
{
"Name": "AkamaiClientToken",
"Label": "Client Token",
"HelpText": "Authentication token used in client authentication. Available in Luna Portal.",
"DefaultValue": null,
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Name": "AkamaiClientAccessToken",
"Label": "Client Access Token",
"HelpText": "Authentication token used in client authentication. Available in Luna Portal.",
"DefaultValue": null,
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Name": "AkamaiSecret",
"Label": "Secret",
"HelpText": "Authentication password used in client authentication. Available in Luna Portal.",
"DefaultValue": null,
"DisplaySettings": {
"Octopus.ControlType": "Sensitive"
}
},
{
"Name": "AkamaiHostname",
"Label": "Hostname",
"HelpText": "The hostname for which to execute the purge operation",
"DefaultValue": null,
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Name": "AkamaiObjects",
"Label": "Objects",
"HelpText": "A comma separated list of objects to purge, only URLs",
"DefaultValue": null,
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Name": "AkamaiAction",
"Label": "Action",
"HelpText": "The action to execute on the purge operation",
"DefaultValue": "invalidate",
"DisplaySettings": {
"Octopus.ControlType": "Select",
"Octopus.SelectOptions": "invalidate\nremove"
}
},
{
"Name": "AkamaiDomain",
"Label": "Domain",
"HelpText": "The Akamai domain to perform the purge operation on",
"DefaultValue": "production",
"DisplaySettings": {
"Octopus.ControlType": "Select",
"Octopus.SelectOptions": "production\nstaging"
}
},
{
"Name": "ProxyUser",
"Label": "Proxy User",
"HelpText": "Optional, a user name for the proxy if required in the network",
"DefaultValue": null,
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Name": "ProxyPassword",
"Label": "Proxy Password",
"HelpText": "Optional, the password for the account to use if a Proxy User was specified",
"DefaultValue": null,
"DisplaySettings": {
"Octopus.ControlType": "Sensitive"
}
}
],
"Properties": {
"Octopus.Action.Script.Syntax": "PowerShell",
"Octopus.Action.Script.ScriptSource": "Inline",
"Octopus.Action.Script.ScriptBody": "$clientToken = $OctopusParameters['AkamaiClientToken']\n$clientAccessToken = $OctopusParameters['AkamaiClientAccessToken']\n$clientSecret = $OctopusParameters['AkamaiSecret']\n$hostname = $OctopusParameters['AkamaiHostname']\n$objects = $OctopusParameters['AkamaiObjects'] -split \",\"\n$action = $OctopusParameters['AkamaiAction']\n$domain = $OctopusParameters['AkamaiDomain']\n$proxyUser = $OctopusParameters['ProxyUser']\n$proxyPassword = $OctopusParameters['ProxyPassword']\n\nif ($proxyUser) {\n $securePassword = ConvertTo-SecureString $proxyPassword -AsPlainText -Force\n $proxyCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $proxyUser,$securePassword\n\n (New-Object System.Net.WebClient).Proxy.Credentials=$proxyCredential\n}\n\n# Copied from https://github.com/akamai-open/AkamaiOPEN-powershell/blob/master/Invoke-AkamaiOPEN.ps1\nfunction Invoke-AkamaiOpenRequest {\n param(\n [Parameter(Mandatory=$true)][string]$Method, \n [Parameter(Mandatory=$true)][string]$ClientToken, \n [Parameter(Mandatory=$true)][string]$ClientAccessToken, \n [Parameter(Mandatory=$true)][string]$ClientSecret, \n [Parameter(Mandatory=$true)][string]$ReqURL, \n [Parameter(Mandatory=$false)][string]$Body)\n\n #Function to generate HMAC SHA256 Base64\n Function Crypto ($secret, $message)\n {\n\t [byte[]] $keyByte = [System.Text.Encoding]::ASCII.GetBytes($secret)\n\t [byte[]] $messageBytes = [System.Text.Encoding]::ASCII.GetBytes($message)\n\t $hmac = new-object System.Security.Cryptography.HMACSHA256((,$keyByte))\n\t [byte[]] $hashmessage = $hmac.ComputeHash($messageBytes)\n\t $Crypt = [System.Convert]::ToBase64String($hashmessage)\n\n\t return $Crypt\n }\n\n #ReqURL Verification\n If (($ReqURL -as [System.URI]).AbsoluteURI -eq $null -or $ReqURL -notmatch \"akamai.com\")\n {\n\t throw \"Error: Ivalid Request URI\"\n }\n\n #Sanitize Method param\n $Method = $Method.ToUpper()\n\n #Split $ReqURL for inclusion in SignatureData\n $ReqArray = $ReqURL -split \"(.*\\/{2})(.*?)(\\/)(.*)\"\n\n #Timestamp for request signing\n $TimeStamp = [DateTime]::UtcNow.ToString(\"yyyyMMddTHH:mm:sszz00\")\n\n #GUID for request signing\n $Nonce = [GUID]::NewGuid()\n\n #Build data string for signature generation\n $SignatureData = $Method + \"`thttps`t\"\n $SignatureData += $ReqArray[2] + \"`t\" + $ReqArray[3] + $ReqArray[4]\n\n if (($Body -ne $null) -and ($Method -ceq \"POST\"))\n {\n\t $Body_SHA256 = [System.Security.Cryptography.SHA256]::Create()\n\t $Post_Hash = [System.Convert]::ToBase64String($Body_SHA256.ComputeHash([System.Text.Encoding]::ASCII.GetBytes($Body.ToString())))\n\n\t $SignatureData += \"`t`t\" + $Post_Hash + \"`t\"\n }\n else\n {\n\t $SignatureData += \"`t`t`t\"\n }\n\n $SignatureData += \"EG1-HMAC-SHA256 \"\n $SignatureData += \"client_token=\" + $ClientToken + \";\"\n $SignatureData += \"access_token=\" + $ClientAccessToken + \";\"\n $SignatureData += \"timestamp=\" + $TimeStamp + \";\"\n $SignatureData += \"nonce=\" + $Nonce + \";\"\n\n #Generate SigningKey\n $SigningKey = Crypto -secret $ClientSecret -message $TimeStamp\n\n #Generate Auth Signature\n $Signature = Crypto -secret $SigningKey -message $SignatureData\n\n #Create AuthHeader\n $AuthorizationHeader = \"EG1-HMAC-SHA256 \"\n $AuthorizationHeader += \"client_token=\" + $ClientToken + \";\"\n $AuthorizationHeader += \"access_token=\" + $ClientAccessToken + \";\"\n $AuthorizationHeader += \"timestamp=\" + $TimeStamp + \";\"\n $AuthorizationHeader += \"nonce=\" + $Nonce + \";\"\n $AuthorizationHeader += \"signature=\" + $Signature\n\n #Create IDictionary to hold request headers\n $Headers = @{}\n\n #Add Auth header\n $Headers.Add('Authorization',$AuthorizationHeader)\n\n #Add additional headers if POSTing or PUTing\n If (($Method -ceq \"POST\") -or ($Method -ceq \"PUT\"))\n {\n\t $Body_Size = [System.Text.Encoding]::UTF8.GetByteCount($Body)\n\t $Headers.Add('max-body',$Body_Size.ToString())\n\n # turn off the \"Expect: 100 Continue\" header\n # as it's not supported on the Akamai side.\n [System.Net.ServicePointManager]::Expect100Continue = $false\n }\n\n #Check for valid Methods and required switches\n If (($Method -ceq \"POST\") -and ($Body -ne $null))\n {\n Invoke-RestMethod -Method $Method -Uri $ReqURL -Headers $Headers -Body $Body -ContentType 'application/json'\n }\n elseif (($Method -ceq \"PUT\") -and ($Body -ne $null))\n {\n\t #Invoke API call with PUT and return\n\t Invoke-RestMethod -Method $Method -Uri $ReqURL -Headers $Headers -Body $Body -ContentType 'application/json'\n }\n elseif (($Method -ceq \"GET\") -or ($Method -ceq \"DELETE\"))\n {\n\t #Invoke API call with GET or DELETE and return\n\t Invoke-RestMethod -Method $Method -Uri $ReqURL -Headers $Headers\n }\n else\n {\n\t throw \"Error: Invalid -Method specified or missing required parameter\"\n }\n}\n\nfunction Perform-AkamaiRequest {\n param (\n [string]$request, \n [string]$method=\"Get\", \n [int]$expectedStatusCode=200, \n $body)\n\n $baseUrl = \"http://private-anon-3934daf8d-akamaiopen2purgeccuv3production.apiary-mock.com\"\n # $baseUrl = \"https://api.ccu.akamai.com\"\n $uri = \"{0}{1}\" -f $baseUrl,$request\n\n if ($uri -match \"mock\"){\n $requestHeaders = @{'Cache-Control'='no-cache,proxy-revalidate'}\n $response = Invoke-RestMethod -Uri $uri -Method $method -DisableKeepAlive -Headers $requestHeaders -Body $body\n } else {\n $json = ConvertTo-Json $body -Compress\n $response = Invoke-AkamaiOpenRequest -Method $method -ClientToken $clientToken -ClientAccessToken $clientAccessToken -ClientSecret $clientSecret -ReqURL $uri -Body $json\n }\n\n if ($response.httpStatus -ne $expectedStatusCode){\n Write-Error \"Request not processed correctly: $($response.detail)\"\n } elseif ($response.detail) {\n Write-Verbose $response.detail\n }\n\n Write-Verbose $response\n\n $response\n}\n\nfunction Request-Purge {\n param ($objects,[string]$hostname,[string]$action=\"remove\",[string]$domain=\"production\")\n\n $body = @{\n objects = $objects\n }\n\n if ($hostname -ne $null -and $hostname -ne \"\") {\n $body = @{\n hostname = $hostname\n objects = $objects\n }\n } \n\n Perform-AkamaiRequest \"/ccu/v3/$action/$domain\" \"Post\" 201 $body\n}\n\n$purge = Request-Purge $objects $hostname $action $domain\n\nWrite-Output \"Purge request created\"\nWrite-Output \"PurgeId: $($purge.purgeId)\"\nWrite-Output \"SupportId: $($purge.supportId)\" ",
"Octopus.Action.Script.ScriptFileName": null,
"Octopus.Action.Package.NuGetFeedId": null,
"Octopus.Action.Package.NuGetPackageId": null
},
"Category": "Akamai",
"HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates//opt/buildagent/work/75443764cd38076d/step-templates/akamai-fast-content-purge.json",
"Website": "/step-templates/f8e2e47b-62ba-44a0-881c-d1911dc14428",
"Logo": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABhQTFRFseDvTrjc1+/3f8zlKqrU////AJnM7/n8E0I9ngAABR5JREFUeNrsndly6zAIQAFJ1v//8c16GydGK3IgA9O3tqOcsCNZhvQjAg7iIA7iIA7iIA7iIA7iIA7iIA7iIA7iIA7iIA5yIAQUnkI2QS4AGLedmAPJEN4QbhJsgdAhxFKMBSAcBYIpZ4djigjZUtTKYTtWBqX1IgeS8Rgj5JQMgdB3MaRAOKM6DUMIhPON8zBEQNhIxWdLoOePHhDWOY7zPX78ecQQ4PsgjFXF/Fk74rHmHv8wCzP377lRHVy6F0z+UyDAfCJ4M6gWitncCfIc+2BF2I4xo5YJkBazAty6JcKpIJx7vJaHNIAxijIKkmPVPfIgxpivgCwHVQNzq4RTQOocFLdJibQepM4RNgEJq0GqHDPeMVp1wgKOebPiKx1BkCoHbHLS7igglQdhBcc+DsqC1PJ5Iwdeq/c/QWQrGVoDwjWD7RyXgp37bHA0n2z0k04QKDtlhmpJeIHgP9n1N5fma4SkD4Qq6geZwjbvmzCUB6kUWFC0qL5RxGvdDNIgFQcB2S6DQo/Dg4Bh5fKvx5ul/y6HsiBlw8orWvHn5C9IglQMKzY18KMNXJYDyWXDWjc0hSaVQK+SmZQO7T0rwS2R7374JPlUSpYC4VJhybDwaEzHhwRee5eEH6RAyrViaPGO+oArchvYhCgEUp5hUUO11zgZGt2lAxGFYLUn6pg2bkPnCmBOIWwq3LsHdPaMA7EO1igEB2e/43vybSBUDFlU5DjAuMdc2WkjrFAIHk5Nbzs674P663kVkX3UJhAuqTMKwc+yBsv7OPTRTXWP6JpAykk9MDnyWSe1bkbRJwwIg5QHQGzcvQ2OkHos5H1/LoiCUDH2Aj83xZGMsE+cKAkSijshKFq1fwQ6lAPhRouH1YnQmayXYIdiIGXLCoyjz8pf2xCkxkGhI4mIHmh6TuuCEEjRsvLSw35BchxULk9gjWG9GZjIOAiK2RClI9Zhn9swNa2vXa6z4kjM7w/GKAASS3VWXubpb64C0yC5Oa1jWia52rLXQaBYY4fPAdeXBBojYD2LYNINgsXKF0/wkLUgH5Hgywqpg5QHjGoUUgUpB620MKkLg1ROyZ3zSMVCkPCuEdIOUp47kBrLmgQBNZYlBULpR0wrqQfBJo2gdZCkxkWEQEA9SG4Dyb+ikfQjIGgApBx+H5yYfwQk2NdI+BUQMANS3mB/1ChgAIQqx2PNgKTK8Xs0DrLtfMgESHkcdPchMgwCrxozoZFQAUErINTwdIIJkMqo8TbByyZAinuhd9tKJkBqTgJWQKB2xC1GGyC54iQpkw2QVH+a1QhIEDo++XUQqtmWFRAbtjVx8CyYAzFhWwKHMw2BVBp3OyCVp5LsgFhwd4lD/oZAqg2vGZCsXiUyjyYZAlHvJbOP7wVzINpzSbuRK88lHd6qu+LqefhHtb/3xE/V/t4DkjfFxtWV0TQbV19qVhy5OmuMqLZS6fwIetNi73dJ0zd6KQFR27/3W3fQSTLgpjpbk5HlVZIMra6RZGxxhSSDazdcLWsDRJ9OhlfWVtOPf4XKMuOELYCqamXGqKn3Cn+tIM3XxqsH4S/yJ2sg7N2+wRoIezfd2UpZ99qOM9+ikta+SOXUPC+0Vti+HYmlVmJf/QTGQK4o8ZsooqswNxjGM9xe+Oti31cHxkB4lhjIGEjKLAvYArnTHF6PB/ZAbpqB93dt2gR50Ly8/ZSSXRBzmd1BHMRBHMRBHMRBHMRBHMRBHMRBHMRBHMRBHORM+SfAAMOMGvrIfh0UAAAAAElFTkSuQmCC",
"$Meta": {
"Type": "ActionTemplate"
}
}
Page updated on Monday, July 11, 2016