diff --git a/.github/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE.md similarity index 100% rename from .github/pull_request_template.md rename to .github/PULL_REQUEST_TEMPLATE.md diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..3527b17 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,27 @@ +# Documentation Index + +This index maps the core architecture, guide, operations, and reference pages. + +## Architecture +- [Architecture Overview](architecture.md) +- [Architecture Deep Design](architecture/deep-design.md) +- [FSLogix Integration](architecture/fslogix-integration.md) + +## Guides +- [AVD Deployment Guide](guides/avd-deployment-guide.md) +- [RemoteApps Guide](guides/rdapps.md) + +## Operations and Security +- [Cost Management](operations/cost-management.md) +- [Defender Operations](security/defender-operations.md) + +## Reference +- [Host Pool Options](reference/host-pool-options.md) +- [Monitoring Queries](reference/monitoring-queries.md) +- [RBAC Reference](reference/rbac.md) +- [Docs Validation Checklist](reference/docs-validation-checklist.md) +- [Variable Mapping](reference/variable-mapping.md) +- [Tool Parity Matrix](reference/tool-parity-matrix.md) + +## Diagrams +- [Diagrams Index](diagrams/index.md) diff --git a/docs/architecture.md b/docs/architecture.md index 6ab1433..841c38a 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -60,6 +60,10 @@ The AVD architecture has two distinct planes: └──────────────┘ ``` +Diagram asset: + +![AVD on Azure Local reference architecture](diagrams/avd-reference-architecture.png) + --- ## Key Components @@ -135,3 +139,16 @@ Reference docs: - [FSLogix documentation](https://learn.microsoft.com/en-us/fslogix/) - [Arc Resource Bridge](https://learn.microsoft.com/en-us/azure/azure-arc/resource-bridge/overview) - [Companion SOFS/FSLogix repository](https://github.com/AzureLocal/azurelocal-sofs-fslogix) + +## Extended Documentation + +- [Architecture Deep Design](architecture/deep-design.md) +- [FSLogix Integration Guide](architecture/fslogix-integration.md) +- [Host Pool Options](reference/host-pool-options.md) +- [RBAC Reference](reference/rbac.md) +- [Monitoring Queries](reference/monitoring-queries.md) +- [Cost Management](operations/cost-management.md) +- [Defender Operations](security/defender-operations.md) +- [RemoteApps Guide](guides/rdapps.md) +- [Docs Validation Checklist](reference/docs-validation-checklist.md) +- [Diagrams Index](diagrams/index.md) diff --git a/docs/architecture/deep-design.md b/docs/architecture/deep-design.md new file mode 100644 index 0000000..ecab2d5 --- /dev/null +++ b/docs/architecture/deep-design.md @@ -0,0 +1,87 @@ +# Architecture Deep Design + +This page provides detailed architecture and decision guidance for AVD control-plane resources in Azure and session hosts on Azure Local. + +## Control plane: components and responsibilities +- Host Pool: logical grouping of session hosts. Defines `personal` vs `pooled` assignment, load-balancing behavior, and diagnostics scope. +- Application Group: publishes desktops or RemoteApps; ties to role assignments for end-user access. +- Workspace: user-facing aggregator; maps Application Groups to user experience. +- Key Vault: stores secrets used during provisioning (domain join credentials, certificates). Access controlled via Managed Identity or service principal. +- Log Analytics (LAW): central diagnostics ingestion for AVD control-plane categories and session-host telemetry. +- Storage: optional Azure Storage for MSIX app attach or cloud-backed FSLogix scenarios. + +Design notes: +- Treat the control plane as subscription-scoped and idempotent; prefer modules (Bicep modules / AVM) and expose outputs used by session-host provisioning (hostPoolId, workspaceId, lawResourceId). +- Use `Key Vault` for secrets; grant least-privilege access via managed identities on deployment principals. + +## Session-host topologies +- Single-cluster: one Azure Local cluster hosting all session hosts — simpler management, single point of failure at host level. +- Multi-cluster: multiple Azure Local clusters (regional or fault-domain separation) — requires cross-cluster identity and network planning. +- Distributed SOFS (guest cluster approach): recommended pattern — guest S2D cluster inside VMs provides FSLogix SMB shares with stacked resiliency (host CSV + guest S2D). + +## Identity patterns +- AD DS (domain-join): required for Azure Local when using on-premises SMB and Kerberos for FSLogix. +- Hybrid Entra ID: domain-joined + Entra registration; supports SSO and Conditional Access while maintaining Kerberos SMB for profiles. +- Entra-only + Cloud Cache: viable for Entra-only scenarios — requires FSLogix Cloud Cache (CCD) and cloud storage backing; increases complexity for SOFS integration. + +Recommendation: default to AD DS / hybrid Entra ID for Azure Local deployments unless the environment is Entra-native and cloud-based profile caching is acceptable. + +## Network design +- Egress: session-hosts must reach broker endpoints, Entra ID, Windows Update, and Log Analytics over HTTPS (443). +- SMB: keep FSLogix SMB traffic on the same L2/L3 domain (low latency). Avoid routing SMB across wide-area links. +- DNS: ensure session-hosts resolve both on-prem and Azure endpoints; consider split-horizon DNS for internal names. +- Ports & rules: document minimal required ports (RDP/UDP via AVD gateway handled by Azure; SMB 445 for profiles; WinRM 5985/5986 for automation). + +## DR, backups and availability +- Control-plane: maintain ARM/Bicep source of truth; backup Key Vault contents via Key Vault backup and export parameterized templates for faster recovery. +- FSLogix profiles: recommend backups of profile containers or use replication for SOFS (storage-level replication) and regularly test restore procedures. +- Disaster scenarios: document runbooks for control-plane redeploy from IaC, profile restore, and reprovisioning session-hosts from golden images. + +## Cost and sizing guidance +- Log Analytics: retention and ingestion drive costs; keep diagnostic categories scoped (only required categories) and use sampling for high-volume telemetry. +- Session-host sizing: provision VMs based on expected concurrency; prefer tested session density per SKU rather than overcommitting CPU; use autoscale to optimize costs. + +## Worked deployment patterns + +### Small footprint (up to 100 users) +- One pooled host pool. +- Single Azure Local cluster. +- One SOFS share and one Log Analytics workspace. + +### Medium footprint (100-500 users) +- Multiple app groups on shared host pools. +- Separate prod/non-prod host pools. +- Dedicated monitoring workspace and defined DR for profile containers. + +### Large footprint (500+ users) +- Multi-cluster session-host strategy. +- Segmented host pools by workload tier. +- Replicated profile storage and tested DR runbooks. + +## Outputs and contracts +- Ensure the control-plane module exports canonical outputs: + - `hostPoolResourceId` + - `applicationGroupResourceId` + - `workspaceResourceId` + - `logAnalyticsWorkspaceId` + - `keyVaultResourceId` + +These outputs are consumed by session-host provisioning modules and orchestration scripts. + +## Parameter mapping summary + +| Functional area | Canonical config | Bicep parameter family | Terraform variable family | PowerShell input | +|---|---|---|---|---| +| Host pool | `host_pool.*` | `hostPool*` | `host_pool_*` | `-HostPool*` | +| Diagnostics | `monitoring.*` | `logAnalytics*`, `diagnostic*` | `log_analytics_*` | `-LogAnalytics*` | +| Identity/RBAC | `identity.*`, `rbac.*` | `principal*`, `roleAssignment*` | `principal_*`, `role_assignment_*` | `-Principal*`, `-Role*` | +| FSLogix | `fslogix.*` | `fslogix*` | `fslogix_*` | `-FSLogix*` | + +## References +- Microsoft AVD docs: https://learn.microsoft.com/azure/virtual-desktop/ +- FSLogix docs: https://learn.microsoft.com/fslogix/ +- Azure Monitor diagnostic settings: https://learn.microsoft.com/azure/azure-monitor/alerts/diagnostic-settings +- Host pool guide: ../reference/host-pool-options.md +- FSLogix guide: ./fslogix-integration.md +- Monitoring guide: ../reference/monitoring-queries.md +- Cost guide: ../operations/cost-management.md diff --git a/docs/architecture/fslogix-integration.md b/docs/architecture/fslogix-integration.md new file mode 100644 index 0000000..76ca005 --- /dev/null +++ b/docs/architecture/fslogix-integration.md @@ -0,0 +1,135 @@ +# FSLogix Integration + +This guide defines how to run FSLogix profile containers for AVD session hosts on Azure Local with operationally safe defaults. + +## 1) Profile container model selection + +### VHDX on SMB (SOFS) +- Best for: Azure Local with low-latency SMB and AD DS/Kerberos. +- Pros: simple operations, predictable performance, no cloud dependency in steady state. +- Cons: recovery depends on storage replication/backup maturity. + +### Cloud Cache (CCD) +- Best for: multi-site resiliency, Entra-only patterns, or mixed storage backends. +- Pros: supports multiple providers and tolerates backend outages. +- Cons: higher write amplification, more tuning/monitoring complexity. + +Recommended default: use VHDX on SOFS for primary Azure Local designs and introduce CCD only where explicit DR/availability requirements justify complexity. + +## 2) Sizing and capacity planning + +Baseline sizing: +- Profile target per user: 25-40 GB (start with 30 GB). +- Free space buffer: 30% on the profile volume. +- Metadata growth allowance: 10% additional capacity. + +Planning formula: + +$$ +Required\ Capacity = (Users \times Profile\ Size) \times 1.4 +$$ + +Example: +- 400 users, 30 GB each: $400 \times 30 \times 1.4 = 16.8$ TB usable. + +## 3) SOFS and SMB configuration guidance + +Storage layout: +- Use dedicated CSV volumes for profile containers (separate from golden image/app content volumes). +- Use continuous availability SMB shares for profile paths. +- Keep storage traffic on dedicated east-west networks. + +SMB recommendations: +- SMB Multichannel enabled. +- SMB encryption only where required by policy (measure impact first). +- Access-based enumeration enabled for profile shares. + +Permissions baseline: +- Share permissions: `Authenticated Users` change, `Administrators` full control. +- NTFS: Creator Owner full on subfolders/files, users only to their own folders, admins/system full control. + +## 4) FSLogix registry baseline + +Primary keys under `HKLM:\SOFTWARE\FSLogix\Profiles`: +- `Enabled` (DWORD) = `1` +- `DeleteLocalProfileWhenVHDShouldApply` (DWORD) = `1` +- `FlipFlopProfileDirectoryName` (DWORD) = `1` +- `IsDynamic` (DWORD) = `1` +- `SizeInMBs` (DWORD) = `30720` (30 GB default) +- `VolumeType` (String) = `vhdx` +- `VHDLocations` (Multi-String) = `\\sofs\fslogixprofiles` + +PowerShell example: + +```powershell +$base = 'HKLM:\SOFTWARE\FSLogix\Profiles' +New-Item -Path $base -Force | Out-Null +New-ItemProperty -Path $base -Name Enabled -PropertyType DWord -Value 1 -Force | Out-Null +New-ItemProperty -Path $base -Name DeleteLocalProfileWhenVHDShouldApply -PropertyType DWord -Value 1 -Force | Out-Null +New-ItemProperty -Path $base -Name FlipFlopProfileDirectoryName -PropertyType DWord -Value 1 -Force | Out-Null +New-ItemProperty -Path $base -Name IsDynamic -PropertyType DWord -Value 1 -Force | Out-Null +New-ItemProperty -Path $base -Name SizeInMBs -PropertyType DWord -Value 30720 -Force | Out-Null +New-ItemProperty -Path $base -Name VolumeType -PropertyType String -Value 'vhdx' -Force | Out-Null +New-ItemProperty -Path $base -Name VHDLocations -PropertyType MultiString -Value '\\sofs\fslogixprofiles' -Force | Out-Null +``` + +Ansible example: + +```yaml +- name: Configure FSLogix registry baseline + ansible.windows.win_regedit: + path: HKLM:\SOFTWARE\FSLogix\Profiles + name: "{{ item.name }}" + data: "{{ item.data }}" + type: "{{ item.type }}" + state: present + loop: + - { name: Enabled, type: dword, data: 1 } + - { name: DeleteLocalProfileWhenVHDShouldApply, type: dword, data: 1 } + - { name: FlipFlopProfileDirectoryName, type: dword, data: 1 } + - { name: IsDynamic, type: dword, data: 1 } + - { name: SizeInMBs, type: dword, data: 30720 } + - { name: VolumeType, type: string, data: vhdx } + - { name: VHDLocations, type: multistring, data: '\\sofs\fslogixprofiles' } +``` + +## 5) Antivirus and performance exclusions + +Validate against security policy before applying exclusions. Common exclusions include: +- FSLogix process paths (`frxsvc.exe`, `frxrobocopy.exe`). +- Profile container share path. +- VHD(X) attach points. + +Always verify exclusions with security operations and Defender policy owners. + +## 6) DR and backup strategy + +Minimum controls: +- Daily backup of FSLogix container volumes. +- Replication across fault domains or secondary site for critical workloads. +- Quarterly restore test using representative profile containers. + +Recovery objective guidance: +- Define profile RPO/RTO explicitly in operations runbooks. +- Validate sign-in performance after restore and check profile lock cleanup. + +## 7) Validation tests + +Post-deployment checks: +- User sign-in creates and mounts profile VHDX. +- Re-sign-in lands on same profile state across hosts. +- Event logs show no recurring `frxsvc` attach errors. +- SMB latency and IO remain within baseline thresholds. + +PowerShell validation example: + +```powershell +Get-WinEvent -LogName 'Microsoft-FSLogix-Apps/Operational' -MaxEvents 100 | + Where-Object { $_.LevelDisplayName -in 'Error','Warning' } | + Select-Object TimeCreated, Id, Message +``` + +## Related references +- Companion SOFS repo: https://github.com/AzureLocal/azurelocal-sofs-fslogix +- FSLogix docs: https://learn.microsoft.com/fslogix/ +- Deep architecture design: ../deep-design.md diff --git a/docs/audit/docs-audit.md b/docs/audit/docs-audit.md new file mode 100644 index 0000000..960d7f9 --- /dev/null +++ b/docs/audit/docs-audit.md @@ -0,0 +1,46 @@ +# Documentation Audit — azurelocal-avd + +Generated: 2026-03-22 + +## Overview +This audit lists existing documentation files in `azurelocal-avd` and recommended edits/additions to align with Epic #8 documentation plan. + +## Existing key docs (reviewed) +- `docs/architecture.md` — High-level architecture (exists) +- `docs/guides/avd-deployment-guide.md` — Deployment guide (exists) +- `docs/reference/monitoring-queries.md` — Monitoring KQLs (exists) +- `docs/reference/tool-parity-matrix.md` — Tool parity (exists) +- `docs/reference/variable-mapping.md` — Variable mapping (exists) + +## Recommended new pages (stubs created) +- `docs/architecture/deep-design.md` — deeper design (created) +- `docs/architecture/fslogix-integration.md` — FSLogix integration (created) +- `docs/reference/host-pool-options.md` — host-pool config options (created) +- `docs/guides/rdapps.md` — RemoteApps publishing guide (created) +- `docs/operations/defender-operations.md` — Defender & security (created) +- `docs/operations/cost-management.md` — cost management (created) +- `docs/diagrams/README.md` — diagrams guidance (created) +- `docs/README.md` — docs index (created) + +## Files that should be updated (high priority) +- `docs/architecture.md` — add links to new deep-design and FSLogix pages; include decision flows and diagram references +- `docs/guides/avd-deployment-guide.md` — update steps to reference new RBAC/FSLogix/host-pool docs +- `docs/reference/monitoring-queries.md` — expand with LAW table mappings and cost-related KQL samples +- `mkdocs.yml` — ensure `docs/diagrams` included and `mkdocs-drawio` plugin is configured (CI currently installs mkdocs-drawio) +- `.github/workflows/validate-repo-structure.yml` — ensure checks accept new files; add docs lint/check step if not present + +## Reusable assets in `azurelocal-sofs-fslogix` +(Do NOT edit SOFS repo; reference or copy exported PNGs) +- `docs/assets/diagrams/sofs-deployment-phases.drawio` (draw.io source) +- `docs/assets/images/sofs-deployment-phases.png` (exported image) +- `docs/architecture/storage-design.md`, `capacity-planning.md`, `scenarios.md`, `avd-considerations.md` + +## Next recommended actions (short-term) +1. Review and accept the created stubs in a docs PR. +2. Copy selected exported PNGs from `azurelocal-sofs-fslogix` into `docs/diagrams/` in this repo (no edits to SOFS repo). +3. Populate `deep-design.md` and `fslogix-integration.md` with content adapted from SOFS docs and Microsoft references. +4. Add draw.io source files in `docs/diagrams/` for AVD-specific diagrams (control-plane, network, DR) and export PNG/SVG. + +## Contacts / Owners +- Docs owner: maintainers of `azurelocal-avd` (please assign an architecture reviewer) + diff --git a/docs/diagrams/README.md b/docs/diagrams/README.md new file mode 100644 index 0000000..ad2ebe4 --- /dev/null +++ b/docs/diagrams/README.md @@ -0,0 +1,20 @@ +# Diagrams + +This directory contains architecture diagram sources and rendered assets for AVD on Azure Local documentation. + +## Standards +- Use draw.io (`.drawio`) for editable sources. +- Keep exported `.png` and `.svg` for MkDocs compatibility. +- Name diagrams by function and scope (for example `control-plane`, `network-flow`, `dr-recovery`). + +## Included assets +- `control-plane.drawio` +- `avd-reference-architecture.drawio` +- `avd-reference-architecture.png` +- `sofs-deployment-phases.drawio` +- `sofs-deployment-phases.png` + +## Workflow +1. Edit diagram in draw.io. +2. Export PNG and SVG to this folder. +3. Update `docs/diagrams/index.md` if a new asset is added. diff --git a/docs/diagrams/avd-reference-architecture.drawio b/docs/diagrams/avd-reference-architecture.drawio new file mode 100644 index 0000000..08bc17c --- /dev/null +++ b/docs/diagrams/avd-reference-architecture.drawio @@ -0,0 +1,426 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/diagrams/avd-reference-architecture.png b/docs/diagrams/avd-reference-architecture.png new file mode 100644 index 0000000..2597885 Binary files /dev/null and b/docs/diagrams/avd-reference-architecture.png differ diff --git a/docs/diagrams/control-plane.drawio b/docs/diagrams/control-plane.drawio new file mode 100644 index 0000000..65c73a8 --- /dev/null +++ b/docs/diagrams/control-plane.drawio @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/diagrams/control-plane.png b/docs/diagrams/control-plane.png new file mode 100644 index 0000000..16ce349 Binary files /dev/null and b/docs/diagrams/control-plane.png differ diff --git a/docs/diagrams/index.md b/docs/diagrams/index.md new file mode 100644 index 0000000..baa1d68 --- /dev/null +++ b/docs/diagrams/index.md @@ -0,0 +1,19 @@ +# Diagrams Index + +This folder stores draw.io source files and rendered images used by docs pages. + +## Current assets +- `control-plane.drawio`: control-plane and integration topology source. +- `avd-reference-architecture.drawio`: end-to-end AVD on Azure Local architecture source. +- `avd-reference-architecture.png`: rendered architecture image. +- `sofs-deployment-phases.drawio`: SOFS deployment flow source. +- `sofs-deployment-phases.png`: exported image for static rendering. + +## Rendering guidance +- Keep `.drawio` as source of truth. +- Export `.png` and `.svg` for documentation consumption. +- Reference rendered files in architecture and operations pages. + +## Consumption links +- [Architecture Overview](../architecture.md) +- [Deep Design](../architecture/deep-design.md) diff --git a/docs/diagrams/sofs-deployment-phases.drawio b/docs/diagrams/sofs-deployment-phases.drawio new file mode 100644 index 0000000..e18d040 --- /dev/null +++ b/docs/diagrams/sofs-deployment-phases.drawio @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/diagrams/sofs-deployment-phases.png b/docs/diagrams/sofs-deployment-phases.png new file mode 100644 index 0000000..4a68d1d Binary files /dev/null and b/docs/diagrams/sofs-deployment-phases.png differ diff --git a/docs/guides/avd-deployment-guide.md b/docs/guides/avd-deployment-guide.md index b43b50b..3e1b575 100644 --- a/docs/guides/avd-deployment-guide.md +++ b/docs/guides/avd-deployment-guide.md @@ -34,6 +34,9 @@ Also review: - [Tool Parity Matrix](../reference/tool-parity-matrix.md) - [Phase Ownership](../reference/phase-ownership.md) - [Monitoring Queries](../reference/monitoring-queries.md) +- [Host Pool Options](../reference/host-pool-options.md) +- [RBAC Reference](../reference/rbac.md) +- [FSLogix Integration](../architecture/fslogix-integration.md) --- @@ -141,3 +144,5 @@ Run monitoring checks in Log Analytics using [Monitoring Queries](../reference/m - Review [deployment scenarios](../scenarios.md) for different configurations - Set up CI/CD pipelines using the examples in `examples/pipelines/` for automated deployments - Deploy [FSLogix profiles](https://github.com/AzureLocal/azurelocal-sofs-fslogix) with the companion repo +- Publish applications using [RemoteApps Guide](rdapps.md) +- Review [Cost Management](../operations/cost-management.md) and [Defender Operations](../security/defender-operations.md) diff --git a/docs/guides/rdapps.md b/docs/guides/rdapps.md new file mode 100644 index 0000000..8dd585f --- /dev/null +++ b/docs/guides/rdapps.md @@ -0,0 +1,95 @@ +# RemoteApps (RDApps) Publishing Guide + +This guide covers publishing RemoteApps through AVD Application Groups and operating them at scale on Azure Local session-host infrastructure. + +## 1) RemoteApp vs Desktop publishing + +Use RemoteApp when: +- Users need one or a few business applications. +- You want tighter app-level access control. +- You need lower endpoint resource overhead than full desktop sessions. + +Use Desktop when: +- Users require broad shell access and personalized environments. +- App dependencies are difficult to isolate. + +## 2) Application Group model + +Recommended structure: +- One host pool per workload class. +- Separate Application Groups by department or app criticality. +- One Workspace per business unit or environment boundary. + +Naming example: +- `ag-finance-remoteapp-prod` +- `ag-engineering-remoteapp-prod` + +## 3) Publish RemoteApps + +PowerShell example: + +```powershell +# Create RemoteApp application group +New-AzWvdApplicationGroup -ResourceGroupName $rg -Location $location ` + -HostPoolArmPath $hostPoolId -Name 'ag-finance-remoteapp-prod' -ApplicationGroupType 'RemoteApp' + +# Publish an application +New-AzWvdApplication -ResourceGroupName $rg -GroupName 'ag-finance-remoteapp-prod' ` + -Name 'NotepadPP' -FilePath 'C:\Program Files\Notepad++\notepad++.exe' ` + -CommandLineSetting 'DoNotAllow' + +# Assign group to workspace +Register-AzWvdApplicationGroup -ResourceGroupName $rg -WorkspaceName $workspaceName ` + -ApplicationGroupPath $appGroupId +``` + +## 4) RBAC for app assignment + +Minimum assignment pattern: +- Assign end users to Application Group scope (not subscription scope). +- Keep operator roles separated from security/audit roles. +- Prefer Entra groups over direct user assignment. + +## 5) MSIX app attach and FSLogix + +Guidance: +- Use MSIX for clean app lifecycle and version rollback. +- Keep user-state in FSLogix profile containers. +- Separate app package storage from profile container shares. + +Operational notes: +- Validate package mount latency during sign-in peaks. +- Track package update windows to avoid user session disruption. + +## 6) Diagnostics and monitoring + +Track: +- Application launch failures by app group. +- Session disconnects correlated with app startup events. +- Per-app user concurrency trends. + +Starter KQL (app group trends): + +```kusto +WVDConnections +| where TimeGenerated > ago(24h) +| summarize Connections=count(), Users=dcount(UserName) by HostPoolName, bin(TimeGenerated, 1h) +| order by TimeGenerated asc +``` + +## 7) Scaling patterns for RemoteApps +- Keep app groups small and domain-aligned for clear ownership. +- Split high-demand apps to dedicated host pools when noisy-neighbor effects appear. +- Use depth-first pools for cost-centric workloads and breadth-first where user experience is primary. + +## 8) Validation checklist +- RemoteApp appears in user feed. +- Launch succeeds from multiple client types. +- App group assignment respects least privilege. +- Telemetry shows stable launch and session metrics. + +## References +- AVD RemoteApp overview: https://learn.microsoft.com/azure/virtual-desktop/remote-app-streaming/overview +- Manage application groups: https://learn.microsoft.com/azure/virtual-desktop/manage-app-groups +- MSIX app attach: https://learn.microsoft.com/azure/virtual-desktop/app-attach-overview +- FSLogix documentation: https://learn.microsoft.com/fslogix/ diff --git a/docs/operations/cost-management.md b/docs/operations/cost-management.md new file mode 100644 index 0000000..e633dd4 --- /dev/null +++ b/docs/operations/cost-management.md @@ -0,0 +1,88 @@ +# Cost Management and Attribution + +This guide provides a cost model and operating practices for AVD deployments where control-plane resources run in Azure and session hosts run on Azure Local. + +## 1) Cost domains + +### Azure control-plane costs +- AVD service-related Azure resources (Log Analytics, Key Vault, optional Storage). +- Monitoring and data ingestion. +- Optional app package storage and backup services. + +### Azure Local session-host costs +- Compute and storage consumption on-premises. +- Licensing and operations overhead. +- Network and backup infrastructure costs. + +## 2) Tagging strategy for attribution + +Apply consistent tags to every Azure resource: +- `service = avd` +- `environment = dev|test|prod` +- `owner = team-name` +- `cost-center = finance-code` +- `workload = control-plane|monitoring|identity|storage` + +Use the same logical labels in on-prem cost reporting for reconciliation. + +## 3) Log Analytics retention planning + +Retention guidance: +- Start with 30 days for operational workspaces. +- Increase only for compliance requirements. +- Route high-volume diagnostics selectively to reduce ingestion overhead. + +Key principle: ingest only categories that map to actionable alerts or reporting. + +## 4) Cost analysis views + +Recommended Azure Cost Management views: +- Cost by resource group (control-plane vs monitoring). +- Cost by tag (`workload`, `environment`, `cost-center`). +- Daily cost trend with anomaly detection. + +## 5) KQL samples for cost signals + +Ingestion by table: + +```kusto +Usage +| where TimeGenerated > ago(30d) +| summarize GB=sum(Quantity) / 1000 by DataType +| order by GB desc +``` + +Daily ingestion trend: + +```kusto +Usage +| where TimeGenerated > ago(30d) +| summarize GB=sum(Quantity) / 1000 by bin(TimeGenerated, 1d) +| order by TimeGenerated asc +``` + +Per-host heartbeat proxy for active footprint: + +```kusto +Heartbeat +| where TimeGenerated > ago(7d) +| summarize ActiveDays=dcount(bin(TimeGenerated, 1d)) by Computer +| order by ActiveDays desc +``` + +## 6) Optimization playbook +- Tune diagnostic categories and reduce noisy tables. +- Use depth-first pools where user-experience impact is acceptable. +- Right-size session hosts using measured concurrency, not peak speculation. +- Review unattached storage and stale analytics retention monthly. + +## 7) Monthly governance checklist +- Validate tag completeness and fix missing tags. +- Compare budget vs actual by environment. +- Review top 10 cost-driving resources. +- Validate autoscale policy effectiveness. +- Capture optimization actions with owners and due dates. + +## References +- Azure Cost Management: https://learn.microsoft.com/azure/cost-management-billing/ +- Azure Monitor cost planning: https://learn.microsoft.com/azure/azure-monitor/logs/cost-logs diff --git a/docs/operations/defender-operations.md b/docs/operations/defender-operations.md new file mode 100644 index 0000000..8c6d353 --- /dev/null +++ b/docs/operations/defender-operations.md @@ -0,0 +1,5 @@ +# Defender Operations + +Security operations content for Defender is maintained in `docs/security/defender-operations.md`. + +Use this page as an operations entry point and keep the canonical guidance in the security section. diff --git a/docs/reference/docs-validation-checklist.md b/docs/reference/docs-validation-checklist.md new file mode 100644 index 0000000..b89d576 --- /dev/null +++ b/docs/reference/docs-validation-checklist.md @@ -0,0 +1,26 @@ +# Docs Validation and Review Checklist + +Use this checklist for every docs-only PR. + +## Automated validation +- Confirm all markdown links resolve. +- Confirm `mkdocs.yml` nav entries point to existing files. +- Confirm each diagram source (`.drawio`) has a rendered image (`.png` and/or `.svg`) when referenced in docs. +- Confirm no temporary placeholder text remains (`TODO`, `TBD`, `placeholder`) unless explicitly marked as owner action. + +## Content quality checks +- Verify all configuration examples align with `config/variables.yml` naming. +- Verify AVD terminology is consistent (`host pool`, `application group`, `workspace`). +- Verify references point to current Microsoft docs. +- Verify security guidance aligns with least-privilege RBAC patterns. + +## Required sign-offs +- Architecture owner: required for architecture, networking, identity, FSLogix, DR, and host pool behavior changes. +- Security owner: required for Defender and RBAC guidance changes. +- Operations owner: required for monitoring, cost, and runbook updates. + +## PR template prompts +- What docs changed and why? +- What diagrams were updated, and were exports regenerated? +- What assumptions remain environment-specific? +- Which owner approved architecture/security content? \ No newline at end of file diff --git a/docs/reference/host-pool-options.md b/docs/reference/host-pool-options.md new file mode 100644 index 0000000..7cf7de5 --- /dev/null +++ b/docs/reference/host-pool-options.md @@ -0,0 +1,118 @@ +# Host Pool Options (Pooled and Personal) + +This reference defines host pool behavior, parameter mapping, and recommended autoscale patterns. + +## 1) Host pool types + +### Pooled +- Purpose: shared compute for task workers, call centers, and shift-based operations. +- Load balancing options: + - `BreadthFirst`: spreads users across hosts. + - `DepthFirst`: fills hosts before moving to next host. +- Recommended baseline: + - `BreadthFirst` for user-experience consistency. + - `DepthFirst` for cost-optimized autoscale scenarios. + +### Personal +- Purpose: dedicated VM per user for developers, engineers, privileged workflows. +- Assignment: + - `Automatic`: first available VM assigned at first sign-in. + - `Direct`: preassigned VM-to-user mapping by operations. +- Recommended baseline: `Direct` where strict ownership/compliance is needed. + +## 2) Core parameter reference + +| Parameter | Scope | Applies To | Notes | +|---|---|---|---| +| `hostPoolType` | Host pool | Pooled/Personal | `Pooled` or `Personal` | +| `loadBalancingType` | Host pool | Pooled | `BreadthFirst` or `DepthFirst` | +| `maxSessionLimit` | Host pool | Pooled | Set from load-test data | +| `personalDesktopAssignmentType` | Host pool | Personal | `Automatic` or `Direct` | +| `startVMOnConnect` | Host pool | Both | Requires RBAC + service principal | +| `registrationTokenExpiration` | Host registration | Both | Short-lived token recommended | + +## 3) Configuration mapping + +| Canonical key (`config/variables.yml`) | Bicep | Terraform | PowerShell | +|---|---|---|---| +| `host_pool.type` | `hostPoolType` | `host_pool_type` | `-HostPoolType` | +| `host_pool.load_balancing` | `loadBalancingType` | `load_balancing_type` | `-LoadBalancingType` | +| `host_pool.max_sessions` | `maxSessionLimit` | `max_session_limit` | `-MaxSessionLimit` | +| `host_pool.personal_assignment` | `personalDesktopAssignmentType` | `personal_desktop_assignment_type` | `-PersonalAssignmentType` | +| `host_pool.start_vm_on_connect` | `startVMOnConnect` | `start_vm_on_connect` | `-StartVMOnConnect` | + +## 4) Implementation examples + +Bicep (pooled): + +```bicep +param hostPoolType string = 'Pooled' +param loadBalancingType string = 'BreadthFirst' +param maxSessionLimit int = 12 + +resource hostPool 'Microsoft.DesktopVirtualization/hostPools@2024-04-03' = { + name: 'hp-pooled-prod' + location: resourceGroup().location + properties: { + hostPoolType: hostPoolType + loadBalancerType: loadBalancingType + maxSessionLimit: maxSessionLimit + startVMOnConnect: true + preferredAppGroupType: 'Desktop' + } +} +``` + +Terraform (personal): + +```hcl +resource "azurerm_virtual_desktop_host_pool" "personal" { + name = "hp-personal-prod" + location = azurerm_resource_group.avd.location + resource_group_name = azurerm_resource_group.avd.name + type = "Personal" + personal_desktop_assignment_type = "Direct" + start_vm_on_connect = true +} +``` + +PowerShell: + +```powershell +New-AzWvdHostPool -ResourceGroupName $rg -Name 'hp-pooled-prod' -Location $location ` + -HostPoolType 'Pooled' -LoadBalancerType 'BreadthFirst' -MaxSessionLimit 12 -StartVMOnConnect:$true +``` + +## 5) Autoscale patterns + +### Schedule-first +- Start baseline capacity before business hours. +- Drain and stop non-required hosts after hours. + +### Load-first +- Increase hosts on session/cpu thresholds. +- Decrease hosts on sustained low utilization. + +### Hybrid +- Schedule baseline + dynamic headroom during peaks. + +Recommended controls: +- Reserve at least one spare host per pool. +- Use drain mode before host maintenance. +- Keep scale actions idempotent and logged. + +## 6) Start VM on Connect requirements +- App registration/service principal authorized on subscription/RG scope. +- Required roles: VM start permission, AVD host pool access. +- Validate startup latency with login SLA tests. + +## 7) Operational checks +- Track session distribution by host and pool. +- Alert on host pools with registration or heartbeat drops. +- Review `maxSessionLimit` quarterly against real concurrency. + +## References +- AVD host pool overview: https://learn.microsoft.com/azure/virtual-desktop/host-pool-load-balancing +- Personal desktop assignment: https://learn.microsoft.com/azure/virtual-desktop/configure-host-pool-personal-desktop-assignment-type +- Autoscale for pooled host pools: https://learn.microsoft.com/azure/virtual-desktop/autoscale-scaling-plan +- Start VM on Connect: https://learn.microsoft.com/azure/virtual-desktop/start-virtual-machine-connect diff --git a/docs/reference/monitoring-queries.md b/docs/reference/monitoring-queries.md index 6776969..d22b8ca 100644 --- a/docs/reference/monitoring-queries.md +++ b/docs/reference/monitoring-queries.md @@ -1,25 +1,51 @@ -# Monitoring Validation Queries +# Monitoring, Diagnostics, and KQL Queries -Run these queries in Log Analytics after deployment to validate diagnostics and host readiness. +Use this page to validate observability coverage across AVD control-plane resources and Azure Local session-host workloads. -## Agent Health +## 1) Diagnostic categories by resource + +| Resource | Recommended categories | Destination | +|---|---|---| +| Host Pool | `Management`, `Error`, `Checkpoint` | Log Analytics | +| Application Group | `Management`, `Error` | Log Analytics | +| Workspace | `Management`, `Error` | Log Analytics | +| Key Vault | `AuditEvent` | Log Analytics | +| Azure Activity | Subscription activity logs | Log Analytics | + +## 2) Common Log Analytics tables + +| Table | Purpose | +|---|---| +| `WVDConnections` | Session connection and reconnection events | +| `WVDErrors` | Service and agent-side AVD errors | +| `WVDAgentHealthStatus` | Session host agent state and freshness | +| `WVDCheckpoints` | Broker/session workflow checkpoints | +| `Heartbeat` | VM liveness and MMA/AMA heartbeat | +| `AzureDiagnostics` | Unified diagnostics for configured Azure resources | +| `SecurityEvent` | Security events from Windows session hosts | + +## 3) Health and availability queries + +### Agent health by host pool ```kusto WVDAgentHealthStatus | where TimeGenerated > ago(1h) | summarize LastSeen=max(TimeGenerated), Hosts=dcount(SessionHostName) by HostPoolName +| order by LastSeen asc ``` -## Connection Volume +### Session host heartbeat freshness ```kusto -WVDConnections -| where TimeGenerated > ago(24h) -| summarize Connections=count() by UserName, HostPoolName -| order by Connections desc +Heartbeat +| where TimeGenerated > ago(15m) +| summarize LastHeartbeat=max(TimeGenerated) by Computer +| extend MinutesSinceHeartbeat = datetime_diff('minute', now(), LastHeartbeat) +| order by MinutesSinceHeartbeat desc ``` -## Error Summary +### Error summary by symbol ```kusto WVDErrors @@ -28,20 +54,82 @@ WVDErrors | order by Errors desc ``` -## Heartbeat +## 4) User experience queries + +### Connection trends (hourly) ```kusto -Heartbeat -| where TimeGenerated > ago(5m) -| summarize LastHeartbeat=max(TimeGenerated) by Computer -| order by LastHeartbeat desc +WVDConnections +| where TimeGenerated > ago(7d) +| summarize Connections=count(), Users=dcount(UserName) by HostPoolName, bin(TimeGenerated, 1h) +| order by TimeGenerated asc ``` -## Checkpoints +### Top reconnect users ```kusto -WVDCheckpoints -| where TimeGenerated > ago(1h) -| summarize Events=count() by Source, Name +WVDConnections +| where TimeGenerated > ago(24h) +| summarize Connections=count() by UserName, HostPoolName +| order by Connections desc +| take 25 +``` + +## 5) FSLogix and profile reliability queries + +### FSLogix warnings/errors from Windows events + +```kusto +Event +| where TimeGenerated > ago(24h) +| where Source == 'frxsvc' +| summarize Events=count() by EventLevelName, Computer | order by Events desc ``` + +### Profile attach error trend + +```kusto +Event +| where TimeGenerated > ago(7d) +| where Source == 'frxsvc' and EventLevelName in ('Error','Warning') +| summarize Count=count() by bin(TimeGenerated, 1h), Computer +| order by TimeGenerated asc +``` + +## 6) Cost sampling queries + +### Ingestion estimate by table (last 24h) + +```kusto +Usage +| where TimeGenerated > ago(24h) +| summarize GB=sum(Quantity) / 1000 by DataType +| order by GB desc +``` + +### Daily ingestion trend + +```kusto +Usage +| where TimeGenerated > ago(30d) +| summarize GB=sum(Quantity) / 1000 by bin(TimeGenerated, 1d) +| order by TimeGenerated asc +``` + +## 7) Alerting recommendations +- Agent health staleness over 10 minutes. +- Error rate spike over rolling baseline. +- Heartbeat missing for critical session-host groups. +- Log Analytics ingestion anomaly (sharp day-over-day increase). + +## 8) Operational run frequency +- Hourly: host heartbeat and active error checks. +- Daily: connection trend and ingestion checks. +- Weekly: host-pool balancing and user-density review. + +## References +- Azure Monitor: https://learn.microsoft.com/azure/azure-monitor/ +- Azure Monitor diagnostic settings: https://learn.microsoft.com/azure/azure-monitor/essentials/diagnostic-settings +- AVD diagnostic categories: https://learn.microsoft.com/azure/virtual-desktop/diagnostics-log-analytics +- Log Analytics query language (KQL): https://learn.microsoft.com/azure/azure-monitor/logs/log-analytics-overview diff --git a/docs/reference/rbac.md b/docs/reference/rbac.md new file mode 100644 index 0000000..ea88115 --- /dev/null +++ b/docs/reference/rbac.md @@ -0,0 +1,70 @@ +# RBAC Reference + +This page provides least-privilege role mapping for AVD control-plane deployment and operations. + +## 1) Role matrix + +| Persona | Scope | Recommended role(s) | +|---|---|---| +| Platform engineer | Subscription/RG | `Contributor` (deployment scope only) | +| Security operations | Subscription/RG | `Reader`, `Security Reader` | +| Monitoring operations | Log Analytics | `Log Analytics Reader` | +| Helpdesk (user session support) | Host pool / app group | `Desktop Virtualization Reader` + operational custom role as needed | +| End users | Application Group | `Desktop Virtualization User` | + +## 2) Least-privilege principles +- Assign at the narrowest possible scope. +- Use Entra groups instead of direct user role assignments. +- Separate deployment roles from operations roles. +- Use temporary elevation (PIM) for high-privilege actions. + +## 3) Example custom role (deployment manager) + +```json +{ + "Name": "AVD.DeploymentManager", + "Description": "Deploy and update AVD control-plane resources without full subscription owner rights.", + "Actions": [ + "Microsoft.DesktopVirtualization/*", + "Microsoft.Insights/diagnosticSettings/*", + "Microsoft.OperationalInsights/workspaces/read", + "Microsoft.Authorization/roleAssignments/read", + "Microsoft.Resources/subscriptions/resourceGroups/read" + ], + "NotActions": [ + "Microsoft.Authorization/roleAssignments/delete" + ], + "AssignableScopes": [ + "/subscriptions//resourceGroups/" + ] +} +``` + +## 4) CLI assignment examples + +```bash +az role assignment create \ + --assignee-object-id \ + --assignee-principal-type Group \ + --role "Desktop Virtualization User" \ + --scope /subscriptions//resourceGroups//providers/Microsoft.DesktopVirtualization/applicationGroups/ +``` + +```bash +az role assignment create \ + --assignee-object-id \ + --assignee-principal-type Group \ + --role "Log Analytics Reader" \ + --scope /subscriptions//resourceGroups//providers/Microsoft.OperationalInsights/workspaces/ +``` + +## 5) PowerShell assignment example + +```powershell +New-AzRoleAssignment -ObjectId $GroupObjectId -RoleDefinitionName "Desktop Virtualization User" -Scope $AppGroupScope +``` + +## 6) Governance checks +- Weekly: detect direct user assignments at subscription scope. +- Monthly: review stale privileged role assignments. +- Quarterly: role recertification with service owners. diff --git a/docs/security/defender-operations.md b/docs/security/defender-operations.md new file mode 100644 index 0000000..7bfa26e --- /dev/null +++ b/docs/security/defender-operations.md @@ -0,0 +1,60 @@ +# Defender and Security Hardening + +This guide defines baseline security controls for AVD control-plane and Azure Local session-host operations. + +## 1) Defender for Cloud baseline + +Enable and review: +- Defender plans required by the deployed resource mix. +- Secure Score recommendations for subscription/resource groups hosting AVD resources. +- Regulatory compliance mapping used by your organization. + +Operational cadence: +- Daily triage of high-severity recommendations. +- Weekly review of unresolved medium-severity findings. + +## 2) Session-host endpoint protection + +Required controls: +- Defender for Endpoint onboarding for all session hosts. +- Tamper protection and cloud-delivered protection enabled. +- ASR (Attack Surface Reduction) rules tested in audit mode, then enforced. + +FSLogix-aware considerations: +- Validate any process/path exclusions with security owners before rollout. +- Revalidate exclusions quarterly. + +## 3) Identity and access hardening +- Require MFA and conditional access for privileged roles. +- Use PIM/JIT for elevated access. +- Assign least-privilege roles at resource-group or resource scope. + +## 4) Policy recommendations +- Enforce diagnostics to Log Analytics for AVD resources. +- Require approved locations and tag policy. +- Block legacy auth where applicable. +- Audit public network exposure for related services. + +## 5) Alerting and incident response + +Alert classes: +- Suspicious sign-in and impossible travel. +- Malware/ransomware signals on session hosts. +- Repeated profile mount failures with security correlations. + +Response runbook minimum: +1. Isolate impacted host. +2. Collect forensic artifacts. +3. Reimage host from trusted image. +4. Validate profile/container integrity. +5. Rotate credentials/tokens if needed. + +## 6) Validation checklist +- Defender onboarding complete for 100% of session hosts. +- All critical recommendations triaged. +- Security alerts integrated into SOC workflow. +- Quarterly tabletop exercise completed for AVD incident scenario. + +## References +- Defender for Cloud: https://learn.microsoft.com/azure/defender-for-cloud/ +- Defender for Endpoint: https://learn.microsoft.com/microsoft-365/security/defender-endpoint/ diff --git a/mkdocs.yml b/mkdocs.yml index 9c02cb0..13cd3eb 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -34,16 +34,27 @@ theme: nav: - Home: index.md - Architecture: architecture.md + - Deep Architecture: + - Deep Design: architecture/deep-design.md + - FSLogix Integration: architecture/fslogix-integration.md - Getting Started: getting-started.md - Guides: - AVD Deployment Guide: guides/avd-deployment-guide.md + - RemoteApps Guide: guides/rdapps.md - Scenarios: scenarios.md + - Operations: + - Cost Management: operations/cost-management.md + - Defender Operations: security/defender-operations.md - Reference: - Variables: reference/variables.md - Variable Mapping: reference/variable-mapping.md - Tool Parity Matrix: reference/tool-parity-matrix.md - Phase Ownership: reference/phase-ownership.md - Monitoring Queries: reference/monitoring-queries.md + - Host Pool Options: reference/host-pool-options.md + - RBAC Reference: reference/rbac.md + - Docs Validation Checklist: reference/docs-validation-checklist.md + - Diagrams: diagrams/index.md - Standards: - Overview: standards/index.md - Documentation: standards/documentation.md