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 attachment_point block creates a named attachment point within the policy group. The ruleset defined above uses data.aviatrix_dcf_attachment_point.tf_policy_attachment (with name "attach-to-policy") to attach to this point. This block is the reference that associates the ruleset to the policy block. Without this attachment_point block, the ruleset becomes orphaned. Attachment point names must be globally unique for the entire MWP setup.

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:

Ruleset with Attachment Point Reference
{
    "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.

Policy Block Attached to System Root
{
    "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.

Terraform Code Without Attachment Point
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
    #}
}
API Response Showing Orphan Ruleset
{
    "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 /v2.5/api/microseg/policy-list3 to identify orphan rulesets based on the tree structure returned. It is the user’s responsibility to manage rulesets correctly to avoid orphans.

Notes and Limitations

  • TERRAFORM_BEFORE_UI_MANAGED and TERRAFORM_AFTER_UI_MANAGED UUIDs can only be used once per Terraform file for rulesets

  • To reuse attach_to attribute for multiple rulesets, detach from the existing ruleset before attaching to a new ruleset

  • Attachment point names in aviatrix_dcf_attachment_point and aviatrix_dcf_policy_group must 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-list3 to identify orphan rulesets