MultiWriter Policy via Terraform
The MultiWriter Policy (MWP) feature introduces hierarchical policy structure and attachment points for distributed policy management via Terraform. MWP enables large enterprises to scale policy governance across multiple teams while maintaining a unified enforcement model.
-
Hierarchical Structure: Build policy trees using Groups and Rulesets. Groups can contain other groups and rulesets for modular design
-
Attachment Points: Named points allow independent management of different policy segments. Multiple teams can attach policies without dependency on creation order
-
Terraform Support: Full Terraform support for creating hierarchical policies. UI displays rulesets as a flat list for visibility.
-
API: GET /v2.5/policy-list3 for managing hierarchical structures
Benefits
-
Enterprise Manageability: Break down large rulesets into logical groups
-
Multi-Team Collaboration: Different Terraform instances manage separate policy segments
-
Scalable Policy Management: Modular design reduces operational risk
-
Future-Ready: Enables RBAC, scopes, and versioning
Prerequisites
Define attachment point data sources to place policy objects:
data "aviatrix_dcf_attachment_point" "tf_before" {
name = "TERRAFORM_BEFORE_UI_MANAGED"
}
data "aviatrix_dcf_attachment_point" "tf_after" {
name = "TERRAFORM_AFTER_UI_MANAGED"
}
-
TERRAFORM_BEFORE_UI_MANAGED— Rulesets created before UI-managed rulesets -
TERRAFORM_AFTER_UI_MANAGED— Rulesets created after UI-managed rulesets
Configuration Scenarios
Scenario 1: Create and Attach an Empty Ruleset
resource "aviatrix_dcf_ruleset" "empty_before_ruleset" {
attach_to = data.aviatrix_dcf_attachment_point.tf_before.id
name = "example-before-ruleset"
}
resource "aviatrix_dcf_ruleset" "empty_after_ruleset" {
attach_to = data.aviatrix_dcf_attachment_point.tf_after.id
name = "example-after-ruleset"
}
Scenario 2: Create a Ruleset with Rules and Define Placement
resource "aviatrix_dcf_ruleset" "before_ruleset" {
attach_to = data.aviatrix_dcf_attachment_point.tf_before.id
name = "ruleset-before-with-rules"
rules {
name = "Policy 1-1"
action = "DENY"
dst_smart_groups = [aviatrix_smart_group.sp1_vm_smart_group.id]
src_smart_groups = [aviatrix_smart_group.sp2_vm_smart_group.id]
protocol = "tcp"
}
rules {
name = "Policy 1-2"
action = "PERMIT"
dst_smart_groups = [aviatrix_smart_group.sp1_vm_smart_group.id]
src_smart_groups = [aviatrix_smart_group.sp2_vm_smart_group.id]
protocol = "udp"
}
}
resource "aviatrix_dcf_ruleset" "after_ruleset" {
attach_to = data.aviatrix_dcf_attachment_point.tf_after.id
name = "ruleset-after-with-rules"
rules {
name = "Policy 2-1"
action = "PERMIT"
dst_smart_groups = [aviatrix_smart_group.sp1_vm_smart_group.id]
src_smart_groups = [aviatrix_smart_group.sp2_vm_smart_group.id]
protocol = "tcp"
}
rules {
name = "Policy 2-2"
action = "DENY"
dst_smart_groups = [aviatrix_smart_group.sp1_vm_smart_group.id]
src_smart_groups = [aviatrix_smart_group.sp2_vm_smart_group.id]
protocol = "udp"
}
}
Scenario 3: Create an Empty Policy Group
|
Creating an empty policy group is not supported. |
# NOT SUPPORTED
resource "aviatrix_dcf_policy_group" "base_policy_group" {
attach_to = data.aviatrix_dcf_attachment_point.tf_before.id
name = "example-policy-group"
}
Scenario 4: Create a Ruleset and Add to a Policy Group Using Ruleset Reference
resource "aviatrix_dcf_ruleset" "child_ruleset" {
name = "child_ruleset"
rules {
name = "Policy 4-1"
action = "PERMIT"
dst_smart_groups = [aviatrix_smart_group.sp1_vm_smart_group.id]
src_smart_groups = [aviatrix_smart_group.sp2_vm_smart_group.id]
protocol = "ANY"
}
}
resource "aviatrix_dcf_policy_group" "parent_policy_group" {
attach_to = data.aviatrix_dcf_attachment_point.tf_before.id
name = "example-policy-group"
policy_group_reference {
priority = 100
target_uuid = aviatrix_dcf_policy_group.child_policy_group.id
}
ruleset_reference {
priority = 200
target_uuid = aviatrix_dcf_ruleset.child_ruleset.id
}
# This will create a new attachment point if it doesn't exist
attachment_point {
name = "test"
priority = 300
}
}
Scenario 5: Attach Ruleset to Policy Group Using Attachment Point
Attach a ruleset from one team to another team’s policy group using attachment points.
data "aviatrix_dcf_attachment_point" "tf_policy_attachment" {
name = "attach-to-policy"
}
resource "aviatrix_dcf_ruleset" "after_ruleset_policy" {
attach_to = data.aviatrix_dcf_attachment_point.tf_policy_attachment.id
name = "ruleset-with-attachment-point"
rules {
name = "Policy 5-1"
action = "PERMIT"
dst_smart_groups = [aviatrix_smart_group.sp1_vm_smart_group.id]
src_smart_groups = [aviatrix_smart_group.sp2_vm_smart_group.id]
protocol = "ANY"
}
}
resource "aviatrix_dcf_policy_group" "parent_policy_group_to_rule" {
attach_to = data.aviatrix_dcf_attachment_point.tf_before.id
name = "example-policy-group-with-policy"
policy_group_reference {
priority = 400
target_uuid = aviatrix_dcf_policy_group.parent_policy_group.id
}
# This creates the attachment point that the ruleset will connect to
attachment_point {
name = "attach-to-policy"
priority = 300
}
}
|
The |
Verify Configuration Using API
Use the policy-list3 API to verify the hierarchical policy structure:
curl --location 'https://<controller>/v2.5/api/microseg/policy-list3' \
--header 'Accept: application/json' \
--header 'Authorization: cid <CID>'
The response shows how rulesets and policy groups are connected through attachment points:
{
"dcf_policies": [
{
"attach_to": "44c020ff-b652-4bf5-ac44-0edc7e01d0d0",
"name": "ruleset-with-attachement-point",
"policies": [
{
"action": "PERMIT",
"decrypt_policy": "DECRYPT_UNSPECIFIED",
"desc": "",
"dst_ads": ["b8a93df6-d953-45ad-b02a-d188a80cf62c"],
"exclude_sg_orchestration": false,
"flow_app_requirement": "APP_UNSPECIFIED",
"intrusion_severity": "INTRUSION_SEVERITY_NONE",
"log_profile": "",
"logging": false,
"name": "Policy 5-1",
"port_ranges": [],
"priority": 0,
"protocol": "PROTOCOL_UNSPECIFIED",
"ruleset": 0,
"ruleset_name": "",
"src_ads": ["fb213f9b-b440-4ea2-9993-5127c892a6e7"],
"system_resource": false,
"tls_profile": "",
"uuid": "6f9b3536-15c7-474b-a328-0dfe8e0aa136",
"watch": false,
"web_filters": []
}
],
"system_resource": false,
"uuid": "d247bdea-3ca1-429a-bc6d-573881f5e105"
},
{
"attach_to": "defa11a1-3000-4001-0000-000000000000",
"name": "example-policy-group-with-policy",
"sub_policies": [
{
"block": "9165f3ab-81a9-4030-93f8-97ae778126ce",
"priority": 400
},
{
"attachment_point": {
"name": "attach-to-policy",
"target_uuid": "d247bdea-3ca1-429a-bc6d-573881f5e105",
"uuid": "44c020ff-b652-4bf5-ac44-0edc7e01d0d0"
},
"priority": 300
}
],
"system_resource": false,
"uuid": "ed6c047b-e625-4e20-b404-e5c9c2352cb2"
}
]
}
The attachment point 44c020ff-b652-4bf5-ac44-0edc7e01d0d0 is defined using the data block and links the ruleset (d247bdea-3ca1-429a-bc6d-573881f5e105) to the policy group.
{
"dcf_policies": [
{
"attach_to": "",
"name": "System Root Policy Block",
"sub_policies": [
{
"list": "defa11a1-3000-1000-0000-000000000000",
"priority": 1
},
{
"list": "defa11a1-3000-2000-0000-000000000000",
"priority": 10
},
{
"list": "defa11a1-3000-3000-0000-000000000000",
"priority": 20
},
{
"attachment_point": {
"name": "TERRAFORM_BEFORE_UI_MANAGED",
"target_uuid": "ed6c047b-e625-4e20-b404-e5c9c2352cb2",
"uuid": "defa11a1-3000-4001-0000-000000000000"
},
"priority": 50,
"system_resource": true
}
]
}
]
}
The policy block with UUID ed6c047b-e625-4e20-b404-e5c9c2352cb2 is attached to the TERRAFORM_BEFORE_UI_MANAGED block with UUID defa11a1-3000-4001-0000-000000000000.
Impact of Missing Attachment Point
If the attachment_point attribute is not used in the policy block, the ruleset becomes orphaned and not visible in CoPilot UI.
resource "aviatrix_dcf_policy_group" "parent_policy_groupto-rule" {
attach_to = data.aviatrix_dcf_attachment_point.tf_before.id
name = "example-policy-group-with-policy"
policy_group_reference{
priority = 400
target_uuid = aviatrix_dcf_policy_group.parent_policy_group.id
}
# attachment_point block is commented out
#attachment_point {
# name = "attach-to-policy"
# priority = 300
#}
}
{
"dcf_policies": [
{
"attach_to": "44c020ff-b652-4bf5-ac44-0edc7e01d0d0",
"name": "ruleset-with-attachement-point",
"policies": [
{
"action": "PERMIT",
"decrypt_policy": "DECRYPT_UNSPECIFIED",
"desc": "",
"dst_ads": ["b8a93df6-d953-45ad-b02a-d188a80cf62c"],
"exclude_sg_orchestration": false,
"flow_app_requirement": "APP_UNSPECIFIED",
"intrusion_severity": "INTRUSION_SEVERITY_NONE",
"log_profile": "",
"logging": false,
"name": "Policy 5-1",
"port_ranges": [],
"priority": 0,
"protocol": "PROTOCOL_UNSPECIFIED",
"ruleset": 0,
"ruleset_name": "",
"src_ads": ["fb213f9b-b440-4ea2-9993-5127c892a6e7"],
"system_resource": false,
"tls_profile": "",
"uuid": "6f9b3536-15c7-474b-a328-0dfe8e0aa136",
"watch": false,
"web_filters": []
}
],
"system_resource": false,
"uuid": "d247bdea-3ca1-429a-bc6d-573881f5e105"
},
{
"attach_to": "defa11a1-3000-4001-0000-000000000000",
"name": "example-policy-group-with-policy",
"sub_policies": [
{
"block": "9165f3ab-81a9-4030-93f8-97ae778126ce",
"priority": 400
}
],
"system_resource": false,
"uuid": "ed6c047b-e625-4e20-b404-e5c9c2352cb2"
}
]
}
In this response, the attachment point 44c020ff-b652-4bf5-ac44-0edc7e01d0d0 is not attached to the policy block, making the ruleset orphaned.
|
CoPilot UI does not display orphan rulesets. If a ruleset is not attached to the main tree, it will not be visible in CoPilot UI. Use the API |
Notes and Limitations
-
TERRAFORM_BEFORE_UI_MANAGEDandTERRAFORM_AFTER_UI_MANAGEDUUIDs can only be used once per Terraform file for rulesets -
To reuse
attach_toattribute for multiple rulesets, detach from the existing ruleset before attaching to a new ruleset -
Attachment point names in
aviatrix_dcf_attachment_pointandaviatrix_dcf_policy_groupmust match -
Empty policy groups are not supported
-
Policy Groups are not visible in CoPilot UI
-
Editing rules in CoPilot removes attachment point references. Do not edit Terraform-created rules in CoPilot
-
Orphan rulesets (not attached to main tree) are not visible in CoPilot UI. Use API
/v2.5/api/microseg/policy-list3to identify orphan rulesets