# ASTRAL Onboarding Runbook This guide walks through deploying ASTRAL into a new Azure DevOps organization and Microsoft 365 tenant. ## Prerequisites - Azure DevOps organization and project created. - Owner or Contributor access to the target Microsoft 365 tenant. - Permission to create app registrations and grant admin consent in Entra ID. - PowerShell 7+ or Windows PowerShell 5.1 with the `Microsoft.Graph` module (for the bootstrap script). ## Step 1: Import the repository 1. In Azure DevOps, create a new Git repository in your project. 2. Push the contents of this repository into it, or use **Import repository** from a public Git URL. ## Step 2: Create the tenant variable group 1. In Azure DevOps, go to **Pipelines > Library** and create a new Variable Group. 2. Recommended name: `vg-astral-tenant` (you can choose any name). 3. Add the variables from `templates/variables-tenant.yml`. Use your real tenant values: | Variable | Example value | Notes | | --- | --- | --- | | `TENANT_NAME` | `contoso.onmicrosoft.com` | Your M365 tenant domain | | `SERVICE_CONNECTION_NAME` | `sc-astral-backup` | Name you will use for the service connection | | `USER_NAME` | `ASTRAL Backup Service` | Git committer name | | `USER_EMAIL` | `astral-backup@contoso.com` | Git committer email | | `AGENT_POOL_NAME` | `Azure Pipelines` | Change if using a self-hosted pool | | `BACKUP_TIMEZONE` | `Europe/Prague` | Valid tz database name | | `FULL_RUN_HOUR` | `00` | Hour that triggers full export | | `AUTO_REMEDIATE_RESTORE_PIPELINE_ID` | *(leave empty)* | Filled in Step 8 | 4. If you plan to use Azure OpenAI summaries, also add: - `ENABLE_PR_AI_SUMMARY` = `true` - `AZURE_OPENAI_ENDPOINT` - `AZURE_OPENAI_DEPLOYMENT` - `AZURE_OPENAI_API_KEY` *(mark as secret)* ## Step 3: Link the variable group to the pipelines Open each pipeline YAML and uncomment the variable group line near the top: ```yaml variables: - group: vg-astral-tenant # <-- uncomment this line - template: templates/variables-common.yml ``` Do this for: - `azure-pipelines.yml` - `azure-pipelines-review-sync.yml` - `azure-pipelines-restore.yml` Commit and push the changes. ## Step 4: Run the tenant bootstrap script Run `deploy/bootstrap-tenant.ps1` in a PowerShell session authenticated to your target tenant. ```powershell # Example .\deploy\bootstrap-tenant.ps1 -TenantName "contoso.onmicrosoft.com" -ServiceConnectionName "sc-astral-backup" ``` The script will: 1. Create a single-tenant app registration. 2. Add required Microsoft Graph application permissions. 3. Grant admin consent. 4. Create a workload federated credential for Azure DevOps. 5. Print the App ID and instructions for creating the Azure DevOps service connection. ## Step 5: Create the Azure DevOps service connection 1. In Azure DevOps, go to **Project settings > Service connections**. 2. Click **New service connection > Azure Resource Manager > Workload identity federation (manual)**. 3. Fill in: - **Subscription**: leave blank or select if you also want ARM access (not required). - **Tenant ID**: your Microsoft 365 tenant ID. - **Service Connection Name**: the same value you set in `SERVICE_CONNECTION_NAME` (e.g. `sc-astral-backup`). - **App ID**: from the bootstrap script output. 4. Save the service connection. ## Step 6: Import the pipelines 1. Go to **Pipelines > Create pipeline > Azure Repos Git**. 2. Select your repository. 3. Choose **Existing Azure Pipelines YAML file**. 4. Import each of the three YAMLs one by one: - `azure-pipelines.yml` (main backup) - `azure-pipelines-review-sync.yml` (review sync) - `azure-pipelines-restore.yml` (restore) ## Step 7: Grant repository permissions to the build identity 1. Go to **Project settings > Repositories**. 2. Select your repository. 3. Under **Security**, grant the **Build Service** account: - Contribute - Create branch - Force push - Create pull request - Edit pull request - Tag creation (if you enable tagging) 4. Under **Pipelines**, grant the build service **Queue builds** permission on `azure-pipelines-restore.yml` if you plan to use auto-remediation. ## Step 8: Set the restore pipeline definition ID After importing `azure-pipelines-restore.yml`, find its definition ID: 1. Open the restore pipeline in Azure DevOps. 2. The URL contains `definitionId=XX`. Note the number. 3. Go back to your variable group (`vg-astral-tenant`) and set: - `AUTO_REMEDIATE_RESTORE_PIPELINE_ID` = `XX` ## Step 9: Validate the deployment 1. Import `deploy/validate-deployment.yml` as a one-time pipeline. 2. Run it. 3. Verify that all checks pass: - Graph token acquisition - Required roles present - Test read from Graph - Test PR creation and abandonment ## Step 10: Run the first backup 1. Queue a manual run of `azure-pipelines.yml`. 2. Set `forceFullRun=true` to get a complete initial snapshot. 3. Verify that `tenant-state/` is populated and a rolling PR is created. ## Optional: progressive feature rollout | Phase | What to enable | | --- | --- | | Backup-only | `ENABLE_PR_REVIEW_SUMMARY=false`, `ENABLE_PR_REVIEWER_DECISIONS=false`, `AUTO_REMEDIATE_AFTER_MERGE=false` | | Review package | `ENABLE_PR_REVIEW_SUMMARY=true`, `ENABLE_PR_REVIEWER_DECISIONS=true` | | Full package | Also enable restore and set `AUTO_REMEDIATE_AFTER_MERGE=true` if desired | | AI summaries | `ENABLE_PR_AI_SUMMARY=true` plus Azure OpenAI variables | ## Troubleshooting | Symptom | Likely cause | Fix | | --- | --- | --- | | Pipeline fails at "Get Graph Token" | Wrong service connection name or missing federated credential | Verify `SERVICE_CONNECTION_NAME` matches the service connection exactly | | "Missing required Graph roles" | Admin consent not granted | Run bootstrap script again or grant consent manually in Entra ID | | Rolling PR not created | Build identity lacks PR permissions | Add **Create pull request** and **Edit pull request** permissions | | Restore pipeline queue fails | `AUTO_REMEDIATE_RESTORE_PIPELINE_ID` wrong or missing queue permission | Verify the ID and grant **Queue builds** on the restore pipeline | | Empty `tenant-state/` after run | First run may have no data if Graph returns nothing; also check `BACKUP_FOLDER` path | Verify Graph permissions and re-run |