Sync from dev @ 252c1cf
Source: main (252c1cf) Excluded: live tenant exports, generated artifacts, and dev-only tooling.
This commit is contained in:
59
docs/assets/astral-logo.svg
Normal file
59
docs/assets/astral-logo.svg
Normal file
@@ -0,0 +1,59 @@
|
||||
<svg width="1200" height="320" viewBox="0 0 1200 320" fill="none" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="title desc">
|
||||
<title id="title">ASTRAL logo</title>
|
||||
<desc id="desc">ASTRAL wordmark with celestial shield, orbit, and star symbol.</desc>
|
||||
<defs>
|
||||
<linearGradient id="shieldGradient" x1="34" y1="28" x2="192" y2="230" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#071A2E"/>
|
||||
<stop offset="0.52" stop-color="#123B68"/>
|
||||
<stop offset="1" stop-color="#0D6E8E"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="coreGlow" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(112 110) rotate(90) scale(88)">
|
||||
<stop stop-color="#5EEAD4" stop-opacity="0.95"/>
|
||||
<stop offset="0.45" stop-color="#38BDF8" stop-opacity="0.45"/>
|
||||
<stop offset="1" stop-color="#0EA5E9" stop-opacity="0"/>
|
||||
</radialGradient>
|
||||
<linearGradient id="starGradient" x1="88" y1="82" x2="138" y2="154" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FFF3B0"/>
|
||||
<stop offset="0.55" stop-color="#FFD166"/>
|
||||
<stop offset="1" stop-color="#F59E0B"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="orbitGradient" x1="62" y1="76" x2="160" y2="160" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#BFF6FF" stop-opacity="0.95"/>
|
||||
<stop offset="1" stop-color="#67E8F9" stop-opacity="0.35"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="crescentGradient" x1="78" y1="66" x2="120" y2="106" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#D9F99D"/>
|
||||
<stop offset="1" stop-color="#7DD3FC"/>
|
||||
</linearGradient>
|
||||
<filter id="softShadow" x="0" y="0" width="260" height="260" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feDropShadow dx="0" dy="10" stdDeviation="10" flood-color="#102A43" flood-opacity="0.16"/>
|
||||
</filter>
|
||||
</defs>
|
||||
|
||||
<g filter="url(#softShadow)">
|
||||
<path d="M112 22L188 52V120C188 173 155 221 112 244C69 221 36 173 36 120V52L112 22Z" fill="url(#shieldGradient)"/>
|
||||
<path d="M112 46L168 68V120C168 162 145 199 112 219C79 199 56 162 56 120V68L112 46Z" fill="#F8FBFF" fill-opacity="0.08" stroke="#C9F3FF" stroke-opacity="0.42" stroke-width="2"/>
|
||||
<circle cx="112" cy="112" r="72" fill="url(#coreGlow)"/>
|
||||
<path d="M94 74C83 81 77 94 77 108C77 124 86 138 100 145C92 137 88 126 88 115C88 99 96 84 109 75C104 74 99 73 94 74Z" fill="url(#crescentGradient)" fill-opacity="0.9"/>
|
||||
<ellipse cx="112" cy="112" rx="58" ry="34" transform="rotate(-18 112 112)" stroke="url(#orbitGradient)" stroke-width="3"/>
|
||||
<circle cx="161" cy="95" r="4.5" fill="#CFFAFE"/>
|
||||
<path d="M112 72L120.5 95.5L145.5 96.5L125.5 111.5L133 135L112 121L91 135L98.5 111.5L78.5 96.5L103.5 95.5L112 72Z" fill="url(#starGradient)"/>
|
||||
<circle cx="79" cy="82" r="2" fill="#E0F2FE"/>
|
||||
<circle cx="145" cy="69" r="1.7" fill="#FDE68A"/>
|
||||
<circle cx="149" cy="144" r="1.7" fill="#BAE6FD"/>
|
||||
<circle cx="69" cy="140" r="1.5" fill="#F0FDFA"/>
|
||||
<path d="M149 56L151.5 62L158 64.5L151.5 67L149 73L146.5 67L140 64.5L146.5 62L149 56Z" fill="#F8FAFC" fill-opacity="0.92"/>
|
||||
<circle cx="112" cy="112" r="44" stroke="#BEE3F8" stroke-opacity="0.28" stroke-width="1.5" stroke-dasharray="4 6"/>
|
||||
</g>
|
||||
|
||||
<g transform="translate(250 62)">
|
||||
<text x="0" y="78" fill="#102A43" font-family="Avenir Next, Montserrat, Inter, Arial, sans-serif" font-size="92" font-weight="800" letter-spacing="10">ASTRAL</text>
|
||||
<text x="2" y="124" fill="#0B6E8A" font-family="Avenir Next, Montserrat, Inter, Arial, sans-serif" font-size="22" font-weight="600" letter-spacing="2.4">
|
||||
Admin Security Through Review, Automation & Least-privilege
|
||||
</text>
|
||||
<line x1="0" y1="146" x2="756" y2="146" stroke="#D9E2EC" stroke-width="2"/>
|
||||
<text x="2" y="186" fill="#486581" font-family="Avenir Next, Montserrat, Inter, Arial, sans-serif" font-size="26" font-weight="500" letter-spacing="0.6">
|
||||
Configuration drift review and remediation for Intune and Entra
|
||||
</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
143
docs/m365-baseline-roadmap.md
Normal file
143
docs/m365-baseline-roadmap.md
Normal file
@@ -0,0 +1,143 @@
|
||||
# M365 Baseline Expansion Roadmap
|
||||
|
||||
This document tracks the repository from its current implemented state rather than from the original proposal.
|
||||
|
||||
## Current State
|
||||
|
||||
The repository already operates as a two-workload baseline system:
|
||||
|
||||
- Intune drift backup via IntuneCD
|
||||
- Entra drift backup for Named Locations, Authentication Strengths, Conditional Access, App Registrations, and Enterprise Applications
|
||||
|
||||
The surrounding control loop is also implemented:
|
||||
|
||||
- hourly backup pipeline plus midnight Prague full run
|
||||
- rolling PR per workload
|
||||
- deterministic reviewer summary with optional Azure OpenAI narrative
|
||||
- optional per-file change-ticket threads
|
||||
- reviewer `/reject` and `/accept` decision sync every 20 minutes
|
||||
- auto-remediation for rejected drift snapshots
|
||||
- post-merge restore queue for partial-accept / partial-reject review flows
|
||||
- selective historical restore from branch, tag, or commit
|
||||
- output validation and drift-noise filtering before commit
|
||||
|
||||
## What Is Stable Today
|
||||
|
||||
Stable and part of the normal operating model:
|
||||
|
||||
- Intune export and reporting
|
||||
- Entra Named Locations export
|
||||
- Entra Authentication Strengths export
|
||||
- Entra Conditional Access export with reference-name enrichment
|
||||
- object inventory and assignment reporting for both workloads
|
||||
- Entra app inventory reporting
|
||||
- drift-branch commit and rolling PR update workflow
|
||||
|
||||
Implemented, but intentionally constrained:
|
||||
|
||||
- App Registrations export is full-run only
|
||||
- Enterprise Applications export is full-run only
|
||||
- light runs preserve the previous committed snapshot for those two Entra categories
|
||||
|
||||
Not yet implemented:
|
||||
|
||||
- Directory role templates and active directory roles
|
||||
- Exchange Online, Teams, SharePoint, Purview, and Azure governance modules
|
||||
|
||||
## Current Gaps And Stabilization Backlog
|
||||
|
||||
1. Fix App Registrations light-run stability.
|
||||
The current pipeline still disables hourly App Registrations export because some runs produce resolver-only churn. Re-enabling hourly export requires a deterministic light-run result.
|
||||
|
||||
2. Keep Enterprise Applications scoped as a heavy module unless runtime proves otherwise.
|
||||
Enterprise Applications are already exported, but only on full runs. The current design assumes this category should remain bounded to the daily/full path unless runtime and diff quality support widening scope.
|
||||
|
||||
3. Add the next identity-baseline module only after Phase 1 is fully stable.
|
||||
Directory roles are the next logical addition, but they should follow the same pattern: deterministic export, report generation, validation, reviewer-noise filtering, and tests.
|
||||
|
||||
## Design Rules For New Modules
|
||||
|
||||
Every expansion module should follow the conventions already used by Intune and Entra:
|
||||
|
||||
1. Store raw JSON under `tenant-state/<workload-or-module>/`.
|
||||
2. Store human-review reports under `tenant-state/reports/<workload-or-module>/`.
|
||||
3. Keep one object per file with deterministic naming and stable key ordering where possible.
|
||||
4. Validate expected outputs before drift commit.
|
||||
5. Filter known non-config churn before PR creation.
|
||||
6. Update permissions, README, and tests in the same change.
|
||||
7. Start as daily/full-run scope unless there is evidence it is safe and cheap to run hourly.
|
||||
|
||||
## Roadmap By Phase
|
||||
|
||||
### Phase 1: Identity Baseline
|
||||
|
||||
Completed:
|
||||
|
||||
- Entra Named Locations
|
||||
- Entra Authentication Strengths
|
||||
- Entra Conditional Access
|
||||
- App Registrations exporter
|
||||
- Enterprise Applications exporter
|
||||
|
||||
Remaining:
|
||||
|
||||
- stabilize App Registrations for light runs
|
||||
- decide whether Enterprise Applications should remain full-run only
|
||||
- add Directory Roles / Directory Role Templates
|
||||
|
||||
### Phase 2: Service Policy Baseline
|
||||
|
||||
Candidate modules:
|
||||
|
||||
- Exchange Online transport and mail flow rules
|
||||
- Defender for Office policy configuration
|
||||
- Teams policy families
|
||||
- SharePoint and OneDrive tenant-level sharing controls
|
||||
|
||||
### Phase 3: Governance Baseline
|
||||
|
||||
Candidate modules:
|
||||
|
||||
- Purview DLP policies
|
||||
- Purview retention labels and policies
|
||||
- Azure policy assignments and initiatives
|
||||
- Azure RBAC role assignments
|
||||
|
||||
## Proposed Future Repository Shape
|
||||
|
||||
Keep the existing lowercase workload structure and extend it consistently:
|
||||
|
||||
```text
|
||||
tenant-state/
|
||||
intune/
|
||||
entra/
|
||||
exchange/
|
||||
teams/
|
||||
sharepoint/
|
||||
purview/
|
||||
azure-governance/
|
||||
reports/
|
||||
intune/
|
||||
entra/
|
||||
exchange/
|
||||
teams/
|
||||
sharepoint/
|
||||
purview/
|
||||
azure-governance/
|
||||
```
|
||||
|
||||
## Recommended Execution Order
|
||||
|
||||
1. Finish Phase 1 stabilization.
|
||||
2. Add Directory Roles as the next identity module.
|
||||
3. Add one Phase 2 or Phase 3 module at a time.
|
||||
4. Require several stable daily cycles before widening scope or adding the next module.
|
||||
5. Promote a module from full-run only to hourly only after unchanged tenants produce clean, low-noise diffs.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- No regression in current Intune or Entra backup success rate.
|
||||
- Unchanged environments produce deterministic outputs across repeated runs.
|
||||
- Reviewer PRs stay focused on configuration-effective drift, not enrichment noise.
|
||||
- New modules document exact permissions and expected outputs.
|
||||
- Restore and review workflows remain coherent as scope expands.
|
||||
39
docs/security-review-email-draft.md
Normal file
39
docs/security-review-email-draft.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Security Review Email Draft
|
||||
|
||||
## Subject
|
||||
|
||||
Security review package for ASTRAL
|
||||
|
||||
## Email Body
|
||||
|
||||
Hello,
|
||||
|
||||
As discussed, I am sending the security review package for ASTRAL.
|
||||
|
||||
ASTRAL stands for Admin Security Through Review, Automation & Least-privilege.
|
||||
|
||||
Attached are:
|
||||
|
||||
- `security-review-package.pdf` - product security overview, architecture, deployment modes, permissions, data flows, and key security considerations
|
||||
- `security-review-questionnaire.pdf` - short-form questionnaire answers for easier circulation within your security review process
|
||||
|
||||
A few points to highlight up front:
|
||||
|
||||
- the platform supports multiple deployment modes, from backup-only through full review and remediation workflows
|
||||
- AI-assisted review summaries are optional and can be enabled or disabled independently of the backup and restore functions
|
||||
- when AI is enabled, the intended model is a customer-controlled Azure OpenAI deployment rather than an unrelated public AI service
|
||||
- the AI summary feature is advisory and is intended to help non-technical reviewers such as PMs or management understand technical Intune and Entra changes in plain language
|
||||
|
||||
The source repository is private because it contains operational implementation details and tenant-specific configuration material. If your review requires deeper technical evidence, we can provide a controlled walkthrough of the implementation, configuration, and pipeline behavior.
|
||||
|
||||
If useful, I can also provide:
|
||||
|
||||
- a live architecture walkthrough
|
||||
- a permission-by-permission review of the Microsoft Graph access model
|
||||
- a demonstration of deployment modes and AI-assisted review summaries
|
||||
|
||||
Please let me know if your team would like any additional material in a different format.
|
||||
|
||||
Best regards,
|
||||
|
||||
[Your Name]
|
||||
402
docs/security-review-package.md
Normal file
402
docs/security-review-package.md
Normal file
@@ -0,0 +1,402 @@
|
||||
<img src="./assets/astral-logo.svg" alt="ASTRAL logo" width="760" />
|
||||
|
||||
# ASTRAL Security Review Package
|
||||
|
||||
Prepared: 2026-03-27
|
||||
|
||||
## Purpose
|
||||
|
||||
This document describes the security posture of ASTRAL, an Intune / Entra drift backup, review, and remediation platform implemented in this repository.
|
||||
|
||||
ASTRAL stands for:
|
||||
|
||||
- Admin Security Through Review, Automation & Least-privilege
|
||||
|
||||
The goal of the platform is to:
|
||||
|
||||
- export Microsoft Intune and selected Entra ID configuration from a production tenant,
|
||||
- store approved configuration snapshots in Git,
|
||||
- surface drift through rolling pull requests,
|
||||
- optionally restore tenant configuration back to the approved baseline.
|
||||
|
||||
This package is intended for customer security review of the full product and its available deployment modes.
|
||||
|
||||
## Executive Summary
|
||||
|
||||
ASTRAL is an Azure DevOps pipeline based administrative workflow, not a customer-facing application and not an endpoint agent.
|
||||
|
||||
Key characteristics:
|
||||
|
||||
- No inbound listener or public application endpoint is exposed by this repository.
|
||||
- The normal operating mode is outbound-only scheduled jobs from Azure DevOps to Microsoft Graph and Azure DevOps APIs.
|
||||
- The default backup/review path is read-oriented against Microsoft Graph.
|
||||
- A separate restore path can write configuration back to the tenant, but only through the dedicated restore pipeline and only when enabled and authorized.
|
||||
- AI-assisted PR summaries are optional and are not required for backup, review, or restore.
|
||||
|
||||
## Deployment Modes
|
||||
|
||||
The repository can be deployed progressively. It does not need to be introduced as an all-or-nothing package.
|
||||
|
||||
| Mode | Scope | Graph Access Profile | Azure DevOps Scope | AI |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Backup-only | Export tenant configuration, generate reports, retain Git-tracked snapshots | Read-only | Repository and scheduled pipeline only | Disabled |
|
||||
| Review package | Backup-only plus rolling PR review, reviewer summaries, optional change-ticket threads, reviewer `/accept` and `/reject` processing | Read-only | Repository, PR workflows, review-sync pipeline | Optional |
|
||||
| Full package | Review package plus restore pipeline, rollback support, selective remediation, and optional auto-remediation | Read + Write for restore path only | Repository, PR workflows, review-sync, restore pipeline | Optional |
|
||||
|
||||
Important clarifications:
|
||||
|
||||
- AI is an add-on, not a core dependency.
|
||||
- Restore is a separate capability, not a requirement for backup or review.
|
||||
- Organizations can adopt the platform progressively, starting with backup-only and adding review or restore capabilities later.
|
||||
- AI can be enabled or disabled independently of the backup, review, and restore layers.
|
||||
|
||||
## System Overview
|
||||
|
||||
### In-Scope Components
|
||||
|
||||
| Component | Function | Security Relevance |
|
||||
| --- | --- | --- |
|
||||
| Azure DevOps pipeline `azure-pipelines.yml` | Scheduled backup, drift commit, rolling PR management, documentation artifact publishing | Main execution path |
|
||||
| Azure DevOps pipeline `azure-pipelines-review-sync.yml` | Processes reviewer `/reject` and `/accept` decisions and refreshes PR summaries | Uses Azure DevOps API token |
|
||||
| Azure DevOps pipeline `azure-pipelines-restore.yml` | Restores approved baseline to tenant | Write-capable path |
|
||||
| Azure DevOps Git repository | Stores approved baseline, drift branches, JSON exports, reports, docs | Primary configuration store |
|
||||
| Microsoft Graph | Source of Intune and Entra configuration; optional target for restore | Production tenant access |
|
||||
| Azure DevOps REST APIs | PR creation/update, review thread sync, restore queueing | Change-management control plane |
|
||||
| Optional Azure OpenAI | PR summary generation only | Optional data egress path |
|
||||
|
||||
### High-Level Flow
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A["Azure DevOps scheduled pipeline"] --> B["Federated service connection"]
|
||||
B --> C["Microsoft Graph"]
|
||||
A --> D["Git repo: main + drift branches"]
|
||||
A --> E["Azure DevOps PR and thread APIs"]
|
||||
A --> F["Build artifacts: markdown / HTML / PDF"]
|
||||
A -. optional .-> G["Azure OpenAI"]
|
||||
H["Reviewer in Azure DevOps"] --> E
|
||||
E --> I["Rolling PR approval / rejection"]
|
||||
I -. optional remediation .-> J["Restore pipeline"]
|
||||
J --> C
|
||||
```
|
||||
|
||||
## Deployment Model
|
||||
|
||||
### Backup and Review
|
||||
|
||||
The main pipeline runs hourly on `main`.
|
||||
|
||||
- Every hour: export Intune and Entra configuration, generate reports, commit drift to rolling workload branches, and update one rolling PR per workload.
|
||||
- When delayed reviewer notifications are enabled, newly created rolling PRs are opened as Azure DevOps draft PRs, the automated summary is inserted, and the PR is then published for reviewer notification.
|
||||
- At the configured full-run hour: perform the same work plus documentation artifact generation (Markdown, and optionally HTML/PDF if browser dependencies are available).
|
||||
|
||||
The workload branches are:
|
||||
|
||||
- `drift/intune`
|
||||
- `drift/entra`
|
||||
|
||||
Reviewers approve or reject drift through Azure DevOps pull requests. The system is intentionally ex-post change management: admins may make changes in the Microsoft admin portals, and this system detects, records, and routes those changes for review.
|
||||
|
||||
### Review Sync
|
||||
|
||||
The review-sync pipeline runs every 20 minutes on `main`.
|
||||
|
||||
It can:
|
||||
|
||||
- refresh automated PR summaries,
|
||||
- process reviewer `/reject` or `/accept` commands in policy threads,
|
||||
- optionally queue remediation after merge if rejected items were merged out of the PR scope.
|
||||
|
||||
### Restore
|
||||
|
||||
The restore pipeline is the only path that writes configuration back to the tenant.
|
||||
|
||||
It supports:
|
||||
|
||||
- full restore from `main`,
|
||||
- selective restore of specific policy files,
|
||||
- restore from a historical Git ref for rollback use cases,
|
||||
- dry-run mode for report-only validation.
|
||||
|
||||
## Data Processed
|
||||
|
||||
### Data Categories
|
||||
|
||||
| Category | Examples | Source | Stored In |
|
||||
| --- | --- | --- | --- |
|
||||
| Intune configuration objects | compliance policies, device configurations, settings catalog, enrollment profiles, apps, scripts, filters, scope tags | Microsoft Graph / IntuneCD export | Git repo under `tenant-state/intune/**` |
|
||||
| Entra configuration objects | conditional access, named locations, authentication strengths, app registrations, enterprise applications | Microsoft Graph | Git repo under `tenant-state/entra/**` |
|
||||
| Generated reports | assignment inventories, object inventories, app inventories | Derived from exported configuration | `tenant-state/reports/**` and build artifacts |
|
||||
| Documentation artifacts | split markdown, optional HTML/PDF | Derived from exported configuration | build artifacts |
|
||||
| Review metadata | PR descriptions, review threads, accept/reject commands | Azure DevOps reviewers | Azure DevOps PR APIs |
|
||||
| Optional AI summary payload | sampled changed paths, semantic change descriptions, deterministic summary, fingerprints | Derived from repo diff | Azure OpenAI request payload |
|
||||
|
||||
### Data Sensitivity Notes
|
||||
|
||||
- The system is designed for administrative configuration data, not end-user business content.
|
||||
- The repository can still contain sensitive operational material, including policy logic, group names, app identifiers, script bodies, custom configuration payloads, and administrator email addresses present in tenant configuration.
|
||||
- If tenant-authored scripts or custom payloads contain embedded secrets, those secrets would also be captured. This is a customer governance risk, not something the exporter can reliably prevent.
|
||||
- For that reason, the repository, drift branches, build logs, and published artifacts should all be treated as confidential administrative data.
|
||||
- The same sensitivity assumptions apply to any AI summary payload because it is derived from the same administrative configuration changes.
|
||||
|
||||
## Authentication and Authorization
|
||||
|
||||
### Azure to Microsoft Graph
|
||||
|
||||
The pipelines obtain a Microsoft Graph access token at runtime using the Azure DevOps service connection configured in `SERVICE_CONNECTION_NAME` (e.g. `sc-astral-backup`).
|
||||
|
||||
Observed controls in the implementation:
|
||||
|
||||
- token acquisition is performed at runtime with `Get-AzAccessToken`,
|
||||
- token role claims are inspected before proceeding,
|
||||
- the token is stored as a secret pipeline variable (`issecret=true`),
|
||||
- missing required Graph roles cause early failure.
|
||||
|
||||
### Azure DevOps API Access
|
||||
|
||||
The pipelines use `System.AccessToken` for:
|
||||
|
||||
- creating and updating rolling PRs,
|
||||
- reading and updating PR threads,
|
||||
- queuing the restore pipeline.
|
||||
|
||||
The repository permissions documented in the implementation are:
|
||||
|
||||
- contribute,
|
||||
- create branch,
|
||||
- force push,
|
||||
- create/update pull requests,
|
||||
- optional create tag.
|
||||
|
||||
If restore auto-queue is enabled, the pipeline identity also needs:
|
||||
|
||||
- `View builds`,
|
||||
- `Queue builds`,
|
||||
- explicit pipeline authorization when enforced by the project.
|
||||
|
||||
### Graph Permissions by Mode
|
||||
|
||||
#### Backup / Review Mode
|
||||
|
||||
Read-oriented Graph application permissions documented in the repository:
|
||||
|
||||
- `Device.Read.All`
|
||||
- `DeviceManagementApps.Read.All`
|
||||
- `DeviceManagementConfiguration.Read.All`
|
||||
- `DeviceManagementManagedDevices.Read.All`
|
||||
- `DeviceManagementRBAC.Read.All`
|
||||
- `DeviceManagementScripts.Read.All`
|
||||
- `DeviceManagementServiceConfig.Read.All`
|
||||
- `Group.Read.All`
|
||||
- `Policy.Read.All`
|
||||
- `Policy.Read.ConditionalAccess`
|
||||
- `Policy.Read.DeviceConfiguration`
|
||||
- `User.Read.All`
|
||||
- `Application.Read.All` for Entra app exports
|
||||
- `RoleManagement.Read.Directory` or `Directory.Read.All` for richer enrichment
|
||||
- `AuditLog.Read.All` if commit author attribution is desired
|
||||
|
||||
#### Restore Mode
|
||||
|
||||
Write-capable Graph application permissions documented in the repository:
|
||||
|
||||
- `DeviceManagementApps.ReadWrite.All`
|
||||
- `DeviceManagementConfiguration.ReadWrite.All`
|
||||
- `DeviceManagementManagedDevices.ReadWrite.All`
|
||||
- `DeviceManagementRBAC.ReadWrite.All`
|
||||
- `DeviceManagementScripts.ReadWrite.All`
|
||||
- `DeviceManagementServiceConfig.ReadWrite.All`
|
||||
- `Group.Read.All`
|
||||
- `Policy.Read.All`
|
||||
- `Policy.ReadWrite.ConditionalAccess` when Entra updates are included
|
||||
|
||||
## Security Controls Present in the Implementation
|
||||
|
||||
### Network Exposure
|
||||
|
||||
- No inbound application endpoint is created by this repository.
|
||||
- The system is pipeline-driven and relies on outbound HTTPS calls.
|
||||
- Required outbound destinations are:
|
||||
- `graph.microsoft.com`
|
||||
- Azure DevOps organization APIs
|
||||
- optional Azure OpenAI endpoint
|
||||
- Python package registry for `IntuneCD`
|
||||
- npm registry for `md-to-pdf`
|
||||
- optional OS package repositories when HTML/PDF conversion needs Chromium libraries
|
||||
|
||||
### Secrets Handling
|
||||
|
||||
- Graph tokens are obtained just-in-time rather than stored in the repository.
|
||||
- The pipeline marks the Graph token as a secret variable.
|
||||
- The implementation logs token claims and roles for diagnostics, but not the token value itself.
|
||||
- Azure OpenAI uses a pipeline secret variable when enabled.
|
||||
- The pipeline logic itself does not depend on repository-stored application secrets; separate secret scanning of exported tenant content is still recommended.
|
||||
|
||||
### Change Control
|
||||
|
||||
- Drift is committed to dedicated rolling branches rather than directly to `main`.
|
||||
- Review happens through rolling pull requests into `main`.
|
||||
- The implementation can delay reviewer notification by creating new rolling PRs as drafts until the automated summary block is present, reducing generic first-notification content.
|
||||
- Optional file-level change tickets can be enforced through auto-created PR threads.
|
||||
- Reviewers can explicitly accept or reject individual configuration files.
|
||||
- Generated reports are excluded from drift commits and PR diffs to reduce review noise.
|
||||
|
||||
### Safety Checks
|
||||
|
||||
- Backup jobs validate expected outputs before committing drift.
|
||||
- Intune backup logic checks for unauthorized Graph 403 responses and fails unless the failure is explicitly allowed by configuration.
|
||||
- Entra export logic is configured to fail on requested export errors to avoid partial snapshots.
|
||||
- Restore validates required write permissions before running.
|
||||
- Selective restore sanitizes requested paths and rejects path traversal or missing-file conditions.
|
||||
- Restore supports dry-run mode before any tenant change is applied.
|
||||
|
||||
### Auditability
|
||||
|
||||
- Git history retains approved baseline snapshots.
|
||||
- Rolling PR history provides reviewer decisions and rationale.
|
||||
- Azure DevOps build history records pipeline runs and restoration events.
|
||||
- Optional tags can be created for snapshots.
|
||||
|
||||
## Optional Azure OpenAI Integration
|
||||
|
||||
Azure OpenAI is used only for PR review narrative generation.
|
||||
|
||||
Important scoping facts from the implementation:
|
||||
|
||||
- the feature is optional and controlled by pipeline variables,
|
||||
- the core backup/review/restore workflow does not depend on it,
|
||||
- it can remain disabled in every deployment mode,
|
||||
- only a reduced, budget-limited change payload is sent,
|
||||
- the payload contains changed paths, semantic summaries, risk labels, fingerprints, and deterministic summary text,
|
||||
- it does not need direct Microsoft Graph access,
|
||||
- it can be disabled with `ENABLE_PR_AI_SUMMARY=false`.
|
||||
|
||||
### Intended AI Deployment Posture
|
||||
|
||||
The intended security posture for AI is not an opaque third-party black-box service. The implementation is designed to use a customer-controlled Azure OpenAI deployment defined by:
|
||||
|
||||
- `AZURE_OPENAI_ENDPOINT`
|
||||
- `AZURE_OPENAI_DEPLOYMENT`
|
||||
- `AZURE_OPENAI_API_KEY`
|
||||
|
||||
In the intended production design:
|
||||
|
||||
- AI requests are sent to the customer's Azure OpenAI resource,
|
||||
- the model endpoint is explicitly configured by the customer,
|
||||
- the AI service is a bounded summarization component rather than a system of record,
|
||||
- Graph access remains with the pipeline and is not delegated to the model.
|
||||
|
||||
For formal security documentation, the safest statement is:
|
||||
|
||||
- the system is intended to use customer-managed Azure OpenAI infrastructure, typically within the same Azure tenant or controlled Azure environment, rather than an unrelated public AI service.
|
||||
|
||||
### AI Security Considerations
|
||||
|
||||
From a security perspective, the AI feature changes the system in these specific ways:
|
||||
|
||||
- it introduces an additional outbound destination: the configured Azure OpenAI endpoint,
|
||||
- it sends a derived review payload based on configuration drift rather than raw tenant-wide exports,
|
||||
- it does not grant the AI service direct credentials to Microsoft Graph or Azure DevOps,
|
||||
- it is advisory only and does not approve, merge, reject, or restore changes by itself,
|
||||
- it can be disabled independently of the rest of the platform.
|
||||
|
||||
### AI Business Purpose
|
||||
|
||||
The AI summaries exist to make technical Intune and Entra drift understandable to non-technical reviewers.
|
||||
|
||||
Their intended audience includes:
|
||||
|
||||
- project managers,
|
||||
- delivery leads,
|
||||
- security managers,
|
||||
- customer management stakeholders,
|
||||
- reviewers who own risk acceptance but do not work daily with raw policy JSON.
|
||||
|
||||
The purpose is not to replace technical review. The purpose is to provide a manager-readable explanation of:
|
||||
|
||||
- what changed,
|
||||
- why it matters operationally,
|
||||
- whether the change appears routine, risky, or potentially security-relevant,
|
||||
- what a reviewer should verify before approval.
|
||||
|
||||
This allows management or PM stakeholders to participate meaningfully in review without needing to parse raw technical policy structures.
|
||||
|
||||
## Residual Risks and Customer Decisions
|
||||
|
||||
The following items are not fully solved by the repository alone and should be addressed in the customer deployment decision:
|
||||
|
||||
| Area | Current State | Recommended Position |
|
||||
| --- | --- | --- |
|
||||
| Restore capability | Supported by design; can change production tenant state | Keep restore manual only, or disable auto-remediation by default until operational controls are approved |
|
||||
| Backup vs restore identity separation | Sample config uses the same service connection name in backup and restore pipelines | Use separate service principals: read-only for backup/review, write-enabled only for restore |
|
||||
| Azure OpenAI egress | Optional and customer-configurable | Enable only when the organization approves the payload scope and Azure OpenAI deployment model |
|
||||
| Artifact retention | Not defined in repo; inherited from Azure DevOps settings | Set explicit retention for builds, logs, and artifacts |
|
||||
| Repo access model | Not defined in repo | Restrict repo and artifact access to administrators/reviewers only |
|
||||
| Build agent hardening | Pool name exists, but agent type and hardening are deployment-specific | Prefer dedicated hardened agent or approved Microsoft-hosted configuration |
|
||||
| Runtime package download | `pip`, `npm`, and sometimes `apt-get` are used during pipeline runs | Pre-bake dependencies into the agent image if customer forbids runtime internet package fetches |
|
||||
| Secret content inside exported scripts | Possible if tenant admins embed secrets in Intune scripts or custom payloads | Review tenant script hygiene before onboarding |
|
||||
|
||||
## Recommended Deployment Configuration
|
||||
|
||||
For a conservative production deployment, use this profile:
|
||||
|
||||
1. Enable backup and review workflows.
|
||||
2. Enable Azure OpenAI summaries only when a customer-controlled Azure OpenAI deployment is approved.
|
||||
3. Disable automatic remediation queueing.
|
||||
4. Do not authorize the restore pipeline for automatic queueing.
|
||||
5. Use a read-only Graph application identity for backup/review.
|
||||
6. Keep restore on a separate manual path with a separate write-enabled identity.
|
||||
7. Apply Azure DevOps branch policies so `main` requires reviewer approval.
|
||||
8. Set explicit retention and access-control policies for:
|
||||
- Git repository
|
||||
- build logs
|
||||
- markdown/HTML/PDF artifacts
|
||||
|
||||
Suggested conservative variable posture:
|
||||
|
||||
```text
|
||||
ENABLE_PR_AI_SUMMARY=<true|false according to approved deployment mode>
|
||||
AUTO_REMEDIATE_ON_PR_REJECTION=false
|
||||
AUTO_REMEDIATE_AFTER_MERGE=false
|
||||
REQUIRE_CHANGE_TICKETS=true
|
||||
```
|
||||
|
||||
## Out of Scope
|
||||
|
||||
This repository does not provide:
|
||||
|
||||
- endpoint malware protection,
|
||||
- customer device telemetry collection,
|
||||
- user authentication to a SaaS application,
|
||||
- network ingress services,
|
||||
- a standalone secrets vault,
|
||||
- customer-managed key support within the application itself.
|
||||
|
||||
Those controls, where needed, come from Azure DevOps, Microsoft 365 / Entra, the chosen agent environment, and the customer's broader platform governance.
|
||||
|
||||
## Customer-Specific Items to Fill Before Sending
|
||||
|
||||
The following are deployment-specific and should be completed with the actual customer environment:
|
||||
|
||||
- Azure DevOps organization and project name
|
||||
- whether the agent pool is Microsoft-hosted or self-hosted
|
||||
- repo retention period
|
||||
- build log retention period
|
||||
- artifact retention period
|
||||
- named reviewer groups and branch policies
|
||||
- exact service principal names used for backup and restore
|
||||
- which Azure OpenAI resource and deployment are used, if AI is enabled
|
||||
- whether restore is manual-only or fully enabled
|
||||
|
||||
## Repository Evidence
|
||||
|
||||
The statements in this document are based on the implementation in:
|
||||
|
||||
- `README.md`
|
||||
- `azure-pipelines.yml`
|
||||
- `azure-pipelines-review-sync.yml`
|
||||
- `azure-pipelines-restore.yml`
|
||||
- `scripts/update_pr_review_summary.py`
|
||||
- `scripts/apply_reviewer_rejections.py`
|
||||
- `scripts/queue_post_merge_restore.py`
|
||||
- `scripts/export_entra_baseline.py`
|
||||
35
docs/security-review-questionnaire.md
Normal file
35
docs/security-review-questionnaire.md
Normal file
@@ -0,0 +1,35 @@
|
||||
<img src="./assets/astral-logo.svg" alt="ASTRAL logo" width="700" />
|
||||
|
||||
# ASTRAL Security Review Questionnaire
|
||||
|
||||
Prepared: 2026-03-27
|
||||
|
||||
This appendix is a shorter, copy/paste-friendly companion to the full ASTRAL security review package.
|
||||
|
||||
| Question | Answer |
|
||||
| --- | --- |
|
||||
| What is the system? | ASTRAL is an Azure DevOps pipeline workflow that exports Microsoft Intune and selected Entra ID configuration, stores approved baseline snapshots in Git, and raises configuration drift for review through rolling pull requests. |
|
||||
| What deployment modes are supported? | The same repository can be operated in progressive modes: backup-only, review package, or full package with restore/remediation. AI is optional in all modes. |
|
||||
| Is it a public-facing application? | No. It is an administrative pipeline workflow with no public UI or inbound application endpoint created by this repository. |
|
||||
| Does it require inbound network access from the internet? | No. The implemented workflow is outbound-only over HTTPS. |
|
||||
| What production systems does it access? | Microsoft Graph for Intune and Entra configuration, plus Azure DevOps APIs for pull request and pipeline operations. |
|
||||
| Does it make production changes? | Backup and review pipelines are read-oriented against Microsoft Graph. The restore pipeline is write-capable and can apply approved baseline configuration back to the tenant when explicitly enabled and authorized. |
|
||||
| What data is processed? | Administrative configuration data such as Intune policies, device configuration, enrollment profiles, apps, scripts, conditional access, named locations, authentication strengths, app registrations, and enterprise application metadata. |
|
||||
| Does it process end-user business content? | It is not designed for business content. However, exported admin-authored scripts or custom payloads can contain sensitive operational data if the tenant already stores it there. |
|
||||
| Where is data stored? | In the Azure DevOps Git repository, Azure DevOps pull requests/threads, build logs, and optional build artifacts such as markdown, HTML, and PDF documentation. |
|
||||
| How does it authenticate to Microsoft Graph? | By obtaining a Microsoft Graph token at runtime through an Azure DevOps Azure service connection using workload identity / federated credential flow. |
|
||||
| How does it authenticate to Azure DevOps APIs? | With `System.AccessToken` scoped to the pipeline identity. |
|
||||
| Are long-lived secrets stored in the repository? | The pipeline logic does not require repository-stored application secrets. Runtime tokens are acquired during pipeline execution, but exported tenant content should still be treated as potentially sensitive and reviewed for embedded secrets in admin-authored scripts or custom payloads. |
|
||||
| How are secrets handled in the pipeline? | The Graph access token is set as a secret pipeline variable. The implementation logs token claims and granted roles for diagnostics, but not the token value. |
|
||||
| What minimum permissions are required? | Read-only Microsoft Graph application permissions for backup/review, and additional write permissions only for restore. Exact permissions are listed in the full package. |
|
||||
| Is there separation between read and write access? | The code supports a safe separation model. For production, create separate read-only and write-enabled service principals/connections so backup and restore use different identities. |
|
||||
| What change-control mechanism exists? | Drift is committed to dedicated workload branches and reviewed through rolling pull requests into `main`. New rolling PRs can be created as drafts until the automated summary is inserted, and optional per-file change-ticket threads and reviewer `/reject` commands are supported. |
|
||||
| Can reviewers block or scope changes? | Yes. Reviewers can approve the rolling PR, reject it, or reject individual file-level drift items through PR threads when that feature is enabled. |
|
||||
| Is rollback supported? | Yes. The restore pipeline supports full restore, selective restore by file path, historical restore by Git ref, and dry-run mode. |
|
||||
| What external network destinations are required? | Microsoft Graph, Azure DevOps APIs, optional Azure OpenAI, Python package registry for `IntuneCD`, npm registry for `md-to-pdf`, and optionally OS package repositories when browser dependencies are installed for HTML/PDF generation. |
|
||||
| Does the system send data to AI services? | Only if Azure OpenAI summary generation is explicitly configured. It is optional for the platform overall. |
|
||||
| What AI service is intended? | A customer-controlled Azure OpenAI deployment configured through the Azure OpenAI endpoint and deployment variables, rather than an unrelated public AI service. |
|
||||
| What data is sent to Azure OpenAI when enabled? | A reduced change-review payload containing changed paths, semantic summaries, deterministic summary text, and fingerprints derived from the repo diff. This is intended to support review summarization, not raw tenant-wide export ingestion. |
|
||||
| Why is AI included? | The AI summary is meant to translate technical Intune and Entra drift into manager-readable language so PMs, management, and other non-specialist reviewers can understand impact and review intent without parsing raw policy JSON. |
|
||||
| Recommended deployment posture? | Start with backup-only or review-package mode, enable Azure OpenAI only on a customer-controlled deployment when approved, keep auto-remediation disabled by default, and use separate read-only and write-enabled service principals if restore is enabled. |
|
||||
| What customer-specific controls still need to be defined? | Agent type and hardening, repo/build/artifact retention, exact access groups, branch policies, and whether restore or Azure OpenAI are enabled in the target deployment. |
|
||||
Reference in New Issue
Block a user