forked from coaxke/CloudFlareWorkersMaintenance
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ToggleMaintenanceMode.ps1
141 lines (119 loc) · 5.24 KB
/
ToggleMaintenanceMode.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
<#
Calls Cloudflare API to update/query the status of Cloudflare Workers, which provide
maintenance mode functionality.
#>
<#===============================================================================================#>
<#
.SYNOPSIS
Fetches all of the DNS routes for a given Cloudflare Zone ID
.PARAMETER Headers
HashTable of Requst headers to auth against Cloudflare (API-Key/Email Address)
.PARAMETER zoneID
Unique Cloudflare ID representing a DNS zone which contains Workers
#>
function Get-WorkerRoutes(
[hashtable]$Headers,
[string]$zoneID) {
try {
$workerRoutes = Invoke-RestMethod -Method Get -Uri "https://api.cloudflare.com/client/v4/zones/$($zoneId)/workers/routes" -Headers $Headers
if ($workerRoutes.result.count -gt 0) {
return $workerRoutes.result
}
}
catch {
Write-Error $_.Exception.Message
return $null
}
return $null
}
<#
.SYNOPSIS
Updates and eventually checks the status of a Cloudflare worker for a given route
.PARAMETER workerRoute
Object which contains the unique ID of the route, the pattern of the rule to be enable (e.g. *subdomain.example.com/*),
enabled boolean indicating if the route has been enabled/disabled.
.PARAMETER Headers
HashTable of Requst headers to auth against Cloudflare (API-Key/Email Address)
.PARAMETER zoneID
Unique Cloudflare ID representing a DNS zone which contains Workers
.PARAMETER workerScriptName
Unique name representing the script of the worker which to enable for a given route. This value is $null if we wish to disable
the script on a given route.
#>
function Set-WorkerRouteStatus(
[PsCustomObject]$workerRoute,
[hashtable]$headers,
[string]$zoneId,
[object]$workerScriptName) {
try {
#Generate JSON payload + convert to JSON (Setting as a PSCustomObject preserves the order or properties in payload):
$ApiBody = [pscustomobject]@{
id = $workerRoute.Id
pattern = $workerRoute.Pattern
script = $workerScriptName
} | Convertto-Json
#Enable script for the route.
Invoke-RestMethod -Uri "https://api.cloudflare.com/client/v4/zones/$($zoneId)/workers/routes/$($workerRoute.Id)" `
-Headers $headers -Body $ApiBody -Method PUT -ContentType 'application/json'
Write-Host "Set script '$workerScriptName' on worker route '$($workerRoute.Pattern)'."
#We now need to verify that the workerRouteStatus we just set is returned when we query it (double-check)
#if not, fail the deploy outright - someone needs to investigate what's wrong.
$CheckRoute = Invoke-RestMethod -Uri "https://api.cloudflare.com/client/v4/zones/$($zoneId)/workers/routes/$($workerRoute.Id)" -Headers $headers -Method GET
if (-not (($CheckRoute.result.script) -eq $workerScriptName)) {
if ($null -eq $workerScriptName) {
Write-Error "Attempted to disable CloudFlareRoute '$($workerRoute.Id)' with the pattern '$($workerRoute.Pattern)', however the CloudFlare API
is not returning the exepected result."
}
else {
Write-Error "Attempted to update CloudFlareRoute '$($workerRoute.Id)' with the pattern '$($workerRoute.Pattern)' and the route '$workerScriptName', however the CloudFlare API
is not returning the exepected result."
}
throw;
}
}
catch {
Write-Host "Error updating $($workerRoute.pattern)"
Write-Error $_.Exception.Message
throw;
}
}
##Main:
#Globals vars:
[string]${Maintenance.CfApiKey} = "xxxx123123"
[string]${Maintenance.CfEmail} = "test@example.com"
[string]${Maintenance.CfZoneId} = "zoneID123zoneID123zoneID123zoneID123zoneID123"
[string]${Maintenance.routePattern} = "resdevops.com/*"
[string]${Maintenance.WorkerScriptName} = "some-worker-name"
try {
#Assemble CF API Request Auth headers
$apiRequestHeaders = @{
'X-Auth-Key' = ${Maintenance.CfApiKey}
'X-Auth-Email' = ${Maintenance.CfEmail}
}
$allWorkerRoutes = Get-WorkerRoutes -Headers $apiRequestHeaders -zoneID ${Maintenance.CfZoneId}
if ($allWorkerRoutes -ne $null) {
#If we want to toggle multiple different patterns (comma seperated), split them out:
$allRoutePatterns = (${Maintenance.RoutePattern} -split ",")
foreach ($routePattern in $allRoutePatterns) {
#Its possble the Pattern we pass in could result in multiple Route matches - We'll
#need to enumerate over them regarless:
$filteredWorkerRoutes = $allWorkerRoutes | ? { $_.Pattern -eq $routePattern }
foreach ($filteredWorkerRoute in $filteredWorkerRoutes) {
Write-Host "Processing $filteredWorkerRoute."
switch ((${Maintenance.routeAction}).ToLower()) {
"enable" { Set-WorkerRouteStatus -workerRoute $filteredWorkerRoute -headers $apiRequestHeaders -zoneId ${Maintenance.CfZoneId} -workerScriptName ${Maintenance.WorkerScriptName}; break }
"disable" { Set-WorkerRouteStatus -workerRoute $filteredWorkerRoute -headers $apiRequestHeaders -zoneId ${Maintenance.CfZoneId} -workerScriptName $null ; break}
"status" { Write-Host "Route: $($filteredWorkerRoute.pattern), Script value: $($filteredWorkerRoute.script)"; break }
default { Write-Error "Maintenane routeAction was not an expected value (enable/disable/status)."; break }
}
}
}
Write-Host "Maintenance-mode task complete."
}
else {
Write-Error "No worker routes returned for the zoneID ${Maintenance.CfZoneId}; Please add required routes and re-run the script"
}
}
catch {
Write-Error $_
}