291 lines
9.8 KiB
PowerShell
291 lines
9.8 KiB
PowerShell
|
|
# Cloudflare Setup Script for Miracles In Motion (PowerShell)
|
||
|
|
# This script helps configure Cloudflare for the production deployment
|
||
|
|
|
||
|
|
param(
|
||
|
|
[Parameter(Mandatory=$false)]
|
||
|
|
[string]$Domain = "mim4u.org",
|
||
|
|
|
||
|
|
[Parameter(Mandatory=$false)]
|
||
|
|
[string]$StaticWebAppName = "",
|
||
|
|
|
||
|
|
[Parameter(Mandatory=$false)]
|
||
|
|
[string]$AzureResourceGroup = "rg-miraclesinmotion-prod",
|
||
|
|
|
||
|
|
[Parameter(Mandatory=$false)]
|
||
|
|
[string]$CloudflareApiToken = "",
|
||
|
|
|
||
|
|
[Parameter(Mandatory=$false)]
|
||
|
|
[string]$CloudflareZoneId = ""
|
||
|
|
)
|
||
|
|
|
||
|
|
$ErrorActionPreference = "Stop"
|
||
|
|
|
||
|
|
Write-Host "🌐 Cloudflare Setup Script" -ForegroundColor Green
|
||
|
|
Write-Host "==================================" -ForegroundColor Green
|
||
|
|
Write-Host ""
|
||
|
|
|
||
|
|
# Check if Azure CLI is installed
|
||
|
|
if (-not (Get-Command "az" -ErrorAction SilentlyContinue)) {
|
||
|
|
Write-Host "❌ Azure CLI not found. Please install it first." -ForegroundColor Red
|
||
|
|
Write-Host "Install from: https://docs.microsoft.com/cli/azure/install-azure-cli" -ForegroundColor Yellow
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
|
||
|
|
# Get Azure Static Web App default hostname
|
||
|
|
Write-Host "📋 Getting Azure Static Web App information..." -ForegroundColor Cyan
|
||
|
|
|
||
|
|
if ([string]::IsNullOrEmpty($StaticWebAppName)) {
|
||
|
|
# Try to find Static Web App
|
||
|
|
$swa = az staticwebapp list --resource-group $AzureResourceGroup --output json | ConvertFrom-Json | Select-Object -First 1
|
||
|
|
if ($swa) {
|
||
|
|
$StaticWebAppName = $swa.name
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if ([string]::IsNullOrEmpty($StaticWebAppName)) {
|
||
|
|
Write-Host "❌ Static Web App name not specified and could not be found." -ForegroundColor Red
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
|
||
|
|
$azureStaticWebAppUrl = az staticwebapp show `
|
||
|
|
--name $StaticWebAppName `
|
||
|
|
--resource-group $AzureResourceGroup `
|
||
|
|
--query "defaultHostname" -o tsv
|
||
|
|
|
||
|
|
if ([string]::IsNullOrEmpty($azureStaticWebAppUrl)) {
|
||
|
|
Write-Host "❌ Could not find Static Web App." -ForegroundColor Red
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
|
||
|
|
Write-Host "✅ Found Static Web App: $azureStaticWebAppUrl" -ForegroundColor Green
|
||
|
|
Write-Host ""
|
||
|
|
|
||
|
|
# Get Cloudflare API Token
|
||
|
|
if ([string]::IsNullOrEmpty($CloudflareApiToken)) {
|
||
|
|
$CloudflareApiToken = Read-Host "Enter your Cloudflare API Token"
|
||
|
|
}
|
||
|
|
|
||
|
|
if ([string]::IsNullOrEmpty($CloudflareApiToken)) {
|
||
|
|
Write-Host "❌ Cloudflare API Token is required." -ForegroundColor Red
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
|
||
|
|
# Get Cloudflare Zone ID
|
||
|
|
if ([string]::IsNullOrEmpty($CloudflareZoneId)) {
|
||
|
|
Write-Host "Looking up Zone ID for $Domain..." -ForegroundColor Cyan
|
||
|
|
|
||
|
|
$headers = @{
|
||
|
|
"Authorization" = "Bearer $CloudflareApiToken"
|
||
|
|
"Content-Type" = "application/json"
|
||
|
|
}
|
||
|
|
|
||
|
|
$zoneResponse = Invoke-RestMethod -Uri "https://api.cloudflare.com/client/v4/zones?name=$Domain" -Method Get -Headers $headers
|
||
|
|
|
||
|
|
if ($zoneResponse.success -and $zoneResponse.result.Count -gt 0) {
|
||
|
|
$CloudflareZoneId = $zoneResponse.result[0].id
|
||
|
|
Write-Host "✅ Zone ID: $CloudflareZoneId" -ForegroundColor Green
|
||
|
|
} else {
|
||
|
|
Write-Host "❌ Could not find Zone ID for $Domain" -ForegroundColor Red
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
Write-Host ""
|
||
|
|
|
||
|
|
# Function to create DNS record
|
||
|
|
function New-CloudflareDnsRecord {
|
||
|
|
param(
|
||
|
|
[string]$RecordType,
|
||
|
|
[string]$RecordName,
|
||
|
|
[string]$RecordContent,
|
||
|
|
[bool]$Proxied = $true
|
||
|
|
)
|
||
|
|
|
||
|
|
Write-Host "Creating DNS record: $RecordName.$Domain -> $RecordContent" -ForegroundColor Cyan
|
||
|
|
|
||
|
|
$headers = @{
|
||
|
|
"Authorization" = "Bearer $CloudflareApiToken"
|
||
|
|
"Content-Type" = "application/json"
|
||
|
|
}
|
||
|
|
|
||
|
|
$body = @{
|
||
|
|
type = $RecordType
|
||
|
|
name = $RecordName
|
||
|
|
content = $RecordContent
|
||
|
|
proxied = $Proxied
|
||
|
|
ttl = 1
|
||
|
|
} | ConvertTo-Json
|
||
|
|
|
||
|
|
try {
|
||
|
|
$response = Invoke-RestMethod -Uri "https://api.cloudflare.com/client/v4/zones/$CloudflareZoneId/dns_records" -Method Post -Headers $headers -Body $body
|
||
|
|
|
||
|
|
if ($response.success) {
|
||
|
|
Write-Host "✅ DNS record created successfully" -ForegroundColor Green
|
||
|
|
return $true
|
||
|
|
} else {
|
||
|
|
$errors = $response.errors | ForEach-Object { $_.message } -Join ", "
|
||
|
|
Write-Host "⚠️ DNS record may already exist or error: $errors" -ForegroundColor Yellow
|
||
|
|
return $false
|
||
|
|
}
|
||
|
|
} catch {
|
||
|
|
Write-Host "⚠️ Error creating DNS record: $($_.Exception.Message)" -ForegroundColor Yellow
|
||
|
|
return $false
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# Create CNAME records
|
||
|
|
Write-Host "📝 Creating DNS Records..." -ForegroundColor Green
|
||
|
|
New-CloudflareDnsRecord -RecordType "CNAME" -RecordName "www" -RecordContent $azureStaticWebAppUrl -Proxied $true
|
||
|
|
New-CloudflareDnsRecord -RecordType "CNAME" -RecordName "@" -RecordContent $azureStaticWebAppUrl -Proxied $true
|
||
|
|
Write-Host ""
|
||
|
|
|
||
|
|
# Configure SSL/TLS settings
|
||
|
|
Write-Host "🔒 Configuring SSL/TLS..." -ForegroundColor Green
|
||
|
|
|
||
|
|
$headers = @{
|
||
|
|
"Authorization" = "Bearer $CloudflareApiToken"
|
||
|
|
"Content-Type" = "application/json"
|
||
|
|
}
|
||
|
|
|
||
|
|
$sslBody = @{
|
||
|
|
value = "full"
|
||
|
|
} | ConvertTo-Json
|
||
|
|
|
||
|
|
try {
|
||
|
|
$sslResponse = Invoke-RestMethod -Uri "https://api.cloudflare.com/client/v4/zones/$CloudflareZoneId/settings/ssl" -Method Patch -Headers $headers -Body $sslBody
|
||
|
|
if ($sslResponse.success) {
|
||
|
|
Write-Host "✅ SSL mode set to Full" -ForegroundColor Green
|
||
|
|
}
|
||
|
|
} catch {
|
||
|
|
Write-Host "⚠️ Could not update SSL settings: $($_.Exception.Message)" -ForegroundColor Yellow
|
||
|
|
}
|
||
|
|
|
||
|
|
$httpsBody = @{
|
||
|
|
value = "on"
|
||
|
|
} | ConvertTo-Json
|
||
|
|
|
||
|
|
try {
|
||
|
|
$httpsResponse = Invoke-RestMethod -Uri "https://api.cloudflare.com/client/v4/zones/$CloudflareZoneId/settings/always_use_https" -Method Patch -Headers $headers -Body $httpsBody
|
||
|
|
if ($httpsResponse.success) {
|
||
|
|
Write-Host "✅ Always Use HTTPS enabled" -ForegroundColor Green
|
||
|
|
}
|
||
|
|
} catch {
|
||
|
|
Write-Host "⚠️ Could not enable Always Use HTTPS: $($_.Exception.Message)" -ForegroundColor Yellow
|
||
|
|
}
|
||
|
|
|
||
|
|
Write-Host ""
|
||
|
|
|
||
|
|
# Configure Security Settings
|
||
|
|
Write-Host "🛡️ Configuring Security Settings..." -ForegroundColor Green
|
||
|
|
|
||
|
|
$securityBody = @{
|
||
|
|
value = "medium"
|
||
|
|
} | ConvertTo-Json
|
||
|
|
|
||
|
|
try {
|
||
|
|
$securityResponse = Invoke-RestMethod -Uri "https://api.cloudflare.com/client/v4/zones/$CloudflareZoneId/settings/security_level" -Method Patch -Headers $headers -Body $securityBody
|
||
|
|
if ($securityResponse.success) {
|
||
|
|
Write-Host "✅ Security level set to Medium" -ForegroundColor Green
|
||
|
|
}
|
||
|
|
} catch {
|
||
|
|
Write-Host "⚠️ Could not update security level: $($_.Exception.Message)" -ForegroundColor Yellow
|
||
|
|
}
|
||
|
|
|
||
|
|
$browserCheckBody = @{
|
||
|
|
value = "on"
|
||
|
|
} | ConvertTo-Json
|
||
|
|
|
||
|
|
try {
|
||
|
|
$browserCheckResponse = Invoke-RestMethod -Uri "https://api.cloudflare.com/client/v4/zones/$CloudflareZoneId/settings/browser_check" -Method Patch -Headers $headers -Body $browserCheckBody
|
||
|
|
if ($browserCheckResponse.success) {
|
||
|
|
Write-Host "✅ Browser Integrity Check enabled" -ForegroundColor Green
|
||
|
|
}
|
||
|
|
} catch {
|
||
|
|
Write-Host "⚠️ Could not enable browser check: $($_.Exception.Message)" -ForegroundColor Yellow
|
||
|
|
}
|
||
|
|
|
||
|
|
Write-Host ""
|
||
|
|
|
||
|
|
# Configure Speed Settings
|
||
|
|
Write-Host "⚡ Configuring Speed Settings..." -ForegroundColor Green
|
||
|
|
|
||
|
|
$minifyBody = @{
|
||
|
|
value = @{
|
||
|
|
css = "on"
|
||
|
|
html = "on"
|
||
|
|
js = "on"
|
||
|
|
}
|
||
|
|
} | ConvertTo-Json -Depth 3
|
||
|
|
|
||
|
|
try {
|
||
|
|
$minifyResponse = Invoke-RestMethod -Uri "https://api.cloudflare.com/client/v4/zones/$CloudflareZoneId/settings/minify" -Method Patch -Headers $headers -Body $minifyBody
|
||
|
|
if ($minifyResponse.success) {
|
||
|
|
Write-Host "✅ Minification enabled" -ForegroundColor Green
|
||
|
|
}
|
||
|
|
} catch {
|
||
|
|
Write-Host "⚠️ Could not enable minification: $($_.Exception.Message)" -ForegroundColor Yellow
|
||
|
|
}
|
||
|
|
|
||
|
|
$brotliBody = @{
|
||
|
|
value = "on"
|
||
|
|
} | ConvertTo-Json
|
||
|
|
|
||
|
|
try {
|
||
|
|
$brotliResponse = Invoke-RestMethod -Uri "https://api.cloudflare.com/client/v4/zones/$CloudflareZoneId/settings/brotli" -Method Patch -Headers $headers -Body $brotliBody
|
||
|
|
if ($brotliResponse.success) {
|
||
|
|
Write-Host "✅ Brotli compression enabled" -ForegroundColor Green
|
||
|
|
}
|
||
|
|
} catch {
|
||
|
|
Write-Host "⚠️ Could not enable Brotli: $($_.Exception.Message)" -ForegroundColor Yellow
|
||
|
|
}
|
||
|
|
|
||
|
|
Write-Host ""
|
||
|
|
|
||
|
|
# Add custom domain to Azure Static Web App
|
||
|
|
Write-Host "🔗 Adding Custom Domain to Azure Static Web App..." -ForegroundColor Green
|
||
|
|
|
||
|
|
try {
|
||
|
|
az staticwebapp hostname set `
|
||
|
|
--name $StaticWebAppName `
|
||
|
|
--resource-group $AzureResourceGroup `
|
||
|
|
--hostname $Domain 2>$null | Out-Null
|
||
|
|
Write-Host "✅ Custom domain $Domain added" -ForegroundColor Green
|
||
|
|
} catch {
|
||
|
|
Write-Host "⚠️ Domain may already be added or DNS not ready" -ForegroundColor Yellow
|
||
|
|
}
|
||
|
|
|
||
|
|
try {
|
||
|
|
az staticwebapp hostname set `
|
||
|
|
--name $StaticWebAppName `
|
||
|
|
--resource-group $AzureResourceGroup `
|
||
|
|
--hostname "www.$Domain" 2>$null | Out-Null
|
||
|
|
Write-Host "✅ Custom domain www.$Domain added" -ForegroundColor Green
|
||
|
|
} catch {
|
||
|
|
Write-Host "⚠️ Domain may already be added or DNS not ready" -ForegroundColor Yellow
|
||
|
|
}
|
||
|
|
|
||
|
|
Write-Host ""
|
||
|
|
|
||
|
|
# Summary
|
||
|
|
Write-Host "✅ Cloudflare Setup Complete!" -ForegroundColor Green
|
||
|
|
Write-Host "==================================" -ForegroundColor Green
|
||
|
|
Write-Host ""
|
||
|
|
Write-Host "Next Steps:"
|
||
|
|
Write-Host "1. Verify DNS propagation (may take 24-48 hours)"
|
||
|
|
Write-Host "2. Verify SSL certificates are provisioned"
|
||
|
|
Write-Host "3. Test the website at https://$Domain"
|
||
|
|
Write-Host "4. Monitor Cloudflare analytics"
|
||
|
|
Write-Host ""
|
||
|
|
Write-Host "DNS Records Created:"
|
||
|
|
Write-Host " - www.$Domain -> $azureStaticWebAppUrl"
|
||
|
|
Write-Host " - $Domain -> $azureStaticWebAppUrl"
|
||
|
|
Write-Host ""
|
||
|
|
Write-Host "Cloudflare Settings:"
|
||
|
|
Write-Host " - SSL Mode: Full (strict)"
|
||
|
|
Write-Host " - Always Use HTTPS: Enabled"
|
||
|
|
Write-Host " - Security Level: Medium"
|
||
|
|
Write-Host " - Minification: Enabled"
|
||
|
|
Write-Host " - Brotli Compression: Enabled"
|
||
|
|
Write-Host ""
|
||
|
|
|