Files
miracles_in_motion/docs/DEPLOYMENT_PREREQUISITES.md

20 KiB

🚀 Deployment Prerequisites Guide

Complete guide for setting up MS Azure, MS Entra, Cloudflare, and all other services required for production deployment.

📋 Table of Contents

  1. Azure Setup
  2. MS Entra (Azure AD) Configuration
  3. Cloudflare Configuration
  4. Stripe Configuration
  5. Environment Variables
  6. Pre-Deployment Checklist
  7. Post-Deployment Verification

1. Azure Setup

1.1 Prerequisites

  • Azure subscription with Contributor or Owner role
  • Azure CLI installed and configured
  • Bicep CLI installed (optional, for local validation)
  • PowerShell 7+ (for deployment scripts)

1.2 Initial Azure Configuration

Login to Azure

# Login to Azure
az login

# Verify subscription
az account show

# Set default subscription (if multiple)
az account set --subscription "Your Subscription ID"

Create Resource Group

# Create resource group for production
az group create \
  --name rg-miraclesinmotion-prod \
  --location eastus2

# Verify resource group
az group show --name rg-miraclesinmotion-prod

1.3 Required Azure Services

The infrastructure deployment will create:

  • Azure Static Web Apps (Standard SKU) - Frontend hosting
  • Azure Functions (Premium EP1) - Backend API
  • Azure Cosmos DB - Database
  • Azure Key Vault - Secrets management
  • Azure Application Insights - Monitoring
  • Log Analytics Workspace - Logging
  • Azure SignalR - Real-time communications
  • Storage Account - Function app storage

1.4 Deploy Infrastructure

# Navigate to infrastructure directory
cd infrastructure

# Deploy production infrastructure
az deployment group create \
  --resource-group rg-miraclesinmotion-prod \
  --template-file main-production.bicep \
  --parameters main-production.parameters.json \
  --parameters stripePublicKey="pk_live_YOUR_KEY" \
  --parameters customDomainName="miraclesinmotion.org" \
  --parameters enableCustomDomain=true

# Note: Replace pk_live_YOUR_KEY with your actual Stripe public key

1.5 Get Deployment Outputs

# Get deployment outputs
az deployment group show \
  --resource-group rg-miraclesinmotion-prod \
  --name deployment-name \
  --query properties.outputs

Important Outputs:

  • staticWebAppName - Static Web App resource name
  • staticWebAppUrl - Default URL for Static Web App
  • functionAppName - Function App resource name
  • keyVaultName - Key Vault resource name
  • appInsightsName - Application Insights resource name

2. MS Entra (Azure AD) Configuration

2.1 Create App Registration

Using Azure Portal

  1. Navigate to Azure PortalMicrosoft Entra IDApp registrations

  2. Click + New registration

  3. Configure:

    • Name: Miracles In Motion Web App
    • Supported account types: Accounts in any organizational directory and personal Microsoft accounts
    • Redirect URI:
      • Type: Single-page application (SPA)
      • URI: https://miraclesinmotion.org (production)
      • URI: https://YOUR_STATIC_WEB_APP.azurestaticapps.net (staging)
  4. Click Register

Using Azure CLI

# Create app registration
az ad app create \
  --display-name "Miracles In Motion Web App" \
  --sign-in-audience "AzureADMultipleOrgs" \
  --web-redirect-uris "https://miraclesinmotion.org" "https://www.miraclesinmotion.org"

# Get app registration ID
APP_ID=$(az ad app list --display-name "Miracles In Motion Web App" --query "[0].appId" -o tsv)
echo "App ID: $APP_ID"

2.2 Configure Authentication

  1. In the app registration, go to Authentication
  2. Enable ID tokens (used for implicit and hybrid flows)
  3. Add redirect URIs:
    • https://miraclesinmotion.org
    • https://www.miraclesinmotion.org
    • https://YOUR_STATIC_WEB_APP.azurestaticapps.net
  4. Under Implicit grant and hybrid flows, enable:
    • ID tokens
  5. Save changes

2.3 Configure API Permissions

  1. Go to API permissions
  2. Click + Add a permission
  3. Select Microsoft Graph
  4. Add the following Delegated permissions:
    • User.Read - Read user profile
    • User.ReadBasic.All - Read all users' basic profiles
    • email - View users' email address
    • openid - Sign users in
    • profile - View users' basic profile
  5. Click Add permissions
  6. Click Grant admin consent (if you have admin rights)

2.4 Create Client Secret (Optional - for server-side flows)

# Create client secret (valid for 24 months)
az ad app credential reset \
  --id $APP_ID \
  --display-name "Miracles In Motion Secret" \
  --years 2

# Save the secret value immediately - it won't be shown again!

2.5 Configure App Roles

  1. Go to App roles+ Create app role

  2. Create roles:

    • Display name: Admin

      • Allowed member types: Users/Groups
      • Value: Admin
      • Description: Administrator access to all features
    • Display name: Volunteer

      • Allowed member types: Users/Groups
      • Value: Volunteer
      • Description: Volunteer access to assigned tasks
    • Display name: Resource

      • Allowed member types: Users/Groups
      • Value: Resource
      • Description: Resource provider access
  3. Save each role

2.6 Assign Users to Roles

# Get user object ID
USER_ID=$(az ad user show --id "user@domain.com" --query "id" -o tsv)

# Get app role ID (Admin role)
ROLE_ID=$(az ad app show --id $APP_ID --query "appRoles[?value=='Admin'].id" -o tsv)

# Assign user to role
az ad app assignment create \
  --app-id $APP_ID \
  --principal-id $USER_ID \
  --role-id $ROLE_ID

2.7 Configure Static Web App Authentication

  1. Navigate to Static Web AppAuthentication
  2. Click Add identity provider
  3. Select Microsoft
  4. Configure:
    • App registration: Select your app registration
    • App ID: Your app registration ID
    • App secret setting name: MICROSOFT_CLIENT_SECRET (optional)
  5. Save

Using Azure CLI

# Get Static Web App resource ID
SWA_ID=$(az staticwebapp show \
  --name YOUR_STATIC_WEB_APP_NAME \
  --resource-group rg-miraclesinmotion-prod \
  --query "id" -o tsv)

# Configure Microsoft identity provider
az staticwebapp identity assign \
  --name YOUR_STATIC_WEB_APP_NAME \
  --resource-group rg-miraclesinmotion-prod

# Note: Static Web Apps authentication is configured via Azure Portal
# or through the staticwebapp.config.json file

2.8 Update staticwebapp.config.json

The staticwebapp.config.json file should include authentication configuration:

{
  "routes": [
    {
      "route": "/api/*",
      "allowedRoles": ["anonymous", "authenticated"]
    },
    {
      "route": "/admin/*",
      "allowedRoles": ["Admin"]
    },
    {
      "route": "/volunteer/*",
      "allowedRoles": ["Volunteer", "Admin"]
    },
    {
      "route": "/*",
      "rewrite": "/index.html"
    }
  ],
  "auth": {
    "identityProviders": {
      "azureActiveDirectory": {
        "registration": {
          "openIdIssuer": "https://login.microsoftonline.com/{tenantId}/v2.0",
          "clientIdSettingName": "AZURE_CLIENT_ID",
          "clientSecretSettingName": "AZURE_CLIENT_SECRET"
        }
      }
    }
  },
  "navigationFallback": {
    "rewrite": "/index.html",
    "exclude": ["/api/*", "/admin/*"]
  }
}

2.9 Store Configuration in Key Vault

# Store Azure AD configuration in Key Vault
az keyvault secret set \
  --vault-name YOUR_KEY_VAULT_NAME \
  --name "azure-client-id" \
  --value "$APP_ID"

az keyvault secret set \
  --vault-name YOUR_KEY_VAULT_NAME \
  --name "azure-client-secret" \
  --value "YOUR_CLIENT_SECRET"

az keyvault secret set \
  --vault-name YOUR_KEY_VAULT_NAME \
  --name "azure-tenant-id" \
  --value "$(az account show --query tenantId -o tsv)"

3. Cloudflare Configuration

3.1 Prerequisites

  • Cloudflare account
  • Domain registered and added to Cloudflare
  • DNS management access

3.2 Add Domain to Cloudflare

  1. Log in to Cloudflare Dashboard
  2. Click Add a site
  3. Enter your domain: miraclesinmotion.org
  4. Select a plan (Free plan is sufficient for basic needs)
  5. Cloudflare will scan your existing DNS records

3.3 Update Nameservers

  1. Copy the nameservers provided by Cloudflare
  2. Update your domain registrar with these nameservers
  3. Wait for DNS propagation (24-48 hours)

3.4 Configure DNS Records

Add CNAME Records

  1. Go to DNSRecords
  2. Add the following records:
Type Name Content Proxy TTL
CNAME www YOUR_STATIC_WEB_APP.azurestaticapps.net Proxied Auto
CNAME @ YOUR_STATIC_WEB_APP.azurestaticapps.net Proxied Auto

Note: Replace YOUR_STATIC_WEB_APP with your actual Static Web App name.

Verify DNS Configuration

# Check DNS records
dig miraclesinmotion.org
dig www.miraclesinmotion.org

# Check Cloudflare proxy status
curl -I https://miraclesinmotion.org
# Look for "CF-Cache-Status" header

3.5 Configure SSL/TLS

  1. Go to SSL/TLSOverview
  2. Select Full (strict) encryption mode
  3. Enable Always Use HTTPS
  4. Enable Automatic HTTPS Rewrites

3.6 Configure Page Rules

  1. Go to RulesPage Rules
  2. Create rules:

Rule 1: Force HTTPS

  • URL: *miraclesinmotion.org/*
  • Settings:
    • Always Use HTTPS: On
    • SSL: Full (strict)

Rule 2: Cache Static Assets

  • URL: *miraclesinmotion.org/assets/*
  • Settings:
    • Cache Level: Cache Everything
    • Edge Cache TTL: 1 month

3.7 Configure Security Settings

  1. Go to SecuritySettings
  2. Configure:
    • Security Level: Medium
    • Challenge Passage: 30 minutes
    • Browser Integrity Check: On
    • Privacy Pass Support: On

3.8 Configure Firewall Rules

  1. Go to SecurityWAFCustom rules
  2. Create rules to block malicious traffic:

Rule: Block Bad Bots

  • Expression: (http.user_agent contains "bot" and not http.user_agent contains "Googlebot")
  • Action: Block

Rule: Rate Limiting

  • Expression: (http.request.uri.path contains "/api/")
  • Action: Challenge
  • Rate: 100 requests per minute

3.9 Configure Speed Optimization

  1. Go to SpeedOptimization
  2. Enable:
    • Auto Minify (JavaScript, CSS, HTML)
    • Brotli compression
    • Rocket Loader (optional)
    • Mirage (optional, for mobile)

3.10 Configure Analytics

  1. Go to AnalyticsWeb Analytics
  2. Enable Web Analytics for your domain
  3. Add the tracking script to your application (optional)

3.11 Configure Custom Domain in Azure

After DNS is configured:

# Add custom domain to Static Web App
az staticwebapp hostname set \
  --name YOUR_STATIC_WEB_APP_NAME \
  --resource-group rg-miraclesinmotion-prod \
  --hostname "miraclesinmotion.org"

az staticwebapp hostname set \
  --name YOUR_STATIC_WEB_APP_NAME \
  --resource-group rg-miraclesinmotion-prod \
  --hostname "www.miraclesinmotion.org"

Note: Azure will automatically provision SSL certificates for custom domains.

3.12 Verify Cloudflare Configuration

# Test DNS resolution
nslookup miraclesinmotion.org
nslookup www.miraclesinmotion.org

# Test HTTPS
curl -I https://miraclesinmotion.org

# Test Cloudflare headers
curl -I https://miraclesinmotion.org | grep -i "cf-"

# Expected headers:
# CF-Cache-Status: DYNAMIC
# CF-Ray: [unique-id]
# Server: cloudflare

4. Stripe Configuration

4.1 Create Stripe Account

  1. Go to Stripe Dashboard
  2. Create account or log in
  3. Complete account verification

4.2 Get API Keys

  1. Go to DevelopersAPI keys
  2. Copy:
    • Publishable key (starts with pk_live_)
    • Secret key (starts with sk_live_) - Keep this secret!

4.3 Configure Webhooks

  1. Go to DevelopersWebhooks
  2. Click + Add endpoint
  3. Configure:
    • Endpoint URL: https://miraclesinmotion.org/api/webhooks/stripe
    • Events to send: Select relevant events:
      • payment_intent.succeeded
      • payment_intent.payment_failed
      • charge.succeeded
      • charge.failed
  4. Copy the Webhook signing secret (starts with whsec_)

4.4 Store Stripe Secrets in Key Vault

# Store Stripe keys in Key Vault
az keyvault secret set \
  --vault-name YOUR_KEY_VAULT_NAME \
  --name "stripe-publishable-key" \
  --value "pk_live_YOUR_KEY"

az keyvault secret set \
  --vault-name YOUR_KEY_VAULT_NAME \
  --name "stripe-secret-key" \
  --value "sk_live_YOUR_KEY"

az keyvault secret set \
  --vault-name YOUR_KEY_VAULT_NAME \
  --name "stripe-webhook-secret" \
  --value "whsec_YOUR_SECRET"

4.5 Update Function App Settings

# Get secrets from Key Vault
STRIPE_SECRET=$(az keyvault secret show \
  --vault-name YOUR_KEY_VAULT_NAME \
  --name "stripe-secret-key" \
  --query "value" -o tsv)

# Update Function App settings
az functionapp config appsettings set \
  --name YOUR_FUNCTION_APP_NAME \
  --resource-group rg-miraclesinmotion-prod \
  --settings "STRIPE_SECRET_KEY=@Microsoft.KeyVault(SecretUri=https://YOUR_KEY_VAULT_NAME.vault.azure.net/secrets/stripe-secret-key/)"

5. Environment Variables

5.1 Create Environment File Template

Create .env.production file:

# Azure Configuration
AZURE_STATIC_WEB_APP_URL=https://miraclesinmotion.org
AZURE_FUNCTION_APP_URL=https://YOUR_FUNCTION_APP.azurewebsites.net
AZURE_CLIENT_ID=your-azure-client-id
AZURE_TENANT_ID=your-azure-tenant-id

# Stripe Configuration
VITE_STRIPE_PUBLISHABLE_KEY=pk_live_YOUR_KEY
STRIPE_SECRET_KEY=sk_live_YOUR_KEY
STRIPE_WEBHOOK_SECRET=whsec_YOUR_SECRET

# Cosmos DB Configuration
COSMOS_DATABASE_NAME=MiraclesInMotion
COSMOS_ENDPOINT=https://YOUR_COSMOS_ACCOUNT.documents.azure.com:443/

# Application Insights
APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=YOUR_KEY

# Key Vault
KEY_VAULT_URL=https://YOUR_KEY_VAULT_NAME.vault.azure.net/

# SignalR
SIGNALR_CONNECTION_STRING=Endpoint=https://YOUR_SIGNALR.service.signalr.net;AccessKey=YOUR_KEY;

# Custom Domain
CUSTOM_DOMAIN=miraclesinmotion.org

5.2 Update Static Web App Configuration

# Set environment variables for Static Web App
az staticwebapp appsettings set \
  --name YOUR_STATIC_WEB_APP_NAME \
  --resource-group rg-miraclesinmotion-prod \
  --setting-names "VITE_STRIPE_PUBLISHABLE_KEY=pk_live_YOUR_KEY" \
    "AZURE_CLIENT_ID=your-azure-client-id" \
    "AZURE_TENANT_ID=your-azure-tenant-id"

6. Pre-Deployment Checklist

6.1 Azure Checklist

  • Azure subscription created and active
  • Resource group created
  • Infrastructure deployed via Bicep
  • All Azure resources created successfully
  • Key Vault configured with secrets
  • Application Insights configured
  • Static Web App created
  • Function App created and configured
  • Cosmos DB database and containers created
  • RBAC permissions configured

6.2 MS Entra Checklist

  • App registration created
  • Redirect URIs configured
  • API permissions granted
  • App roles created (Admin, Volunteer, Resource)
  • Users assigned to roles
  • Client ID and Tenant ID recorded
  • Client secret created (if needed)
  • Static Web App authentication configured

6.3 Cloudflare Checklist

  • Domain added to Cloudflare
  • Nameservers updated at registrar
  • DNS records configured (CNAME for www and @)
  • SSL/TLS set to Full (strict)
  • Always Use HTTPS enabled
  • Page rules configured
  • Firewall rules configured
  • Security settings configured
  • Speed optimization enabled
  • Custom domain added to Azure Static Web App

6.4 Stripe Checklist

  • Stripe account created and verified
  • API keys obtained (publishable and secret)
  • Webhook endpoint configured
  • Webhook signing secret obtained
  • Secrets stored in Key Vault
  • Function App configured with Stripe keys

6.5 Application Checklist

  • Environment variables configured
  • staticwebapp.config.json updated
  • Authentication flow tested
  • API endpoints tested
  • Stripe integration tested
  • Monitoring configured
  • Logging configured

7. Post-Deployment Verification

7.1 Verify Azure Resources

# Check Static Web App status
az staticwebapp show \
  --name YOUR_STATIC_WEB_APP_NAME \
  --resource-group rg-miraclesinmotion-prod

# Check Function App status
az functionapp show \
  --name YOUR_FUNCTION_APP_NAME \
  --resource-group rg-miraclesinmotion-prod

# Check Cosmos DB status
az cosmosdb show \
  --name YOUR_COSMOS_ACCOUNT \
  --resource-group rg-miraclesinmotion-prod

7.2 Verify Authentication

  1. Navigate to https://miraclesinmotion.org
  2. Click "Sign In"
  3. Verify Microsoft authentication flow
  4. Verify user roles are assigned correctly
  5. Test role-based access control

7.3 Verify Cloudflare

# Test DNS resolution
dig miraclesinmotion.org
dig www.miraclesinmotion.org

# Test HTTPS
curl -I https://miraclesinmotion.org

# Verify Cloudflare headers
curl -I https://miraclesinmotion.org | grep -i "cf-"

7.4 Verify Stripe Integration

  1. Test donation flow on the website
  2. Verify webhook events are received
  3. Check Stripe dashboard for transactions
  4. Verify payment processing

7.5 Verify Monitoring

  1. Check Application Insights for telemetry
  2. Verify logs are being collected
  3. Set up alerts for critical issues
  4. Test error tracking

7.6 Performance Testing

# Test page load times
curl -w "@curl-format.txt" -o /dev/null -s https://miraclesinmotion.org

# Test API response times
curl -w "@curl-format.txt" -o /dev/null -s https://miraclesinmotion.org/api/donations

8. Troubleshooting

8.1 Common Issues

Authentication Not Working

  • Verify app registration redirect URIs
  • Check Static Web App authentication configuration
  • Verify user roles are assigned
  • Check browser console for errors

DNS Not Resolving

  • Verify nameservers are updated
  • Wait for DNS propagation (24-48 hours)
  • Check Cloudflare DNS records
  • Verify CNAME records point to correct Azure endpoint

SSL Certificate Issues

  • Verify Cloudflare SSL mode is "Full (strict)"
  • Check Azure Static Web App custom domain configuration
  • Wait for SSL certificate provisioning (can take up to 24 hours)

Stripe Webhook Not Working

  • Verify webhook endpoint URL is correct
  • Check webhook signing secret
  • Verify Function App is receiving webhook events
  • Check Function App logs for errors

8.2 Support Resources


9. Next Steps

After completing all prerequisites:

  1. Deploy the application using the deployment script
  2. Verify all functionality
  3. Set up monitoring and alerts
  4. Configure backup and disaster recovery
  5. Set up CI/CD pipeline
  6. Schedule regular security audits
  7. Set up performance monitoring

10. Security Best Practices

  1. Never commit secrets to source control
  2. Use Key Vault for all secrets
  3. Enable MFA for all Azure accounts
  4. Regularly rotate API keys and secrets
  5. Monitor for suspicious activity
  6. Keep dependencies updated
  7. Use HTTPS everywhere
  8. Implement rate limiting
  9. Regular security audits
  10. Follow principle of least privilege

Last Updated: January 2025 Maintained by: Miracles In Motion Development Team