feat: Add proper validation for non-compliance messages in policy assignments#243
feat: Add proper validation for non-compliance messages in policy assignments#243
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #243 +/- ##
==========================================
+ Coverage 47.57% 47.79% +0.21%
==========================================
Files 54 54
Lines 4847 4865 +18
==========================================
+ Hits 2306 2325 +19
Misses 2254 2254
+ Partials 287 286 -1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Co-authored-by: Matt White <16320656+matt-FFFFFF@users.noreply.github.com>
|
Thanks @ASHR4 just getting a review form copilot then will merge |
There was a problem hiding this comment.
Pull request overview
This PR adds validation to assets.PolicyAssignment to ensure there is at most one default non-compliance message (i.e., a non-compliance message without a PolicyDefinitionReferenceID), aligning policy assignment validation with Azure constraints.
Changes:
- Add validation in
ValidatePolicyAssignmentto detect multiple default non-compliance messages. - Add unit tests covering single vs. multiple default non-compliance messages (including empty reference IDs).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
assets/policyAssignment.go |
Introduces validation logic counting “default” non-compliance messages and errors when more than one is present. |
assets/policyAssignment_test.go |
Adds table-driven test cases verifying the new validation behavior. |
|
@ASHR4 some decent comments here, worth a look |
…n-compliance messages
|
@matt-FFFFFF I've implemented the copilot recommendations 😄 |
|
how do you handle this ? @matt-FFFFFF @ASHR4 ~ module.lz_vending.module.lz_vending["xx"].data.azapi_resource_list.subscription_management_group_association[0] will be read during apply
# (depends on a resource or a module with changes pending)
~ module.lz_vending.module.lz_vending["xx"].data.azapi_resource_list.subscriptions[0] will be read during apply
# (depends on a resource or a module with changes pending)
+ module.lz_vending.module.lz_vending["xx"].azapi_resource_action.subscription_association[0] will be created
! module.lz_vending.module.lz_vending["xx"].terraform_data.replacement[0] will be updated in-place
+ module.management_groups.module.management_groups.azapi_resource.policy_assignments["xx-landingzones/Deny-AKS-AllowedImages"] will be created# module.management_groups.module.management_groups.azapi_resource.policy_assignments["xx-landingzones/Deny-AKS-AllowedImages"] will be created
+ resource "azapi_resource" "policy_assignments" {
+ body = {
+ properties = {
+ definitionVersion = "9.*.*"
+ description = "Deny AKS clusters from using container images not from allowed registries."
+ displayName = "xx - AKS allowed container registries"
+ enforcementMode = "DoNotEnforce"
+ metadata = {
+ createdBy = ""
+ createdOn = ""
+ updatedBy = ""
+ updatedOn = ""
}
+ nonComplianceMessages = [
+ {
+ message = "This resource should be compliant with the assigned policy."
},
]
+ notScopes = []
+ overrides = []
+ parameters = {
+ allowedContainerImagesRegex = {
+ value = "^(acrdevxxszn\\.azurecr\\.io|acrxx\\.azurecr\\.io|mcr\\.microsoft\\.com|ghcr\\.io|quay\\.io|ecr-public\\.aws\\.com|registry-1\\.docker\\.io|docker\\.io|temporalio|apache|changemakerstudiosus|weblate|dpage|bitnamilegacy)/.+$"
}
+ effect = {
+ value = "deny"
}
+ excludedNamespaces = {
+ value = [
+ "kube-system",
+ "gatekeeper-system",
+ "azure-arc",
+ "azure-extensions-usage-system",
]
}
}
+ policyDefinitionId = "/providers/Microsoft.Authorization/policyDefinitions/febd0533-8e55-448f-b837-bd0e06f16469"
+ resourceSelectors = []
}
}
+ id = (known after apply)
+ ignore_casing = false
+ ignore_missing_property = true
+ ignore_null_property = false
+ location = "switzerlandnorth"
+ name = "Deny-AKS-AllowedImages"
+ output = (known after apply)
+ parent_id = "/providers/Microsoft.Management/managementGroups/xx-landingzones"
+ replace_triggers_external_values = [
+ "/providers/Microsoft.Authorization/policyDefinitions/febd0533-8e55-448f-b837-bd0e06f16469",
+ "switzerlandnorth",
]
+ response_export_values = []
+ retry = {
+ error_message_regex = [
+ "AuthorizationFailed",
+ "The policy definition specified in policy assignment '.+' is out of scope",
]
+ interval_seconds = 5
+ max_interval_seconds = 30
+ multiplier = 1.5
+ randomization_factor = 0.5
}
+ schema_validation_enabled = true
+ sensitive_body = (write-only attribute)
+ type = "Microsoft.Authorization/policyAssignments@2024-04-01"
+ identity {
+ identity_ids = []
+ principal_id = (known after apply)
+ tenant_id = (known after apply)
+ type = "None"
}
+ timeouts {
+ create = "60m"
+ delete = "5m"
+ read = "60m"
+ update = "5m"
}
}Apply error: module.management_groups.module.management_groups.azapi_resource.policy_assignments["xx-landingzones/Deny-AKS-AllowedImages"]: Creating...
Error: Failed to create/update resource
with module.management_groups.module.management_groups.azapi_resource.policy_assignments["xx-landingzones/Deny-AKS-AllowedImages"],
on .terraform/modules/management_groups.management_groups/main.policy_assignments.tf line 5, in resource "azapi_resource" "policy_assignments":
5: resource "azapi_resource" "policy_assignments" {
creating/updating Resource: (ResourceId
"/providers/Microsoft.Management/managementGroups/xx-landingzones/providers/Microsoft.Authorization/policyAssignments/Deny-AKS-AllowedImages"
/ Api Version "2024-04-01"): PUT
https://management.azure.com/providers/Microsoft.Management/managementGroups/xx-landingzones/providers/Microsoft.Authorization/policyAssignments/Deny-AKS-AllowedImages
--------------------------------------------------------------------------------
RESPONSE 400: 400 Bad Request
ERROR CODE: InvalidCreatePolicyAssignmentRequest
--------------------------------------------------------------------------------
{
"error": {
"code": "InvalidCreatePolicyAssignmentRequest",
"message": "The policy assignment request is invalid. A non-compliance message is being created for a policy definition with mode 'Microsoft.Kubernetes.Data'. Non-compliance messages are not supported for this mode."
}
} |
|
Hi @thisispr, the validation that was added as part of this PR, validates if multiple default non-compliance messages are provided to a single assignment which is not allowed. Your error looks related to the fact you're assigning a policy that has a resource provider mode,
https://learn.microsoft.com/en-us/azure/governance/policy/concepts/assignment-structure#metadata This can be handled via this variable in the avm-ptn-alz module, where you can exclude unsupported assignments. For example: policy_assignment_non_compliance_message_settings = {
fallback_message_unsupported_assignments = [
"Deny-Privileged-AKS",
"Enforce-AKS-HTTPS",
"Deny-Priv-Esc-AKS",
"Deny-AKS-AllowedImages" +++
]
} |

Adding validation logic to ensure that a policy assignment contains at most one default non-compliance message (a message without a
PolicyDefinitionReferenceID).Supports #201