Ticket ID: CP-PB-009
Build Terraform and Pulumi serializers
Background
PolicyBuilder generates ARM JSON by default. For teams using Terraform or Pulumi we need serializers that convert the same policy objects to native HCL or Python IaC. This avoids duplication: the policy logic lives in PolicyBuilder and the serializer produces the target format.
Files
src/itl_policybuilder/serializers/terraform.py
src/itl_policybuilder/serializers/pulumi.py
Terraform serializer
"""
Serialize ARM policy objects to Terraform HCL.
"""
import json
def policy_to_terraform(policy: dict) -> str:
"""Convert ARM policyDefinition to azurerm_policy_definition HCL."""
props = policy["properties"]
name = policy["name"]
rule_json = json.dumps(props["policyRule"], indent=2)
return f'''resource "azurerm_policy_definition" "{name}" {{
name = "{name}"
policy_type = "Custom"
mode = "All"
display_name = "{props["displayName"]}"
description = "{props.get("description", "")}"
policy_rule = <<POLICY_RULE
{rule_json}
POLICY_RULE
}}
'''
def initiative_to_terraform(initiative: dict) -> str:
"""Convert ARM policySetDefinition to azurerm_policy_set_definition HCL."""
props = initiative["properties"]
name = initiative["name"]
refs = props.get("policyDefinitions", [])
policy_ref_blocks = ""
for ref in refs:
policy_def_id = ref["policyDefinitionId"]
policy_ref_blocks += f'''
policy_definition_reference {{
policy_definition_id = "{policy_def_id}"
}}'''
return f'''resource "azurerm_policy_set_definition" "{name}" {{
name = "{name}"
policy_type = "Custom"
display_name = "{props["displayName"]}"
description = "{props.get("description", "")}"
{policy_ref_blocks}
}}
'''
def assignment_to_terraform(assignment: dict, scope_var: str = "var.subscription_id") -> str:
"""Convert ARM policyAssignment to azurerm_subscription_policy_assignment HCL."""
props = assignment["properties"]
name = assignment["name"]
return f'''resource "azurerm_subscription_policy_assignment" "{name}" {{
name = "{name}"
display_name = "{props["displayName"]}"
subscription_id = "/subscriptions/${{{scope_var}}}"
policy_definition_id = azurerm_policy_set_definition.{props.get("policyDefinitionId", name)}.id
enforce = true
}}
'''
Pulumi serializer
"""
Serialize ARM policy objects to Pulumi Python code.
"""
import json
def policy_to_pulumi(policy: dict) -> str:
"""Convert ARM policyDefinition to azure_native.authorization.PolicyDefinition."""
props = policy["properties"]
name = policy["name"]
rule = json.dumps(props["policyRule"])
return f'''import pulumi_azure_native as azure_native
{name.replace("-", "_")} = azure_native.authorization.PolicyDefinition(
resource_name="{name}",
policy_definition_name="{name}",
policy_type="Custom",
mode="All",
display_name="{props["displayName"]}",
policy_rule={rule},
)
'''
def initiative_to_pulumi(initiative: dict) -> str:
"""Convert ARM policySetDefinition to azure_native.authorization.PolicySetDefinition."""
props = initiative["properties"]
name = initiative["name"]
refs = props.get("policyDefinitions", [])
refs_python = json.dumps(refs, indent=4)
return f'''import pulumi_azure_native as azure_native
{name.replace("-", "_")} = azure_native.authorization.PolicySetDefinition(
resource_name="{name}",
policy_set_definition_name="{name}",
policy_type="Custom",
display_name="{props["displayName"]}",
policy_definitions={refs_python},
)
'''
CLI
# Generate Terraform for Defender initiative
python -m itl_policybuilder serialize \
--format terraform \
--initiative defender \
--output output/terraform/
# Generate Pulumi for Foundation initiative
python -m itl_policybuilder serialize \
--format pulumi \
--initiative foundation \
--output output/pulumi/
Output structure
output/terraform/
|-- enable-defender-virtualmachines.tf
|-- enable-defender-sqlservers.tf
|-- ...
`-- initiative-all-plans.tf
output/pulumi/
|-- enable-defender-virtualmachines.py
|-- ...
`-- initiative-all-plans.py
Acceptance Criteria
Related
Ticket ID:
CP-PB-009Build Terraform and Pulumi serializers
Background
PolicyBuilder generates ARM JSON by default. For teams using Terraform or Pulumi we need serializers that convert the same policy objects to native HCL or Python IaC. This avoids duplication: the policy logic lives in PolicyBuilder and the serializer produces the target format.
Files
src/itl_policybuilder/serializers/terraform.pysrc/itl_policybuilder/serializers/pulumi.pyTerraform serializer
Pulumi serializer
CLI
Output structure
Acceptance Criteria
policy_to_terraform()generates valid HCL with heredoc for policy ruleinitiative_to_terraform()generatespolicy_definition_referenceblocksassignment_to_terraform()references policy set definition by resource IDpolicy_to_pulumi()generates valid Python withazure_native.authorizationinitiative_to_pulumi()generates valid Pythonserializecommand accepts--format terraform|pulumiRelated