Add Azure deployment automation and documentation

- Add separate deployment pipeline (azure-pipelines-deploy.yml) for App Service deployment
- Add advanced pipeline with deployment slots (azure-pipelines-slots.yml)
- Restore azure-pipelines.yml to build-only (no deployment)
- Add comprehensive Azure setup documentation:
  - AZURE-NEW-SUBSCRIPTION-SETUP.md: Complete step-by-step Azure resource setup
  - AZURE-RESOURCES-OVERVIEW.md: Quick reference for all Azure resources
  - AZURE-ACR-SHARED-SETUP.md: Guide for shared Container Registry
  - AZURE-ACR-NAMING-RECOMMENDATION.md: Naming recommendations for Zuyderland
  - AZURE-PIPELINE-DEPLOYMENT.md: Automated deployment setup guide
  - AZURE-PIPELINE-QUICK-REFERENCE.md: Quick reference for pipeline variables
  - AZURE-PIPELINES-USAGE.md: Guide for using build and deployment pipelines
- Add setup script (scripts/setup-azure-resources.sh) for automated resource creation
- Support for shared ACR across multiple applications
This commit is contained in:
2026-01-21 23:03:48 +01:00
parent 52f851c1f3
commit 42a04e6cb3
10 changed files with 3176 additions and 0 deletions

418
scripts/setup-azure-resources.sh Executable file
View File

@@ -0,0 +1,418 @@
#!/bin/bash
# Azure Resources Setup Script for CMDB Insight
# This script helps automate the creation of Azure resources
#
# Usage:
# ./scripts/setup-azure-resources.sh
#
# Prerequisites:
# - Azure CLI installed and logged in (az login)
# - Appropriate permissions on Azure subscription
# - Jira credentials ready (OAuth or PAT)
set -e # Exit on error
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Configuration - Customize these values
RESOURCE_GROUP="rg-cmdb-insight-prod"
LOCATION="westeurope"
# ACR Configuration - Can be shared across multiple applications
# Option 1: Use existing ACR (recommended if you have one)
ACR_NAME="" # Leave empty to use existing, or set to create new
ACR_RESOURCE_GROUP="" # Resource group where ACR exists (for existing) or will be created (for new)
# Option 2: Create new ACR (only if ACR_NAME is set and doesn't exist)
# ACR_NAME="yourcompanyacr" # Must be globally unique, lowercase, 5-50 chars
# ACR_RESOURCE_GROUP="rg-shared-services" # Or use RESOURCE_GROUP
DB_SERVER_NAME="cmdb-postgres-prod" # Must be globally unique
DB_ADMIN_USER="cmdbadmin"
DB_NAME="cmdb"
KEY_VAULT_NAME="kv-cmdb-insight-prod" # Must be globally unique
APP_INSIGHTS_NAME="appi-cmdb-insight-prod" # Must be globally unique
APP_SERVICE_PLAN_NAME="plan-cmdb-insight-prod"
BACKEND_APP_NAME="cmdb-backend-prod" # Must be globally unique
FRONTEND_APP_NAME="cmdb-frontend-prod" # Must be globally unique
# SKU Configuration
ACR_SKU="Standard" # Options: Basic, Standard, Premium (Standard recommended for shared ACR)
APP_SERVICE_SKU="B1" # Options: B1, B2, S1
POSTGRES_SKU="Standard_B1ms" # Options: Standard_B1ms, Standard_B2s
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}Azure Resources Setup for CMDB Insight${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
# Check Azure CLI
if ! command -v az &> /dev/null; then
echo -e "${RED}Error: Azure CLI is not installed.${NC}"
echo "Install it from: https://docs.microsoft.com/cli/azure/install-azure-cli"
exit 1
fi
# Check if logged in
if ! az account show &> /dev/null; then
echo -e "${YELLOW}Not logged in to Azure. Please run: az login${NC}"
exit 1
fi
# Show current subscription
echo -e "${GREEN}Current Azure Subscription:${NC}"
az account show --query "{Name:name, SubscriptionId:id}" -o table
echo ""
# Confirm before proceeding
read -p "Do you want to proceed with creating resources? (yes/no): " confirm
if [ "$confirm" != "yes" ]; then
echo "Aborted."
exit 0
fi
echo ""
echo -e "${GREEN}Step 1: Creating Resource Group...${NC}"
az group create \
--name $RESOURCE_GROUP \
--location $LOCATION \
--output none
echo -e "${GREEN}✓ Resource Group created${NC}"
echo ""
echo -e "${GREEN}Step 2: Setting up Azure Container Registry...${NC}"
# Check if ACR_NAME is provided
if [ -z "$ACR_NAME" ]; then
echo -e "${YELLOW}⚠️ ACR_NAME not set. Please provide an existing ACR name or set ACR_NAME to create a new one.${NC}"
read -p "Enter existing ACR name (or press Enter to skip): " EXISTING_ACR_NAME
if [ -z "$EXISTING_ACR_NAME" ]; then
echo -e "${YELLOW}Skipping ACR setup. You'll need to configure ACR manually.${NC}"
ACR_NAME=""
ACR_LOGIN_SERVER=""
else
ACR_NAME=$EXISTING_ACR_NAME
if [ -z "$ACR_RESOURCE_GROUP" ]; then
read -p "Enter ACR resource group: " ACR_RESOURCE_GROUP
fi
# Verify ACR exists
if az acr show --name $ACR_NAME --resource-group $ACR_RESOURCE_GROUP &> /dev/null; then
echo -e "${GREEN}✓ Using existing Container Registry: $ACR_NAME${NC}"
ACR_LOGIN_SERVER=$(az acr show --name $ACR_NAME --resource-group $ACR_RESOURCE_GROUP --query loginServer --output tsv)
echo " ACR Login Server: $ACR_LOGIN_SERVER"
else
echo -e "${RED}Error: ACR '$ACR_NAME' not found in resource group '$ACR_RESOURCE_GROUP'${NC}"
exit 1
fi
fi
else
# Determine ACR resource group
if [ -z "$ACR_RESOURCE_GROUP" ]; then
ACR_RESOURCE_GROUP=$RESOURCE_GROUP
fi
# Check if ACR already exists
if az acr show --name $ACR_NAME --resource-group $ACR_RESOURCE_GROUP &> /dev/null; then
echo -e "${GREEN}✓ Using existing Container Registry: $ACR_NAME${NC}"
ACR_LOGIN_SERVER=$(az acr show --name $ACR_NAME --resource-group $ACR_RESOURCE_GROUP --query loginServer --output tsv)
echo " ACR Login Server: $ACR_LOGIN_SERVER"
else
# Create resource group for ACR if it doesn't exist
if ! az group show --name $ACR_RESOURCE_GROUP &> /dev/null; then
echo "Creating resource group for ACR: $ACR_RESOURCE_GROUP"
az group create --name $ACR_RESOURCE_GROUP --location $LOCATION --output none
fi
# Create new ACR
echo "Creating new Container Registry: $ACR_NAME"
az acr create \
--resource-group $ACR_RESOURCE_GROUP \
--name $ACR_NAME \
--sku $ACR_SKU \
--admin-enabled true \
--output none
echo -e "${GREEN}✓ Container Registry created${NC}"
ACR_LOGIN_SERVER=$(az acr show --name $ACR_NAME --resource-group $ACR_RESOURCE_GROUP --query loginServer --output tsv)
echo " ACR Login Server: $ACR_LOGIN_SERVER"
echo -e "${YELLOW}💡 This ACR can be shared with other applications. Use repository names to separate apps.${NC}"
fi
fi
echo ""
echo -e "${GREEN}Step 3: Creating PostgreSQL Database...${NC}"
echo -e "${YELLOW}Generating secure database password...${NC}"
DB_ADMIN_PASSWORD=$(openssl rand -base64 32 | tr -d "=+/" | cut -c1-25)
echo " Database Password: $DB_ADMIN_PASSWORD"
echo " ${YELLOW}⚠️ Save this password securely!${NC}"
az postgres flexible-server create \
--resource-group $RESOURCE_GROUP \
--name $DB_SERVER_NAME \
--location $LOCATION \
--admin-user $DB_ADMIN_USER \
--admin-password $DB_ADMIN_PASSWORD \
--sku-name $POSTGRES_SKU \
--tier Burstable \
--storage-size 32 \
--version 15 \
--public-access 0.0.0.0 \
--output none
echo -e "${GREEN}✓ PostgreSQL Server created${NC}"
az postgres flexible-server db create \
--resource-group $RESOURCE_GROUP \
--server-name $DB_SERVER_NAME \
--database-name $DB_NAME \
--output none
echo -e "${GREEN}✓ Database created${NC}"
DB_HOST="${DB_SERVER_NAME}.postgres.database.azure.com"
DB_CONNECTION_STRING="postgresql://${DB_ADMIN_USER}:${DB_ADMIN_PASSWORD}@${DB_HOST}:5432/${DB_NAME}?sslmode=require"
echo " Database Host: $DB_HOST"
echo ""
echo -e "${GREEN}Step 4: Creating Key Vault...${NC}"
az keyvault create \
--name $KEY_VAULT_NAME \
--resource-group $RESOURCE_GROUP \
--location $LOCATION \
--sku standard \
--output none
echo -e "${GREEN}✓ Key Vault created${NC}"
# Add database password to Key Vault
az keyvault secret set \
--vault-name $KEY_VAULT_NAME \
--name "DatabasePassword" \
--value "$DB_ADMIN_PASSWORD" \
--output none
echo -e "${GREEN}✓ Database password stored in Key Vault${NC}"
echo ""
echo -e "${YELLOW}⚠️ You need to add the following secrets to Key Vault manually:${NC}"
echo " - JiraPat (if using PAT authentication)"
echo " - SessionSecret (generate with: openssl rand -hex 32)"
echo " - JiraOAuthClientId (if using OAuth)"
echo " - JiraOAuthClientSecret (if using OAuth)"
echo " - JiraSchemaId"
echo ""
echo "Commands to add secrets:"
echo " az keyvault secret set --vault-name $KEY_VAULT_NAME --name SessionSecret --value \$(openssl rand -hex 32)"
echo " az keyvault secret set --vault-name $KEY_VAULT_NAME --name JiraOAuthClientId --value <your-client-id>"
echo " az keyvault secret set --vault-name $KEY_VAULT_NAME --name JiraOAuthClientSecret --value <your-client-secret>"
echo " az keyvault secret set --vault-name $KEY_VAULT_NAME --name JiraSchemaId --value <your-schema-id>"
echo ""
echo -e "${GREEN}Step 5: Creating Application Insights...${NC}"
az monitor app-insights component create \
--app $APP_INSIGHTS_NAME \
--location $LOCATION \
--resource-group $RESOURCE_GROUP \
--application-type web \
--output none
echo -e "${GREEN}✓ Application Insights created${NC}"
INSTRUMENTATION_KEY=$(az monitor app-insights component show \
--app $APP_INSIGHTS_NAME \
--resource-group $RESOURCE_GROUP \
--query instrumentationKey --output tsv)
echo " Instrumentation Key: $INSTRUMENTATION_KEY"
echo ""
echo -e "${GREEN}Step 6: Creating App Service Plan...${NC}"
az appservice plan create \
--name $APP_SERVICE_PLAN_NAME \
--resource-group $RESOURCE_GROUP \
--sku $APP_SERVICE_SKU \
--is-linux \
--output none
echo -e "${GREEN}✓ App Service Plan created${NC}"
echo ""
echo -e "${GREEN}Step 7: Creating Backend App Service...${NC}"
az webapp create \
--name $BACKEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--plan $APP_SERVICE_PLAN_NAME \
--deployment-container-image-name "${ACR_NAME}.azurecr.io/cmdb-insight/backend:latest" \
--output none
echo -e "${GREEN}✓ Backend App Service created${NC}"
# Enable Managed Identity
az webapp identity assign \
--name $BACKEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--output none
BACKEND_PRINCIPAL_ID=$(az webapp identity show \
--name $BACKEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--query principalId --output tsv)
# Grant ACR access (if ACR was configured)
if [ -n "$ACR_NAME" ] && [ -n "$ACR_RESOURCE_GROUP" ]; then
ACR_ID=$(az acr show --name $ACR_NAME --resource-group $ACR_RESOURCE_GROUP --query id --output tsv)
az role assignment create \
--assignee $BACKEND_PRINCIPAL_ID \
--role AcrPull \
--scope $ACR_ID \
--output none
echo -e "${GREEN}✓ ACR access granted to backend${NC}"
else
echo -e "${YELLOW}⚠️ ACR not configured. You'll need to grant ACR access manually.${NC}"
fi
# Configure container (if ACR was configured)
if [ -n "$ACR_NAME" ]; then
az webapp config container set \
--name $BACKEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--docker-custom-image-name "${ACR_NAME}.azurecr.io/cmdb-insight/backend:latest" \
--docker-registry-server-url "https://${ACR_NAME}.azurecr.io" \
--output none
else
echo -e "${YELLOW}⚠️ ACR not configured. You'll need to configure container settings manually.${NC}"
fi
# Grant Key Vault access
az keyvault set-policy \
--name $KEY_VAULT_NAME \
--object-id $BACKEND_PRINCIPAL_ID \
--secret-permissions get list \
--output none
echo -e "${GREEN}✓ Key Vault access granted to backend${NC}"
# Set environment variables (basic - you'll need to add Key Vault references manually)
az webapp config appsettings set \
--name $BACKEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--settings \
NODE_ENV=production \
PORT=3001 \
DATABASE_TYPE=postgres \
DATABASE_URL="postgresql://${DB_ADMIN_USER}:${DB_ADMIN_PASSWORD}@${DB_HOST}:5432/${DB_NAME}?sslmode=require" \
JIRA_HOST=https://jira.zuyderland.nl \
JIRA_AUTH_METHOD=oauth \
FRONTEND_URL="https://${FRONTEND_APP_NAME}.azurewebsites.net" \
APPINSIGHTS_INSTRUMENTATIONKEY="${INSTRUMENTATION_KEY}" \
--output none
# Enable HTTPS only
az webapp update \
--name $BACKEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--https-only true \
--output none
echo -e "${GREEN}✓ Backend configuration complete${NC}"
echo ""
echo -e "${GREEN}Step 8: Creating Frontend App Service...${NC}"
az webapp create \
--name $FRONTEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--plan $APP_SERVICE_PLAN_NAME \
--deployment-container-image-name "${ACR_NAME}.azurecr.io/cmdb-insight/frontend:latest" \
--output none
echo -e "${GREEN}✓ Frontend App Service created${NC}"
# Enable Managed Identity
az webapp identity assign \
--name $FRONTEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--output none
FRONTEND_PRINCIPAL_ID=$(az webapp identity show \
--name $FRONTEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--query principalId --output tsv)
# Grant ACR access (if ACR was configured)
if [ -n "$ACR_NAME" ] && [ -n "$ACR_RESOURCE_GROUP" ]; then
ACR_ID=$(az acr show --name $ACR_NAME --resource-group $ACR_RESOURCE_GROUP --query id --output tsv)
az role assignment create \
--assignee $FRONTEND_PRINCIPAL_ID \
--role AcrPull \
--scope $ACR_ID \
--output none
echo -e "${GREEN}✓ ACR access granted to frontend${NC}"
fi
# Configure container (if ACR was configured)
if [ -n "$ACR_NAME" ]; then
az webapp config container set \
--name $FRONTEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--docker-custom-image-name "${ACR_NAME}.azurecr.io/cmdb-insight/frontend:latest" \
--docker-registry-server-url "https://${ACR_NAME}.azurecr.io" \
--output none
fi
# Set environment variables
az webapp config appsettings set \
--name $FRONTEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--settings \
VITE_API_URL="https://${BACKEND_APP_NAME}.azurewebsites.net/api" \
--output none
# Enable HTTPS only
az webapp update \
--name $FRONTEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--https-only true \
--output none
echo -e "${GREEN}✓ Frontend configuration complete${NC}"
echo ""
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}Setup Complete!${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
echo -e "${YELLOW}Next Steps:${NC}"
echo ""
echo "1. Add secrets to Key Vault:"
echo " az keyvault secret set --vault-name $KEY_VAULT_NAME --name SessionSecret --value \$(openssl rand -hex 32)"
echo " az keyvault secret set --vault-name $KEY_VAULT_NAME --name JiraOAuthClientId --value <your-client-id>"
echo " az keyvault secret set --vault-name $KEY_VAULT_NAME --name JiraOAuthClientSecret --value <your-client-secret>"
echo " az keyvault secret set --vault-name $KEY_VAULT_NAME --name JiraSchemaId --value <your-schema-id>"
echo ""
echo "2. Update backend app settings to use Key Vault references:"
echo " See AZURE-NEW-SUBSCRIPTION-SETUP.md for details"
echo ""
echo "3. Build and push Docker images:"
if [ -n "$ACR_NAME" ]; then
echo " export ACR_NAME=\"$ACR_NAME\""
echo " ./scripts/build-and-push-azure.sh"
else
echo " export ACR_NAME=\"<your-acr-name>\""
echo " ./scripts/build-and-push-azure.sh"
fi
echo ""
echo "4. Restart apps to pull images:"
echo " az webapp restart --name $BACKEND_APP_NAME --resource-group $RESOURCE_GROUP"
echo " az webapp restart --name $FRONTEND_APP_NAME --resource-group $RESOURCE_GROUP"
echo ""
echo -e "${GREEN}Resource Information:${NC}"
echo " Resource Group: $RESOURCE_GROUP"
if [ -n "$ACR_LOGIN_SERVER" ]; then
echo " ACR: $ACR_LOGIN_SERVER"
echo " Repository: cmdb-insight (backend, frontend)"
else
echo " ACR: Not configured (configure manually)"
fi
echo " Database: $DB_HOST"
echo " Key Vault: $KEY_VAULT_NAME"
echo " Frontend URL: https://${FRONTEND_APP_NAME}.azurewebsites.net"
echo " Backend URL: https://${BACKEND_APP_NAME}.azurewebsites.net/api"
echo ""
echo -e "${YELLOW}⚠️ Important: Save the database password securely!${NC}"
echo " Password: $DB_ADMIN_PASSWORD"
echo ""