Sync from dev @ 497baf0

Source: main (497baf0)
Excluded: live tenant exports, generated artifacts, and dev-only tooling.
This commit is contained in:
2026-04-21 22:21:43 +02:00
parent b6ac9524f7
commit 2c41eaca44
25 changed files with 2258 additions and 79 deletions

View File

@@ -13,7 +13,7 @@ Quick start:
1. Fork or import this repository into an Azure DevOps project.
2. Review `templates/variables-tenant.yml` and create a matching Azure DevOps Variable Group in your project (e.g. `vg-astral-tenant`).
3. Uncomment the variable group reference in the three pipeline YAMLs.
4. Run `deploy/bootstrap-tenant.ps1` to create the Azure AD app registration, assign Graph permissions, and configure the federated credential.
4. Run `deploy/provision-change-probe.ps1` to create the Azure AD app registration, assign Graph permissions, configure the federated credential, and optionally provision the event-driven change probe (Azure Function App).
5. Create the Azure DevOps service connection using the app registration details from the bootstrap script.
6. Import the three pipelines (`azure-pipelines.yml`, `azure-pipelines-review-sync.yml`, `azure-pipelines-restore.yml`) into Azure DevOps.
7. Run `deploy/validate-deployment.yml` to verify connectivity and permissions.
@@ -25,7 +25,7 @@ See [`deploy/onboarding-runbook.md`](deploy/onboarding-runbook.md) for the full
The implementation is centered on three Azure DevOps pipelines:
- `azure-pipelines.yml`: hourly backup/export pipeline with rolling PR management.
- `azure-pipelines.yml`: backup/export pipeline with rolling PR management. Runs daily at 02:00 to generate a full tenant snapshot, reports, and documentation artifacts, and is also triggered on-demand by the event-driven change probe.
- `azure-pipelines-review-sync.yml`: 20-minute reviewer-decision sync and post-merge remediation queue.
- `azure-pipelines-restore.yml`: manual or auto-queued restore pipeline for approved baseline rollback.
@@ -39,6 +39,8 @@ The main workflow is:
6. Refresh the PR description with deterministic change/risk summary and optional Azure OpenAI narrative.
7. Apply reviewer `/reject` or `/accept` decisions and queue restore when needed.
An **event-driven change probe** monitors Intune and Entra audit logs and triggers the backup pipeline when actual changes are detected, replacing the previous hourly polling model with a responsive event-driven approach.
This is an ex-post change-management model: admins can change settings in the Microsoft admin portals, and the repo turns those changes into auditable Git drift with a review and rollback path.
## Current Baseline Coverage
@@ -80,10 +82,12 @@ Current scope behavior:
- `azure-pipelines.yml`: backup/export, report generation, drift commit, rolling PR, and docs/artifact flow.
- `azure-pipelines-review-sync.yml`: reviewer decision sync and post-merge remediation helper.
- `azure-pipelines-restore.yml`: baseline restore pipeline with full or selective scope.
- `infra/change-probe/`: Azure Function App for event-driven change detection.
- `deploy/provision-change-probe.ps1`: unified provisioning script for the change probe infrastructure.
- `docs/m365-baseline-roadmap.md`: expansion roadmap beyond current workload scope.
- `docs/security-review-package.md`: implementation-focused security review package.
- `docs/security-review-questionnaire.md`: short-form security review answers.
- `scripts/`: export, reporting, PR automation, validation, and remediation helpers.
- `scripts/`: export, reporting, PR automation, validation, remediation helpers, and change probe logic.
- `tests/`: focused unit coverage for the Python helpers.
- `tenant-state/intune`: committed Intune JSON export.
- `tenant-state/entra`: committed Entra JSON export.
@@ -96,7 +100,7 @@ Current scope behavior:
### Main Backup Pipeline
`azure-pipelines.yml` runs hourly on `main`.
`azure-pipelines.yml` runs daily at 02:00 on `main` to generate a full tenant snapshot, reports, and documentation artifacts. It is also triggered on-demand by the change probe when drift is detected.
For Intune it:
@@ -143,10 +147,21 @@ It also supports optional Entra update when restore automation is triggered for
## Schedule And Run Modes
- Main backup schedule: hourly, `0 * * * *`, on `main`
- Main backup schedule: daily at 02:00, `0 2 * * *`, on `main` (full snapshot, reports, and docs)
- Change probe trigger: event-driven, on-demand via Azure Function App
- Review sync schedule: every 20 minutes, `*/20 * * * *`, on `main`
- Full mode: configured full-run hour (default 00:00) or manual queue with `forceFullRun=true`
- Light mode: every other scheduled hour
- Light mode: all probe-triggered runs except the daily full run
### Change Probe (Event-Driven Backup Trigger)
Because Microsoft Graph change notifications and delta queries do not support Intune device management or Conditional Access resources, an audit-log polling architecture is used:
- **`probe_timer`** (5-minute timer trigger): polls Intune and Entra audit logs via Microsoft Graph, evaluates a debouncer state machine (idle → armed → cooldown), and emits a queue message when the quiet window elapses.
- **`queue_consumer`** (queue trigger): dequeues messages and calls the Azure DevOps REST API to queue the backup pipeline.
- **Debouncer**: 15-minute quiet window + 30-minute cooldown prevents backup storms during bulk changes.
- **State**: stored in Azure Table Storage (`ProbeState` table).
- **Provisioning**: `deploy/provision-change-probe.ps1` creates the Entra app, grants admin consent, provisions Resource Group / Storage Account / Function App, and configures app settings.
Full mode adds:
@@ -251,6 +266,14 @@ Auto-remediation:
- `AUTO_REMEDIATE_MAX_WORKERS`
- `AUTO_REMEDIATE_EXCLUDE_CSV`
Change probe settings:
- `PROBE_APP_ID`
- `PROBE_APP_SECRET`
- `PROBE_QUIET_WINDOW_MINUTES` (default: 15)
- `PROBE_COOLDOWN_MINUTES` (default: 30)
- `GRAPH_TOKEN` (optional passthrough)
Azure OpenAI integration:
- `ENABLE_PR_AI_SUMMARY`
@@ -408,6 +431,28 @@ python3 ./scripts/validate_backup_outputs.py \
--reports-root ./tenant-state/reports/intune
```
Run the change probe locally:
```bash
python3 ./scripts/probe_tenant_changes.py \
--app-id "$PROBE_APP_ID" \
--app-secret "$PROBE_APP_SECRET" \
--tenant-id "$TENANT_ID" \
--state-file ./probe-state.json \
--output ./probe-result.json
```
Trigger the backup pipeline manually:
```bash
python3 ./scripts/trigger_backup_pipeline.py \
--organization cqre \
--project Intune \
--pipeline-id 1 \
--token "$ADO_TOKEN" \
--branch refs/heads/main
```
## Tests
The repository includes focused unit tests for: