Files
miracles_in_motion/docs/DEPLOYMENT_PREREQUISITES.md

769 lines
20 KiB
Markdown

# 🚀 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](#azure-setup)
2. [MS Entra (Azure AD) Configuration](#ms-entra-azure-ad-configuration)
3. [Cloudflare Configuration](#cloudflare-configuration)
4. [Stripe Configuration](#stripe-configuration)
5. [Environment Variables](#environment-variables)
6. [Pre-Deployment Checklist](#pre-deployment-checklist)
7. [Post-Deployment Verification](#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
```bash
# 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
```bash
# 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
```bash
# 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
```bash
# 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 Portal****Microsoft Entra ID****App 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
```bash
# 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)
```bash
# 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
```bash
# 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 App****Authentication**
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
```bash
# 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:
```json
{
"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
```bash
# 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 **DNS****Records**
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
```bash
# 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/TLS****Overview**
2. Select **Full (strict)** encryption mode
3. Enable **Always Use HTTPS**
4. Enable **Automatic HTTPS Rewrites**
### 3.6 Configure Page Rules
1. Go to **Rules****Page 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 **Security****Settings**
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 **Security****WAF****Custom 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 **Speed****Optimization**
2. Enable:
- ✅ Auto Minify (JavaScript, CSS, HTML)
- ✅ Brotli compression
- ✅ Rocket Loader (optional)
- ✅ Mirage (optional, for mobile)
### 3.10 Configure Analytics
1. Go to **Analytics****Web 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:
```bash
# 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
```bash
# 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](https://dashboard.stripe.com)
2. Create account or log in
3. Complete account verification
### 4.2 Get API Keys
1. Go to **Developers****API 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 **Developers****Webhooks**
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
```bash
# 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
```bash
# 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:
```bash
# 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
```bash
# 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
```bash
# 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
```bash
# 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
```bash
# 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
- **Azure Documentation**: https://docs.microsoft.com/azure
- **MS Entra Documentation**: https://docs.microsoft.com/azure/active-directory
- **Cloudflare Documentation**: https://developers.cloudflare.com
- **Stripe Documentation**: https://stripe.com/docs
---
## 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