CiscoDevNet / terraform-provider-fmc

Terraform Provider for FMC
https://registry.terraform.io/providers/CiscoDevNet/fmc/latest/docs
Mozilla Public License 2.0
16 stars 30 forks source link

Assigning policy to multiple devices #127

Closed mossholderm closed 12 months ago

mossholderm commented 1 year ago

Hey, not sure if this is just my lack of knowledge of Terraform, or something that is missing from the provider, so sorry in advance if this is covered elsewhere!

I'm trying to assign a NAT policy all of the FTD sensors created in the Terraform plan, but can't work out how to assign to more than one device. I have code that I think should work, but seems to fail. Sometimes the policy gets assigned to the devices (two in my current setup), but fails with this error:

fmc_policy_devices_assignments.policy_assignment[1]: Creating...
fmc_policy_devices_assignments.policy_assignment[0]: Creating...
fmc_policy_devices_assignments.policy_assignment[1]: Creation complete after 1s [id=6045BD81-FA16-0ed3-0000-004295038862] 
╷
│ Error: unable to create policy devices assignment
│
│   with fmc_policy_devices_assignments.policy_assignment[0],
│   on 070-fmc.tf line 50, in resource "fmc_policy_devices_assignments" "policy_assignment":
│   50: resource "fmc_policy_devices_assignments" "policy_assignment" {
│
│ getting device policy assignments:
│ https://XXX.XXX.XXX.XXX/api/fmc_config/v1/domain/e276abec-e0f2-11e3-8169-6d9ed49b625f/assignment/policyassignments - wrong   
│ status code: 406, error category: FRAMEWORK, error severity: ERROR, error messages: [{Given policy already has some     
│ assignments. Please send PUT request to update assignments.}]

Looking in the FMC after this run, the policy was assigned to both sensors, and I had removed all mappings prior to running the terraform code.

The code that produces the error is here:

resource "fmc_policy_devices_assignments" "policy_assignment" {
    count = var.instances
    policy {
        id   = data.fmc_ftd_nat_policies.nat_policy.id
        type = data.fmc_ftd_nat_policies.nat_policy.type
    }
    target_devices {
        id   = data.fmc_devices.device[0].id
        type = data.fmc_devices.device[0].type
    }
    target_devices {
        id   = data.fmc_devices.device[1].id
        type = data.fmc_devices.device[1].type
    }
}

Is there a way to make the code more dynamic? Is there method to add X many target devices blocks? I can't seem to work it out, and the examples don't seem to cover it.

Thanks so much!

mossholderm commented 1 year ago

A little more info...

Removing the count = var.instances reference AND leaving the two target_device blocks works.

However, using count and a single target_devices block which references count.index as the array index fails with the same errors as in the initial post (code follows):

resource "fmc_policy_devices_assignments" "policy_assignment" {
    count = var.instances
    policy {
        id   = data.fmc_ftd_nat_policies.nat_policy.id
        type = data.fmc_ftd_nat_policies.nat_policy.type
    }
    target_devices {
        id   = data.fmc_devices.device[count.index].id
        type = data.fmc_devices.device[count.index].type
    }

}

Could it be that fmc_policy_devices_assignments is broken when it comes to using the count keyword?

mossholderm commented 12 months ago

I found a solution... for those that might run into the same issue. You need to use a dynamic block to build out the target_devices blocks programmatically.

resource "fmc_policy_devices_assignments" "policy_assignment" {

    policy {
        id   = data.fmc_ftd_nat_policies.nat_policy.id
        type = data.fmc_ftd_nat_policies.nat_policy.type
    }
    dynamic "target_devices" {
        for_each = toset(data.fmc_devices.device[*])
        iterator = target_device
        content {
            id   = target_device.value.id
            type = target_device.value.type
        }
    }
}
mossholderm commented 12 months ago

Solution found.