Skip to content

Add sovereign cloud landing zone module structure and orchestration#8

Merged
Jasazure merged 3 commits intomainfrom
copilot/update-repository-structure
Mar 5, 2026
Merged

Add sovereign cloud landing zone module structure and orchestration#8
Jasazure merged 3 commits intomainfrom
copilot/update-repository-structure

Conversation

Copy link
Copy Markdown

Copilot AI commented Mar 5, 2026

Implements the repository structure for the sovereign cloud platform landing zone: domain-organized Bicep modules, a main orchestration template, environment parameter files, and an annotated directory tree document.

Module structure (modules/sovereign/)

Seven existing Bicep modules reorganized by functional domain:

  • policy/ — Policy initiative (subscription scope)
  • encryption/ — Key Vault CMK + TLS enforcement
  • confidential-compute/ — Confidential VM + AKS node pool
  • hybrid-arc/ — Arc governance + Machine Configuration
  • identity/ — RBAC assignments

Orchestration (deployments/sovereign-baseline/)

  • main.bicep — Subscription-scoped entry point composing all 7 modules. Creates two resource groups (workload, arc), wires cross-module parameters. Confidential VM and AKS node pool are gated behind boolean toggles to avoid accidental expensive deployments.
  • dev.parameters.jsonDoNotEnforce policy mode, compute disabled
  • prod.parameters.jsonDefault enforcement, production KV name

All paths match the existing deploy-sovereign-lz.yml workflow references (az bicep lint/build --file deployments/sovereign-baseline/main.bicep).

Documentation

  • REPOSITORY_STRUCTURE.md — Annotated directory tree, module composition data-flow diagram, CI/CD integration mapping

.gitignore

Added negation pattern for deployments/sovereign-baseline/*.parameters.json — files contain only placeholder GUIDs, no secrets.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • aka.ms
    • Triggering command: /usr/local/bin/bicep bicep lint deployments/sovereign-baseline/main.bicep (dns block)
    • Triggering command: /usr/local/bin/bicep bicep build deployments/sovereign-baseline/main.bicep --outfile /tmp/sovereign-lz.json (dns block)
    • Triggering command: /usr/local/bin/bicep bicep lint modules/sovereign/confidential-compute/sovereign-confidential-aks-nodepool.bicep (dns block)

If you need me to access, download, or install something from one of these locations, you can either:


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 2 commits March 5, 2026 12:11
…arams, and documentation

- Create modules/sovereign/ with 7 Bicep modules organized by domain:
  policy/, encryption/, confidential-compute/, hybrid-arc/, identity/
- Create deployments/sovereign-baseline/main.bicep orchestration template
- Create dev.parameters.json and prod.parameters.json environment configs
- Create REPOSITORY_STRUCTURE.md with annotated directory tree, module
  composition diagram, and CI/CD integration documentation

Co-authored-by: Jasazure <233270744+Jasazure@users.noreply.github.com>
…eline

Add .gitignore exception for deployments/sovereign-baseline/*.parameters.json
to include the environment parameter files (contain only placeholder values).

Co-authored-by: Jasazure <233270744+Jasazure@users.noreply.github.com>
Copilot AI changed the title [WIP] Update repository structure for sovereign cloud modules Add sovereign cloud landing zone module structure and orchestration Mar 5, 2026
@Jasazure Jasazure marked this pull request as ready for review March 5, 2026 12:22
Copilot AI review requested due to automatic review settings March 5, 2026 12:22
@Jasazure Jasazure merged commit 61be11a into main Mar 5, 2026
4 of 5 checks passed
@Jasazure Jasazure deleted the copilot/update-repository-structure branch March 5, 2026 12:23
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a sovereign landing zone layout to the repo, including domain-organized Bicep modules and a subscription-scoped orchestration template with environment parameter files, aligning with the existing GitHub Actions deployment workflow.

Changes:

  • Introduces modules/sovereign/** domain folders containing 7 sovereign landing zone Bicep modules.
  • Adds deployments/sovereign-baseline/main.bicep plus dev/prod parameter files for subscription-scoped orchestration.
  • Documents the intended structure in REPOSITORY_STRUCTURE.md and updates .gitignore to keep the sovereign parameter files tracked.

Reviewed changes

Copilot reviewed 11 out of 12 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
modules/sovereign/policy/sovereign-policy-initiative.bicep Defines a custom policy initiative + assignment for baseline controls.
modules/sovereign/encryption/sovereign-tls-enforcement.bicep Adds subscription-scope policy assignments for TLS enforcement.
modules/sovereign/encryption/sovereign-keyvault-cmk.bicep Deploys a Key Vault configured for CMK scenarios with optional PE + diagnostics.
modules/sovereign/confidential-compute/sovereign-confidential-vm.bicep Deploys an AMD SEV-SNP confidential VM and optional attestation extension.
modules/sovereign/confidential-compute/sovereign-confidential-aks-nodepool.bicep Adds a confidential AKS node pool for an existing cluster.
modules/sovereign/hybrid-arc/sovereign-arc-governance.bicep Assigns Arc governance policies and optionally deploys a Log Analytics workspace.
modules/sovereign/identity/sovereign-rbac-assignments.bicep Creates subscription-scope RBAC role assignments for a SovereignOps group.
deployments/sovereign-baseline/main.bicep Subscription entry point composing all 7 modules and creating 2 RGs.
deployments/sovereign-baseline/dev.parameters.json Dev parameter set (DoNotEnforce, compute disabled).
deployments/sovereign-baseline/prod.parameters.json Prod parameter set (Default enforcement, compute disabled).
REPOSITORY_STRUCTURE.md Annotated directory tree and CI/CD integration mapping.
.gitignore Keeps sovereign baseline *.parameters.json files committed while ignoring others.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -0,0 +1,140 @@
// MODULE: sovereign-policy-initiative
// PURPOSE: Azure Policy initiative enforcing sovereign baseline controls
// (allowed regions, mandatory tags, network controls, CMK enforcement).
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The module header says the initiative includes "CMK enforcement", but the initiative definition in this file only includes allowed locations, mandatory tags, denied resource types, and a Storage TLS policy. If CMK enforcement isn't implemented here, please adjust the comment to reflect what's actually enforced (or add the missing CMK-related policy definitions).

Suggested change
// (allowed regions, mandatory tags, network controls, CMK enforcement).
// (allowed regions, mandatory tags, denied resource types, TLS enforcement).

Copilot uses AI. Check for mistakes.
param tags object = {
environment: environment
managedBy: 'sovereign-landing-zone'
dataClassification: 'Sovereign'
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default tags object uses dataClassification, while the policy module defaults to requiring the DataClassification tag. Even if Azure treats tag keys case-insensitively, this mismatch makes the policy/tag relationship harder to reason about. Consider aligning the tag key with the policy default (or explicitly passing mandatoryTagName from main.bicep).

Suggested change
dataClassification: 'Sovereign'
DataClassification: 'Sovereign'

Copilot uses AI. Check for mistakes.
Comment on lines +184 to +188
module confidentialVm '../../modules/sovereign/confidential-compute/sovereign-confidential-vm.bicep' = if (deployConfidentialVm && workloadSubnetId != '') {
name: 'deploy-confidential-vm'
scope: workloadRg
params: {
vmName: confidentialVmName
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The confidential VM module can be deployed when deployConfidentialVm is true and workloadSubnetId is set, but sshPublicKey can still be the default empty string. In that case the VM deployment will fail because keyData is required. Consider gating the module on sshPublicKey != '' (or making sshPublicKey required when deployConfidentialVm is true) so the template can't enter an invalid deployment state.

Copilot uses AI. Check for mistakes.
Comment on lines +15 to +18
@description('Display name for the sovereign policy initiative')
param initiativeName string = 'sovereign-baseline-initiative'

@description('Description for the initiative')
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter annotations/descriptions appear swapped/misleading: initiativeName is used as the resource name, not the display name, and initiativeDisplayName is used as the display name, not the description. Updating the @description(...) strings (or renaming the params) will prevent confusion for consumers.

Suggested change
@description('Display name for the sovereign policy initiative')
param initiativeName string = 'sovereign-baseline-initiative'
@description('Description for the initiative')
@description('Resource name for the sovereign policy initiative')
param initiativeName string = 'sovereign-baseline-initiative'
@description('Display name for the initiative')

Copilot uses AI. Check for mistakes.
Comment on lines +76 to +80
enableRbacAuthorization: enableRbacAuthorization
enabledForTemplateDeployment: enabledForTemplateDeployment
enabledForDiskEncryption: enabledForDiskEncryption
enabledForDeployment: enabledForDeployment
accessPolicies: []
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enableRbacAuthorization can be set to false, but the template still hard-codes accessPolicies: []. That combination will produce a vault with neither RBAC nor access policies configured, effectively blocking access. Either remove/lock down the parameter, or add an accessPolicies parameter and conditionally populate it when RBAC is disabled.

Copilot uses AI. Check for mistakes.
│ └── workflows/
│ └── deploy-sovereign-lz.yml # Three-stage CI/CD pipeline
│ # validate → what-if → deploy
│ # Uses OIDC federation (no secrets)
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workflow note says "Uses OIDC federation (no secrets)", but the referenced workflow reads AZURE_CLIENT_ID, AZURE_TENANT_ID, and AZURE_SUBSCRIPTION_ID from GitHub secrets. Consider rewording to clarify that OIDC avoids client secrets (rather than avoiding secrets entirely).

Suggested change
│ # Uses OIDC federation (no secrets)
│ # Uses OIDC federation (no client secret)

Copilot uses AI. Check for mistakes.
Comment on lines +50 to +54
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleId)
principalId: sovereignOpsGroupObjectId
principalType: principalType
description: '${assignmentDescription} – ${roleDefinitionNames[index]}'
}
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

roleDefinitionNames[index] assumes roleDefinitionNames and roleDefinitionIds always have identical lengths. If a caller overrides one array but not the other, this can cause an out-of-range access at deployment time and/or incorrect descriptions. Consider modeling roles as a single array of objects (id + name), or removing the name array and deriving descriptions/outputs solely from IDs.

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,66 @@
// MODULE: sovereign-rbac-assignments
// PURPOSE: Scoped RBAC role assignments for a SovereignOps team at
// management group or subscription scope.
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The module header says role assignments are supported at "management group or subscription scope", but the file sets targetScope = 'subscription' (and uses subscriptionResourceId(...)), so it cannot be deployed at management group scope as-is. Please update the header comment (or adjust the implementation) to avoid misleading consumers.

Suggested change
// management group or subscription scope.
// subscription scope.

Copilot uses AI. Check for mistakes.
Comment on lines +90 to +94
// Compliance reporting: Log Analytics workspace for Arc server diagnostics
resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2023-09-01' = if (logAnalyticsWorkspaceId == '') {
name: 'law-arc-governance'
location: location
tags: tags
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Log Analytics workspace is conditionally created but is not referenced by any other resource in the module (no diagnostic settings, no policy assignment parameters pointing to it). As written it can create an unused, billable workspace. Either wire it into the governance/compliance resources that need it, or remove the workspace creation and require logAnalyticsWorkspaceId to be provided by the caller.

Copilot uses AI. Check for mistakes.
Comment on lines +2 to +3
// PURPOSE: Azure Policy assignment and diagnostic settings to enforce TLS
// minimum version across Storage, SQL, and App Service.
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The module purpose comment mentions "diagnostic settings", but this file only creates policy assignments and no Microsoft.Insights/diagnosticSettings resources. Please update the module header to match the actual behavior (or add the diagnostic settings if they are required for the intended design).

Suggested change
// PURPOSE: Azure Policy assignment and diagnostic settings to enforce TLS
// minimum version across Storage, SQL, and App Service.
// PURPOSE: Azure Policy assignments to enforce TLS minimum version across
// Storage, SQL, and App Service.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants