Deploy to production - ensure all endpoints operational
This commit is contained in:
272
scripts/setup-azure-entra.ps1
Normal file
272
scripts/setup-azure-entra.ps1
Normal file
@@ -0,0 +1,272 @@
|
||||
# MS Entra (Azure AD) Setup Script for Miracles In Motion (PowerShell)
|
||||
# This script helps configure Azure AD authentication for the application
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$AppName = "Miracles In Motion Web App",
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$Domain = "mim4u.org",
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$StaticWebAppName = "",
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$AzureResourceGroup = "rg-miraclesinmotion-prod",
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$KeyVaultName = ""
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
Write-Host "🔐 MS Entra (Azure AD) 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
|
||||
}
|
||||
|
||||
# Check if logged in to Azure
|
||||
Write-Host "📋 Checking Azure login status..." -ForegroundColor Cyan
|
||||
$account = az account show --output json 2>$null | ConvertFrom-Json
|
||||
if (-not $account) {
|
||||
Write-Host "⚠️ Not logged in to Azure. Please log in..." -ForegroundColor Yellow
|
||||
az login
|
||||
$account = az account show --output json | ConvertFrom-Json
|
||||
}
|
||||
Write-Host "✅ Logged in as: $($account.user.name)" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
# Get Azure Static Web App URL
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
$azureStaticWebAppUrl = ""
|
||||
if (-not [string]::IsNullOrEmpty($StaticWebAppName)) {
|
||||
$azureStaticWebAppUrl = az staticwebapp show `
|
||||
--name $StaticWebAppName `
|
||||
--resource-group $AzureResourceGroup `
|
||||
--query "defaultHostname" -o tsv 2>$null
|
||||
|
||||
if ($azureStaticWebAppUrl) {
|
||||
$azureStaticWebAppUrl = "https://$azureStaticWebAppUrl"
|
||||
Write-Host "✅ Static Web App URL: $azureStaticWebAppUrl" -ForegroundColor Green
|
||||
}
|
||||
} else {
|
||||
Write-Host "⚠️ Static Web App not found. Using default URL format." -ForegroundColor Yellow
|
||||
$azureStaticWebAppUrl = "https://${StaticWebAppName}.azurestaticapps.net"
|
||||
}
|
||||
|
||||
$productionUrl = "https://$Domain"
|
||||
$wwwUrl = "https://www.$Domain"
|
||||
|
||||
Write-Host ""
|
||||
|
||||
# Get Tenant ID
|
||||
$tenantId = $account.tenantId
|
||||
Write-Host "✅ Tenant ID: $tenantId" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
# Check if app registration already exists
|
||||
Write-Host "🔍 Checking for existing app registration..." -ForegroundColor Cyan
|
||||
$existingApp = az ad app list --display-name $AppName --output json | ConvertFrom-Json | Select-Object -First 1
|
||||
|
||||
if ($existingApp) {
|
||||
Write-Host "⚠️ App registration already exists: $($existingApp.appId)" -ForegroundColor Yellow
|
||||
$updateApp = Read-Host "Do you want to update it? (y/n)"
|
||||
if ($updateApp -ne "y") {
|
||||
$appId = $existingApp.appId
|
||||
Write-Host "✅ Using existing app registration" -ForegroundColor Green
|
||||
} else {
|
||||
$appId = $existingApp.appId
|
||||
Write-Host "📝 Updating app registration..." -ForegroundColor Cyan
|
||||
}
|
||||
} else {
|
||||
# Create app registration
|
||||
Write-Host "📝 Creating app registration..." -ForegroundColor Cyan
|
||||
$appId = az ad app create `
|
||||
--display-name $AppName `
|
||||
--sign-in-audience "AzureADMultipleOrgs" `
|
||||
--web-redirect-uris $productionUrl $wwwUrl $azureStaticWebAppUrl `
|
||||
--query "appId" -o tsv
|
||||
|
||||
Write-Host "✅ App registration created: $appId" -ForegroundColor Green
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
|
||||
# Update redirect URIs
|
||||
Write-Host "📝 Updating redirect URIs..." -ForegroundColor Cyan
|
||||
az ad app update --id $appId `
|
||||
--web-redirect-uris $productionUrl $wwwUrl $azureStaticWebAppUrl `
|
||||
--enable-id-token-issuance true `
|
||||
--enable-access-token-issuance false | Out-Null
|
||||
|
||||
Write-Host "✅ Redirect URIs updated" -ForegroundColor Green
|
||||
Write-Host " - $productionUrl"
|
||||
Write-Host " - $wwwUrl"
|
||||
Write-Host " - $azureStaticWebAppUrl"
|
||||
Write-Host ""
|
||||
|
||||
# Configure API permissions
|
||||
Write-Host "📝 Configuring API permissions..." -ForegroundColor Cyan
|
||||
|
||||
$graphPermissions = @(
|
||||
"User.Read",
|
||||
"User.ReadBasic.All",
|
||||
"email",
|
||||
"openid",
|
||||
"profile"
|
||||
)
|
||||
|
||||
foreach ($permission in $graphPermissions) {
|
||||
Write-Host " Adding permission: $permission" -ForegroundColor Gray
|
||||
$permissionId = az ad sp show --id "00000003-0000-0000-c000-000000000000" --query "oauth2PermissionScopes[?value=='$permission'].id" -o tsv
|
||||
if ($permissionId) {
|
||||
az ad app permission add `
|
||||
--id $appId `
|
||||
--api "00000003-0000-0000-c000-000000000000" `
|
||||
--api-permissions "${permissionId}=Scope" 2>$null | Out-Null
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "✅ API permissions configured" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
# Create service principal
|
||||
Write-Host "📝 Creating service principal..." -ForegroundColor Cyan
|
||||
$spId = az ad sp create --id $appId --query "id" -o tsv 2>$null
|
||||
if (-not $spId) {
|
||||
$spId = az ad sp show --id $appId --query "id" -o tsv
|
||||
}
|
||||
|
||||
Write-Host "✅ Service principal created: $spId" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
# Grant admin consent
|
||||
Write-Host "📝 Granting admin consent for API permissions..." -ForegroundColor Cyan
|
||||
$hasAdmin = Read-Host "Do you have admin privileges to grant consent? (y/n)"
|
||||
|
||||
if ($hasAdmin -eq "y") {
|
||||
az ad app permission admin-consent --id $appId 2>$null
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host "✅ Admin consent granted" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "⚠️ Could not grant admin consent. You may need to do this manually." -ForegroundColor Yellow
|
||||
Write-Host " Go to: Azure Portal → Microsoft Entra ID → App registrations → $AppName → API permissions → Grant admin consent" -ForegroundColor Yellow
|
||||
}
|
||||
} else {
|
||||
Write-Host "⚠️ Skipping admin consent. Please grant consent manually in Azure Portal." -ForegroundColor Yellow
|
||||
Write-Host " Go to: Azure Portal → Microsoft Entra ID → App registrations → $AppName → API permissions → Grant admin consent" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
|
||||
# Create client secret
|
||||
Write-Host "📝 Client Secret Configuration..." -ForegroundColor Cyan
|
||||
$createSecret = Read-Host "Do you want to create a client secret? (y/n)"
|
||||
|
||||
$clientSecret = ""
|
||||
if ($createSecret -eq "y") {
|
||||
$secretName = "Miracles In Motion Secret $(Get-Date -Format 'yyyyMMdd')"
|
||||
$clientSecret = az ad app credential reset --id $appId --display-name $secretName --years 2 --query "password" -o tsv
|
||||
Write-Host "✅ Client secret created" -ForegroundColor Green
|
||||
Write-Host "⚠️ IMPORTANT: Save this secret now - it won't be shown again!" -ForegroundColor Red
|
||||
Write-Host "Secret: $clientSecret" -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
Read-Host "Press Enter to continue after saving the secret..."
|
||||
} else {
|
||||
Write-Host "⚠️ Skipping client secret creation" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
|
||||
# Store configuration in Key Vault
|
||||
Write-Host "📝 Storing configuration in Key Vault..." -ForegroundColor Cyan
|
||||
|
||||
if ([string]::IsNullOrEmpty($KeyVaultName)) {
|
||||
$KeyVaultName = az keyvault list --resource-group $AzureResourceGroup --query "[0].name" -o tsv 2>$null
|
||||
}
|
||||
|
||||
if ($KeyVaultName) {
|
||||
Write-Host "Storing in Key Vault: $KeyVaultName" -ForegroundColor Gray
|
||||
|
||||
az keyvault secret set --vault-name $KeyVaultName --name "azure-client-id" --value $appId 2>$null | Out-Null
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host "✅ Client ID stored" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "⚠️ Could not store Client ID" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
az keyvault secret set --vault-name $KeyVaultName --name "azure-tenant-id" --value $tenantId 2>$null | Out-Null
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host "✅ Tenant ID stored" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "⚠️ Could not store Tenant ID" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
if ($clientSecret) {
|
||||
az keyvault secret set --vault-name $KeyVaultName --name "azure-client-secret" --value $clientSecret 2>$null | Out-Null
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host "✅ Client Secret stored" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "⚠️ Could not store Client Secret" -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Write-Host "⚠️ Key Vault not found. Skipping secret storage." -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
|
||||
# Summary
|
||||
Write-Host "✅ MS Entra Setup Complete!" -ForegroundColor Green
|
||||
Write-Host "==================================" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Write-Host "Configuration Summary:"
|
||||
Write-Host " App Registration ID: $appId"
|
||||
Write-Host " Tenant ID: $tenantId"
|
||||
Write-Host " Service Principal ID: $spId"
|
||||
Write-Host ""
|
||||
Write-Host "Redirect URIs:"
|
||||
Write-Host " - $productionUrl"
|
||||
Write-Host " - $wwwUrl"
|
||||
Write-Host " - $azureStaticWebAppUrl"
|
||||
Write-Host ""
|
||||
Write-Host "Next Steps:"
|
||||
Write-Host "1. Assign users to app roles in Azure Portal"
|
||||
Write-Host "2. Update staticwebapp.config.json with authentication configuration"
|
||||
Write-Host "3. Update application code to use Azure AD authentication"
|
||||
Write-Host "4. Test authentication flow"
|
||||
Write-Host ""
|
||||
Write-Host "Azure Portal Links:"
|
||||
Write-Host " App Registration: https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/~/Overview/appId/$appId"
|
||||
Write-Host " API Permissions: https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/~/CallAnAPI/appId/$appId"
|
||||
Write-Host ""
|
||||
|
||||
# Export variables
|
||||
$configContent = @"
|
||||
# Azure AD Configuration
|
||||
AZURE_CLIENT_ID=$appId
|
||||
AZURE_TENANT_ID=$tenantId
|
||||
AZURE_CLIENT_SECRET=$clientSecret
|
||||
AZURE_STATIC_WEB_APP_URL=$azureStaticWebAppUrl
|
||||
AZURE_PRODUCTION_URL=$productionUrl
|
||||
"@
|
||||
|
||||
$configContent | Out-File -FilePath ".azure-entra-config.env" -Encoding UTF8
|
||||
Write-Host "✅ Configuration saved to .azure-entra-config.env" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
Reference in New Issue
Block a user