I’m currently trying to deploy a policy initiative definition to Azure using Terraform. Everything works fine except for policies where I use parameter values that are Integer. To pin down the problem I created a small example to test the deployment:
main.tf
resource "azurerm_policy_set_definition" "instance" {
name = "INT TEST"
display_name = "INT TEST"
policy_type = "Custom"
management_group_id = "/providers/microsoft.management/managementgroups/example_management_group"
parameters = jsonencode(var.initiative_params_int)
dynamic "policy_definition_reference" {
for_each = var.initiative_with_int_parameters
iterator = policy_definition
content {
policy_definition_id = policy_definition.key
parameter_values = length(policy_definition.value) == 0 ? null : jsonencode({ for name, value in tomap(policy_definition.value) : name => { "value" = value } })
}
}
}
variables.tf
variable "initiative_with_int_parameters" {
default = {
"/providers/Microsoft.Authorization/policyDefinitions/cee51871-e572-4576-855c-047c820360f0" = {
effect = "[parameters('denyAll')]"
minimumRSAKeySize = 2048
}
"/providers/Microsoft.Authorization/policyDefinitions/82067dbb-e53b-4e06-b631-546d197452d9" = {
effect = "[parameters('denyAll')]"
minimumRSAKeySize = 2048
}
"/providers/Microsoft.Authorization/policyDefinitions/12430be1-6cc8-4527-a9a8-e3d38f250096" = {
effect = "[parameters('denyAll')]"
modeRequirement = "Prevention"
}
}
}
variable "initiative_params_int" {
default = {
denyAll = {
type = "String"
defaultValue = "Deny"
metadata = {
displayName = "Deny All"
description = "Deny all requests"
}
}
}
}
When I try to run "terraform apply" and enter "yes" I get the following error:
Error: creating Policy Set Definition "INT TEST": policy.SetDefinitionsClient#CreateOrUpdateAtManagementGroup: Failure responding to request: StatusCode=400 -- Original Error: autorest/azure: Service returned an error. Status=400 Code="InvalidPolicyParameterType" Message="The policy parameter 'minimumRSAKeySize' does not match the expected parameter type defined in the policy definition 'cee51871-e572-4576-855c-047c820360f0'. Details 'The expected policy parameter type: 'Integer'. The actual policy parameter type 'String'.'."
│
│ with azurerm_policy_set_definition.instance,
│ on main.tf line 137, in resource "azurerm_policy_set_definition" "instance":
│ 137: resource "azurerm_policy_set_definition" "instance" {
When I leave out the above two policies and only use the third one everything works and the deployment is successful.
I thought that an explicit typecast might help minimumRSAKeySize = tonumber(2048)
but apparently I can’t do a typecast to number on an Integer value. I also tried to input the values for "minimumRSAKeySize" as String but then I get the same error mentioned above.
2
Answers
I found a solution to the problem. During the assignment of the attribute "parameter_values" inside the policy_definition_reference block the values of the parameters are converted to string:
I adjusted the file variables.tf as follows:
Then the assignment of the policy parameters can be done like this:
This preserves the parameter types and doesn't throw any errors when deploying the initiative using terraform apply.
I suspect the problem here is that you haven’t defined a type constraint for your input variable and so Terraform is attempting to guess what type constraint you intended, but is guessing incorrectly and concluding that you intended to declare
type = map(map(string))
, which therefore forces convertingminimumRSAKeySize
to a string.If that is the problem then you should be able to fix it by declaring an explicit type constraint on each of your input variables so that Terraform does not need to guess. For example:
In general, all Terraform variables ought to have a type constraint. Terraform does not require it for backward compatibility with very old versions of Terraform that had a much more limited type system, but telling Terraform exactly the type you intend means that your configuration will be more readable, Terraform won’t need to guess what type constraint you meant, and Terraform will be able to give you better feedback if you use an incorrect value to define this variable.