Governance Constraints - pci-dss-gw
Generated by bicep-plan agent | 2026-02-11 | Full REST API discovery
[!NOTE] 📚 See SKILL.md for visual standards.
This document captures the governance constraints and Azure Policy requirements that must be addressed in the Bicep implementation for the PCI-DSS Level 1 payment gateway.
Discovery Source
[!IMPORTANT] Governance constraints discovered via REST API including management group-inherited policies. Previous
az policy assignment listdiscovery missed 16 of 21 policies.
| Query | Result | Timestamp |
|---|---|---|
| REST API Total | 21 assignments | 2026-02-11T12:00:00Z |
| Subscription-scope | 5 direct assignments | 2026-02-11T12:00:00Z |
| RG-scoped | 7 resource group assignments | 2026-02-11T12:00:00Z |
| MG-inherited | 9 inherited policies | 2026-02-11T12:00:00Z |
| Deny-effect | 3 blockers found | 2026-02-11T12:00:00Z |
| Tag Policies | 9 tags required (Deny) | 2026-02-11T12:00:00Z |
Discovery Method: REST API
(GET /subscriptions/{id}/providers/Microsoft.Authorization/policyAssignments?api-version=2022-06-01)
Subscription: noalz (00858ffc-dded-4f0f-8bbf-e17fff0d47d9)
Tenant: 2d04cb4c-999b-4e60-a3a7-e8993edc768b
Scope: All effective (subscription + resource group + management group inherited)
[!CAUTION] Previous discovery using
az policy assignment listonly returned 5 subscription-scoped policies. REST API revealed 16 additional policies including critical Deny blockers.
Azure Policy Compliance
| Category | Constraint | Source | Implementation |
|---|---|---|---|
| Tags (Deny) | 9 lowercase tags required on RGs | JV-Enforce RG Tags v3 | All Bicep RG deployments include all 9 |
| Tags (Modify) | 9 tags auto-inherited to children | JV-Inherit Tags | No Bicep action — policy handles it |
| VM SKUs (Deny) | H, M, N series blocked | MCAPSGov Deny | Using D-series — compliant |
| AKS Pools (Deny) | Max 10 agent pool profiles | MCAPSGov Deny | Using 2 pools — compliant |
| Classic (Deny) | All Classic resource types blocked | MCAPSGov Deny + Block ARM | Using ARM — compliant |
| SQL Auth (Deny) | Azure SQL requires AAD-only | MCAPSGov Deny | Using PostgreSQL — N/A |
| HSM Purge (Deny) | Purge protection required | MCAPSGov Deny | Enable purge protection in Bicep |
| Compliance (Audit) | PCI DSS v4 (269 controls) | Subscription policy | Architecture designed for PCI-DSS L1 |
| Compliance (Audit) | GDPR (285 controls) | Subscription policy | EU regions: swedencentral/germanywestcentral |
| Security (Audit) | Azure Security Baseline (224) | MG policy | Cloud security benchmark posture |
| Security (Audit) | MCAPSGov Audit (44) | MG policy | Tenant baseline compliance |
| MFA (Audit) | MFA for write/delete operations | MG policy (×2) | Deploying user must have MFA enabled |
| Naming | No naming policy discovered | — | Follow CAF conventions from azure-defaults |
| Location | No location restriction found | — | EU regions: swedencentral/germanywestcentral |
Complete Policy Inventory
Management Group-Inherited Policies (9)
| # | Display Name | Type | Effect | Sub-Policies | Impact |
|---|---|---|---|---|---|
| 1 | JV-Enforce Resource Group Tags v3 | Policy | Deny | 1 | 🚫 BLOCKER — 9 lowercase tags required |
| 2 | MCAPSGov Deny Policies | Initiative | Deny | 11 | ⚠️ VM SKU + AKS pool + HSM constraints |
| 3 | Block Azure RM Resource Creation | Policy | Deny | 1 | ✅ Classic resources only — no impact |
| 4 | MCAPSGov Deploy and Modify Policies | Initiative | DeployIfNotExists/Modify | 27 | Auto-deploys security agents |
| 5 | MCAPSGov Audit Policies | Initiative | Audit | 44 | Compliance reporting only |
| 6 | Azure Security Baseline | Initiative | Audit | 224 | Microsoft cloud security benchmark |
| 7 | JV - Inherit Multiple Tags from Resource Group | Policy | Modify | 1 | Auto-inherits 9 tags from RG to children |
| 8 | MFA Enforcement for Resource Write Actions | Policy | Audit | 1 | MFA required for write operations |
| 9 | MFA Enforcement for Resource Delete Actions | Policy | Audit | 1 | MFA required for delete operations |
Subscription-Scoped Policies (5)
| # | Display Name | Type | Effect | Impact |
|---|---|---|---|---|
| 10 | PCI DSS v4 | Initiative (269 controls) | Audit | Architecture must align with PCI DSS |
| 11 | EU GDPR 2016/679 | Initiative (285 controls) | Audit | EU data residency validation |
| 12 | ASC DataProtection | Initiative | DeployIfNotExists | Auto-deploys data protection monitoring |
| 13 | ASC OpenSourceRelationalDatabasesProtection | Initiative | DeployIfNotExists | Auto-deploys Defender for PostgreSQL |
| 14 | Defender for SQL Servers on Machines | Initiative | DeployIfNotExists | SQL Defender (not applicable — PaaS only) |
Resource Group-Scoped Policies (7)
All scoped to rg-arcbox-swc01 — a different resource group. No impact on this project.
| # | Display Name | Scope |
|---|---|---|
| 15 | (ArcBox) Enable SSH Posture Control audit | rg-arcbox-swc01 |
| 16 | (ArcBox) Enable Azure Update Manager for Arc-enabled Windows machines | rg-arcbox-swc01 |
| 17 | (ArcBox) Tag resources (unnamed) | rg-arcbox-swc01 |
| 18 | (ArcBox) Azure Monitor (unnamed) | rg-arcbox-swc01 |
| 19 | (ArcBox) Enable Azure Update Manager for Arc-enabled Linux machines | rg-arcbox-swc01 |
| 20 | (ArcBox) Enable Azure Update Manager for Azure Windows machines | rg-arcbox-swc01 |
| 21 | (ArcBox) Enable Azure Update Manager for Azure Linux machines | rg-arcbox-swc01 |
Plan Adaptations Based on Policies
Tag Schema (Updated — CRITICAL)
// Resource Group tags — ALL 9 REQUIRED by JV-Enforce Resource Group Tags v3 (Deny)
// Case-sensitive: ALL lowercase
@description('Deployment environment')
@allowed(['dev', 'staging', 'prod'])
param environment string
@description('Team or individual owner')
param owner string
@description('Cost center code')
param costCenter string
@description('Technical contact email')
param technicalContact string
var requiredRgTags = {
environment: environment
owner: owner
costcenter: costCenter
application: 'pci-dss-gw'
workload: 'payment-gateway'
sla: '99.99'
'backup-policy': 'daily'
'maint-window': 'Sun:02:00-06:00'
'technical-contact': technicalContact
}
// Additional project-standard tags (not policy-enforced but recommended)
var allTags = union(requiredRgTags, {
ManagedBy: 'Bicep'
Project: 'pci-dss-gw'
})
[!IMPORTANT] Resource groups require ALL 9 tags from
JV-Enforce Resource Group Tags v3. Child resources auto-inherit these 9 tags viaJV - Inherit Multiple Tags from Resource Group(Modify effect). Additional tags (ManagedBy, Project) can be appended but are NOT required.
Architectural Constraints
| Original Design | Blocking Policy | Effect | Required Adaptation |
|---|---|---|---|
| 4 PascalCase tags | JV-Enforce RG Tags v3 | Deny | 9 lowercase tags on all resource groups |
| Key Vault Premium HSM | MCAPSGov Deny (HSM purge) | Deny | enablePurgeProtection: true required |
| AKS 2 node pools | MCAPSGov Deny (AKS pool limit) | Deny | ✅ Compliant (2 < 10 limit) — document constraint |
| D8s_v5 / D4s_v5 VMs | MCAPSGov Deny (VM SKU) | Deny | ✅ Compliant — D-series not blocked |
Auto-Applied Configurations
| Policy | Effect | What Gets Auto-Applied |
|---|---|---|
| JV - Inherit Multiple Tags from Resource Group | Modify | 9 RG tags auto-copied to all child resources |
| MCAPSGov Deploy and Modify Policies (27 sub-policies) | DeployIfNotExists/Modify | Security agents, diagnostic settings |
| ASC DataProtection | DeployIfNotExists | Data protection monitoring agents |
| ASC OpenSourceRelationalDatabasesProtection | DeployIfNotExists | Defender for PostgreSQL monitoring |
| Defender for SQL on Machines | DeployIfNotExists | SQL Defender agents (N/A — PaaS) |
Deployment Blockers
[!CAUTION] CRITICAL: Policies that BLOCK deployment. Resolution is REQUIRED before proceeding.
Blocker 1: JV-Enforce Resource Group Tags v3 (DENY)
Assignment: b1ad1a690a5148ec8707ff17
Scope: Management Group (Tenant Root 2d04cb4c-999b-4e60-a3a7-e8993edc768b)
Enforcement Mode: Default (enabled)
Effect: Deny
Policy Definition: 27833bcf-5909-4a37-891c-16a3cb06856d
Policy Rule:
- Applies to:
Microsoft.Resources/subscriptions/resourceGroups - Excludes RG names matching:
AzureBackupRG*,ResourceMover*,databricks-rg*,NetworkWatcherRG,microsoft-network,LogAnalyticsDefaultResources,rg-amba-*,DynamicsDeployments*,MC_myResourceGroup* - Denies creation if ANY of 9 tags are missing (case-sensitive, all lowercase)
| # | Tag Name | Required | Case |
|---|---|---|---|
| 1 | environment |
Yes | lowercase |
| 2 | owner |
Yes | lowercase |
| 3 | costcenter |
Yes | lowercase |
| 4 | application |
Yes | lowercase |
| 5 | workload |
Yes | lowercase |
| 6 | sla |
Yes | lowercase |
| 7 | backup-policy |
Yes | lowercase |
| 8 | maint-window |
Yes | lowercase |
| 9 | technical-contact |
Yes | lowercase |
[!WARNING] Our original plan only had 4 tags (Environment, ManagedBy, Project, Owner) with PascalCase. This policy requires 9 tags with lowercase names. Resource group creation will be DENIED without all 9 tags present.
Resolution: Update all Bicep resource group deployments to include all 9 required tags
with correct lowercase casing. The ManagedBy and Project tags from our defaults are
supplementary but NOT required by policy.
Blocker 2: MCAPSGov Deny Policies (11 sub-policies)
Assignment: MCAPSGovDenyPolicies
Scope: Management Group (Tenant Root 2d04cb4c-999b-4e60-a3a7-e8993edc768b)
Enforcement Mode: Default (enabled)
Effect: Deny (initiative with 11 policies)
| # | Reference ID | Policy Definition | Effect | Impact on This Project |
|---|---|---|---|---|
| 1 | BlockVMSKUs_H | VirtualMachine_SKU_Deny | Deny | ✅ Safe — we use D-series, not H-series (17 blocked SKUs) |
| 2 | BlockVMSKUs_M | VirtualMachine_SKU_Deny | Deny | ✅ Safe — we use D-series, not M-series (44 blocked SKUs) |
| 3 | BlockVMSKUs_N | VirtualMachine_SKU_Deny | Deny | ✅ Safe — we use D-series, not N-series (64 blocked SKUs) |
| 4 | AKS_LimitNodeCount | AKS_LimitNodeCount_Deny | Deny | ✅ Safe — our plan uses 2 pools (system + CDE), limit is 10 |
| 5 | VMSS_LimitNodesCount | VMSS_LimitNodesCount_Deny | Deny | ⚠️ Verify — AKS uses VMSS internally, check node count limit |
| 6 | OpenAI_BlockProvisionedCapacity | AzureOpenAI_ProvisionedCapacity_Deny | Deny | ✅ N/A — not in our architecture |
| 7 | Sentinel_Commitment_Deny | Sentinel_Commitment_Deny | Deny | ✅ N/A — not in our architecture |
| 8 | AzureSQL_WithoutAzureADOnlyAuthentication_Deny | AzureSQL_WithoutAzureADOnlyAuthentication_Deny | Deny | ✅ N/A — we use PostgreSQL, not Azure SQL |
| 9 | AzureSQLMI_WithoutAzureADOnlyAuthentication_Deny | AzureSQLMI_WithoutAzureADOnlyAuthentication_Deny | Deny | ✅ N/A — not in our architecture |
| 10 | NotAllowedResourceTypes | 6c112d4e-5bc7-47ae-a041-ea2d9dccd749 | Deny | ✅ Safe — blocks 57 Classic (ASM) resource types only |
| 11 | KeyVaultManagedHSM_PurgeProtectionEnabled | KeyVaultManagedHSM_PurgeProtectionEnabled_Deny | Deny | ⚠️ Ensure — Key Vault HSM must have purge protection enabled |
Resolutions:
- AKS agent pool limit: Architecture uses 2 pools — compliant. Document constraint.
- VMSS node count: Verify the exact limit parameter and ensure AKS autoscaler max does not exceed it.
- Key Vault HSM purge protection: Set
enablePurgeProtection: trueon Key Vault. - VM SKUs: Only D-series VMs used — compliant. Document blocked families.
Non-Blocker: Block Azure RM Resource Creation (DENY)
Scope: Management Group (Tenant Root)
Assessment: This policy ONLY blocks Classic (ASM) resource types:
Microsoft.ClassicCompute/*, Microsoft.ClassicStorage/*, Microsoft.ClassicNetwork/*.
Impact: None — our Bicep templates use ARM resources exclusively.
Required Tags
Resource Group Tags (MANDATORY — Deny enforced)
// These 9 tags are REQUIRED by JV-Enforce Resource Group Tags v3 (Deny)
// ALL lowercase, case-sensitive — deployment will FAIL without them
var requiredRgTags = {
environment: environment // 'dev' | 'staging' | 'prod'
owner: owner // Team or individual
costcenter: costCenter // Cost center code
application: 'pci-dss-gw' // Application name
workload: 'payment-gateway' // Workload type
sla: '99.99' // SLA target
'backup-policy': 'daily' // Backup policy
'maint-window': 'Sun:02:00-06:00' // Maintenance window
'technical-contact': techContact // Technical contact email
}
Resource Tags (Project standard + auto-inherited)
// Child resources auto-inherit 9 RG tags via JV-Inherit policy (Modify)
// These additional tags are project convention, not policy-enforced
var additionalTags = {
ManagedBy: 'Bicep'
Project: 'pci-dss-gw'
}
var allTags = union(requiredRgTags, additionalTags)
Security Policies
| Area | Requirement | Source |
|---|---|---|
| HTTPS Only | TLS 1.2+ on all services | PCI Req 4 (proactive) |
| Public Access | Disabled via private endpoints | PCI Req 1 (proactive) |
| Managed Identity | All service-to-service auth | PCI Req 8 (proactive) |
| Key Vault HSM | Purge protection required | MCAPSGov Deny + PCI Req 3 |
| AAD-Only Auth | Required for all databases | MCAPSGov Deny (SQL) + PCI Req 8 |
| Network Segmentation | Hub-spoke with Firewall IDPS | PCI Req 1 (proactive) |
| Container Security | Defender auto-enabled | MCAPSGov Deploy (auto) |
| Logging | 1-year retention, tamper-proof | PCI Req 10 (proactive) |
| Defender for PostgreSQL | Auto-enabled | ASC policy (auto) |
| Defender for Cloud | Enhanced posture | PCI Req 11 (proactive) |
| MFA Enforcement | Write/delete operations | MG policy (Audit) |
| Security Baseline | 224 controls | MG policy (Audit) |
Cost Policies
| Constraint | Source | Impact |
|---|---|---|
| H/M/N VM SKUs blocked | MCAPSGov Deny (3 policies) | Prevents expensive HPC/GPU VMs |
| OpenAI provisioned capacity blocked | MCAPSGov Deny | Prevents AI spend |
| Sentinel commitment tier blocked | MCAPSGov Deny | Prevents commitment over-provisioning |
| No budget policy found | — | Recommend Azure Cost Management alert at $20,000/mo |
| No reservations policy | — | Recommend 1-year RI for AKS + PostgreSQL (~35% savings) |
Network Policies
| Policy | Constraint | Impact |
|---|---|---|
| No location restriction | No Deny policy on allowed locations | Using EU regions: swedencentral/germanywestcentral |
| No naming policy | No Deny policy on naming conventions | Following CAF conventions from azure-defaults skill |
| NSG flow logs | MCAPSGov Deploy auto-enables | Auto-applied via DeployIfNotExists |
[!NOTE] No network-specific Deny policies found. Architecture follows PCI-DSS network segmentation requirements proactively (hub-spoke, private endpoints, Azure Firewall IDPS).
References
| Topic | Link |
|---|---|
| Azure Policy effects | Policy effects |
| Tag enforcement patterns | Tag policies |
| PCI-DSS on Azure | PCI compliance |
| Azure Policy exemptions | Exemption structure |
| Tag inheritance | Inherit a tag from RG |
| MCAPSGov policies | Tenant Root management group (internal) |
| REST API discovery | Policy assignments API |
Governance constraints discovered via REST API on subscription noalz (00858ffc-dded-4f0f-8bbf-e17fff0d47d9).
All 21 assignments verified including 9 management group-inherited policies.
See governance-discovery.instructions.md for discovery methodology.