-
Notifications
You must be signed in to change notification settings - Fork 15
Description
I'm trying to programmatically create address objects and a policy package using the Provider. I cannot work out how to effectively control policy order in a policy package. Without this, I can't use the provider to manage policy packages.
I'm using for_each to create fortimanager_packages_firewall_policy resources from a list of policies - this works but the policies are created in a random order due to there being no execution order with terraform for_each object even with parallelism set to 1 (ref: hashicorp/terraform#30841).
I'm then creating a fortimanager_packages_firewall_policy_move resource for each policy to order the policies in Fortimanager based on the order of policies in the list. This works and all policy_move resources are created as intended with the correct policy and target, but again due to no execution order within terraform for_each the order the policy_move resources are created and policies are moved to is random.
For example policy id 90 is moved after 100, then 100 is moved after 110 but because 110 could be above in the policy package and its policy_move resources hasn't been created yet 100 will move after 110 meaning it's now above 90. After running apply I can see in the state file that terraform knows the policies aren't where they should be according to the policy_move resource state_pos attribute, but on subsequent applies it doesn't try and fix it, it just shows no changes to infrastructure.
terraform {
required_providers {
fortimanager = {
source = "fortinetdev/fortimanager"
version = "1.15.0"
}
}
}
locals {
address_objects = yamldecode(file("${path.module}/firewall_address.yaml"))
all_addresses = merge(
{ for k, v in local.address_objects.ipmask_addresses : k => merge(v, { type = "ipmask" }) },
{ for k, v in local.address_objects.fqdn_addresses : k => merge(v, { type = "fqdn" }) }
)
policy_list = yamldecode(file("${path.module}/firewall_policies.yaml")).policies
policy_map = { for p in local.policy_list : p.policyid => p }
}
resource "fortimanager_packages_pkg" "aws" {
name = "aws"
type = "pkg"
}
resource "fortimanager_object_firewall_address" "bulk_addresses" {
for_each = local.all_addresses
name = each.key
obj_type = "ip"
type = each.value.type
subnet = lookup(each.value, "subnet", null)
fqdn = lookup(each.value, "fqdn", null)
}
resource "fortimanager_packages_firewall_policy" "bulk_policies" {
for_each = local.policy_map
pkg = fortimanager_packages_pkg.aws.name
policyid = each.key
name = each.value.name
srcintf = lookup(each.value, "srcintf", ["any"])
dstintf = lookup(each.value, "dstintf", ["any"])
srcaddr = [for addr in each.value.srcaddr : fortimanager_object_firewall_address.bulk_addresses[addr].name]
dstaddr = [for addr in each.value.dstaddr : fortimanager_object_firewall_address.bulk_addresses[addr].name]
service = each.value.service
action = lookup(each.value, "action", "accept")
status = lookup(each.value, "status", "enable")
schedule = lookup(each.value, "schedule", "always")
logtraffic = lookup(each.value, "logtraffic", "all")
nat = lookup(each.value, "nat", null)
utm_status = lookup(each.value, "utm_status", null)
av_profile = lookup(each.value, "av_profile", null)
ips_sensor = lookup(each.value, "ips_sensor", null)
webfilter_profile = lookup(each.value, "webfilter_profile", null)
comments = lookup(each.value, "comments", null)
}
resource "fortimanager_packages_firewall_policy_move" "order_policies" {
for_each = {
for i, policy in local.policy_list :
policy.policyid => i if i > 0
}
pkg = fortimanager_packages_pkg.aws.name
policy = fortimanager_packages_firewall_policy.bulk_policies[each.key].policyid
target = fortimanager_packages_firewall_policy.bulk_policies[local.policy_list[each.value - 1].policyid].policyid
option = "after"
}firewall_address.yaml
ipmask_addresses:
addr_192_168_0_1: {subnet: ["192.168.0.1", "255.255.255.255"]}
addr_192_168_0_2: {subnet: ["192.168.0.2", "255.255.255.255"]}
addr_192_168_0_3: {subnet: ["192.168.0.3", "255.255.255.255"]}
fqdn_addresses:
addr_1_aws_com: {fqdn: "1.aws.com"}
addr_2_aws_com: {fqdn: "2.aws.com"}
addr_3_aws_com: {fqdn: "3.aws.com"}firewall_policies.yaml
policies:
- name: "policy_10"
policyid: 10
srcaddr: ["addr_192_168_0_1"]
dstaddr: ["addr_1_aws_com"]
service: ["HTTP"]
- name: "policy_20"
policyid: 20
srcaddr: ["addr_192_168_0_2"]
dstaddr: ["addr_2_aws_com"]
service: ["HTTPS"]
- name: "policy_30"
policyid: 30
srcaddr: ["addr_192_168_0_3"]
dstaddr: ["addr_3_aws_com"]
service: ["ALL"]
- name: "policy_40"
policyid: 40
srcaddr: ["addr_192_168_0_4"]
dstaddr: ["addr_4_aws_com"]
service: ["SSH"]
- name: "policy_50"
policyid: 50
srcaddr: ["addr_192_168_0_5"]
dstaddr: ["addr_5_aws_com"]
service: ["FTP"]
- name: "policy_60"
policyid: 60
srcaddr: ["addr_192_168_0_6"]
dstaddr: ["addr_6_aws_com"]
service: ["DNS"]
- name: "policy_70"
policyid: 70
srcaddr: ["addr_192_168_0_7"]
dstaddr: ["addr_7_aws_com"]
service: ["SMTP"]
- name: "policy_80"
policyid: 80
srcaddr: ["addr_192_168_0_8"]
dstaddr: ["addr_8_aws_com"]
service: ["POP3"]
- name: "policy_90"
policyid: 90
srcaddr: ["addr_192_168_0_9"]
dstaddr: ["addr_9_aws_com"]
service: ["IMAP"]
- name: "policy_100"
policyid: 100
srcaddr: ["addr_192_168_0_10"]
dstaddr: ["addr_10_aws_com"]
service: ["SNMP"]
- name: "policy_110"
policyid: 110
srcaddr: ["addr_192_168_0_11"]
dstaddr: ["addr_11_aws_com"]
service: ["TELNET"]
- name: "policy_120"
policyid: 120
srcaddr: ["addr_192_168_0_12"]
dstaddr: ["addr_12_aws_com"]
service: ["HTTP", "HTTPS"]
- name: "policy_130"
policyid: 130
srcaddr: ["addr_192_168_0_13"]
dstaddr: ["addr_13_aws_com"]
service: ["ALL_TCP"]
- name: "policy_140"
policyid: 140
srcaddr: ["addr_192_168_0_14"]
dstaddr: ["addr_14_aws_com"]
service: ["ALL_UDP"]
- name: "policy_150"
policyid: 150
srcaddr: ["addr_192_168_0_15"]
dstaddr: ["addr_15_aws_com"]
service: ["ALL_ICMP"]
- name: "policy_160"
policyid: 160
srcaddr: ["addr_192_168_0_16"]
dstaddr: ["addr_16_aws_com"]
service: ["RDP"]
- name: "policy_170"
policyid: 170
srcaddr: ["addr_192_168_0_17"]
dstaddr: ["addr_17_aws_com"]
service: ["VNC"]
- name: "policy_180"
policyid: 180
srcaddr: ["addr_192_168_0_18"]
dstaddr: ["addr_18_aws_com"]
service: ["LDAP"]
- name: "policy_190"
policyid: 190
srcaddr: ["addr_192_168_0_19"]
dstaddr: ["addr_19_aws_com"]
service: ["NTP"]
- name: "policy_200"
policyid: 200
srcaddr: ["addr_192_168_0_20"]
dstaddr: ["addr_20_aws_com"]
service: ["ALL"]I could be completely off base here but I tried to research and find examples of how to manage policy order with the Provider and couldn't find anything. How is policy order supposed to be managed? Individual resources with depends_on is not scalable when dealing with hundreds of policies and letting policies be created in a random order won't work either.