CiscoISE / terraform-provider-ciscoise

Terraform Provider for Cisco ISE
https://registry.terraform.io/providers/CiscoISE/ciscoise/latest/docs
MIT License
10 stars 4 forks source link

Resource 'ciscoise_network_access_authentication_rules' does not support nested children blocks #68

Closed aussietexan closed 2 years ago

aussietexan commented 2 years ago

Environment: ISE version and patch: ISE 3.1 patch 4 Terraform version: 1.3.1 ISE provider version: 0.6.10-beta OS version: MacOS 12.6

Affected resources The same nested logic described below should apply to all of the following resources:

Describe the bug The ISE Authentication and Authorization Policies support creation of multiple AND/OR condition matching blocks. As such, the TF resource needs to support creation of the same structure. When attempting to create a new AuthC Policy, TF return an error for multiple unsupported arguments:

│ Error: Unsupported argument
│ 
│   on policy.tf line 329, in resource "ciscoise_network_access_authentication_rules" "mm-authc-eaptls":
│  329:         dictionary_name  = "Radius"
│ 
│ An argument named "dictionary_name" is not expected here.
╵
╷
│ Error: Unsupported argument
│ 
│   on policy.tf line 330, in resource "ciscoise_network_access_authentication_rules" "mm-authc-eaptls":
│  330:         attribute_name  = "NAS-Port-Type"
│ 
│ An argument named "attribute_name" is not expected here.
╵
╷
│ Error: Unsupported argument
│ 
│   on policy.tf line 331, in resource "ciscoise_network_access_authentication_rules" "mm-authc-eaptls":
│  331:         operator = "equals"
│ 
│ An argument named "operator" is not expected here.
╵
╷
│ Error: Unsupported argument
│ 
│   on policy.tf line 332, in resource "ciscoise_network_access_authentication_rules" "mm-authc-eaptls":
│  332:         attribute_value = "Ethernet"
│ 
│ An argument named "attribute_value" is not expected here.
╵
╷
│ Error: Unsupported argument
│ 
│   on policy.tf line 337, in resource "ciscoise_network_access_authentication_rules" "mm-authc-eaptls":
│  337:         dictionary_name  = "Network Access"
│ 
│ An argument named "dictionary_name" is not expected here.
╵
╷
│ Error: Unsupported argument
│ 
│   on policy.tf line 338, in resource "ciscoise_network_access_authentication_rules" "mm-authc-eaptls":
│  338:         attribute_name  = "EapAuthentication"
│ 
│ An argument named "attribute_name" is not expected here.
╵
╷
│ Error: Unsupported argument
│ 
│   on policy.tf line 339, in resource "ciscoise_network_access_authentication_rules" "mm-authc-eaptls":
│  339:         operator = "equals"
│ 
│ An argument named "operator" is not expected here.
╵
╷
│ Error: Unsupported argument
│ 
│   on policy.tf line 340, in resource "ciscoise_network_access_authentication_rules" "mm-authc-eaptls":
│  340:         attribute_value = "EAP-TLS"
│ 
│ An argument named "attribute_value" is not expected here.

Example code

resource "ciscoise_network_access_authentication_rules" "mm-authc-eaptls" {
  provider = ciscoise.ise31-2
  parameters {
    identity_source_name = ciscoise_id_store_sequence.iss-ad-cert.item[0].name
    if_auth_fail         = "REJECT"
    if_process_fail      = "DROP"
    if_user_not_found    = "REJECT"
    policy_id = "b8731cac-dba3-43bc-ac2b-f3205e01e8c1"
    rule {
      default    = "false"
      name       = var.authc-policy-eaptls
      rank       = 0
      state      = "enabled"
      condition {
        condition_type = "andBlock"
        is_negate = "false"
      children {
        dictionary_name  = "Radius"
        attribute_name  = "NAS-Port-Type"
        operator = "equals"
        attribute_value = "Ethernet"
        is_negate      = "false"
      }
      children {
        dictionary_name  = "Network Access"
        attribute_name  = "EapAuthentication"
        operator = "equals"
        attribute_value = "EAP-TLS"
        is_negate = "false"
      }
    }

OpenAPI call resulting in '201 Created' response

{
        {
            "rule": {
                "default": false,
                "name": "Dot1x EAP-TLS",
                "rank": 0,
                "state": "enabled",
                "condition": {
                    "conditionType": "ConditionAndBlock",
                    "isNegate": false,
                    "children": [
                        {
                            "conditionType": "ConditionAttributes",
                            "isNegate": false,
                            "dictionaryName": "Radius",
                            "attributeName": "NAS-Port-Type",
                            "operator": "equals",
                            "attributeValue": "Ethernet"
                        },
                        {
                            "conditionType": "ConditionAttributes",
                            "isNegate": false,
                            "dictionaryName": "Network Access",
                            "attributeName": "EapAuthentication",
                            "operator": "equals",
                            "attributeValue": "EAP-TLS"
                        }
                    ]
                }
            },
            "identitySourceName": "ISS_AD_Cert",
            "ifAuthFail": "REJECT",
            "ifUserNotFound": "REJECT",
            "ifProcessFail": "DROP"
        }
}

Additional context Policy Sets, Authentication, and Authorization policies support multiple levels of nesting, so the TF resources needs to support the same. Here is an example of the GET API output for a nested OR block within the same policy.

{
    "version": "1.0.0",
    "response": {
        "rule": {
            "default": false,
            "id": "ce68e2e9-1526-45c2-b025-925d80725d22",
            "name": "Dot1x EAP-TLS",
            "hitCounts": 0,
            "rank": 0,
            "state": "enabled",
            "condition": {
                "link": null,
                "conditionType": "ConditionAndBlock",
                "isNegate": false,
                "children": [
                    {
                        "link": null,
                        "conditionType": "ConditionAttributes",
                        "isNegate": false,
                        "dictionaryName": "Radius",
                        "attributeName": "NAS-Port-Type",
                        "operator": "equals",
                        "dictionaryValue": null,
                        "attributeValue": "Ethernet"
                    },
                    {
                        "link": null,
                        "conditionType": "ConditionAttributes",
                        "isNegate": false,
                        "dictionaryName": "Network Access",
                        "attributeName": "EapAuthentication",
                        "operator": "equals",
                        "dictionaryValue": null,
                        "attributeValue": "EAP-TLS"
                    },
                    {
                        "link": null,
                        "conditionType": "ConditionOrBlock",
                        "isNegate": false,
                        "children": [
                            {
                                "link": null,
                                "conditionType": "ConditionAttributes",
                                "isNegate": false,
                                "dictionaryName": "Radius",
                                "attributeName": "User-Name",
                                "operator": "equals",
                                "dictionaryValue": null,
                                "attributeValue": "user1"
                            },
                            {
                                "link": null,
                                "conditionType": "ConditionAttributes",
                                "isNegate": false,
                                "dictionaryName": "Radius",
                                "attributeName": "User-Name",
                                "operator": "equals",
                                "dictionaryValue": null,
                                "attributeValue": "user2"
                            }
                        ]
                    }
                ]
            }
        },
        "identitySourceName": "ISS_AD_Cert",
        "ifAuthFail": "REJECT",
        "ifUserNotFound": "REJECT",
        "ifProcessFail": "DROP",
        "link": {
            "rel": "self",
            "href": "https://ise31-2.ise.trappedunderise.com/api/v1/policy/network-access/policy-set/b8731cac-dba3-43bc-ac2b-f3205e01e8c1/authentication/ce68e2e9-1526-45c2-b025-925d80725d22",
            "type": "application/json"
        }
    }
}
fmunozmiranda commented 2 years ago

@aussietexan , please try it with 0.6.11-beta and let us know if it is working for you.

aussietexan commented 2 years ago

Hi @fmunozmiranda. I tried using the same example code above to create the AuthC rule with the 0.6.11-beta code and now I get a 400 error.

│ Error: Failure when executing CreateNetworkAccessAuthenticationRule
│ 
│   with ciscoise_network_access_authentication_rules.mm-authc-eaptls,
│   on policy.tf line 309, in resource "ciscoise_network_access_authentication_rules" "mm-authc-eaptls":
│  309: resource "ciscoise_network_access_authentication_rules" "mm-authc-eaptls" {
│ 
│ error with operation CreateNetworkAccessAuthenticationRule
│ {
│   "message" : "request has bad input format in the body",
│   "code" : 400
│ }
aussietexan commented 2 years ago

@fmunozmiranda. I noticed that the documentation was updated to included the 'condition_type' in the nested children block, so I updated my TF code as follows. It still returns the same 400 error.

TF Code

resource "ciscoise_network_access_authentication_rules" "mm-authc-eaptls" {
  provider = ciscoise.ise31-2
  parameters {
    identity_source_name = ciscoise_id_store_sequence.iss-ad-cert.item[0].name
    if_auth_fail         = "REJECT"
    if_process_fail      = "DROP"
    if_user_not_found    = "REJECT"
    policy_id = "8c73e8d8-1c3c-477b-8b6f-d58952d490f2"
    rule {
      default    = "false"
      name       = var.authc-policy-eaptls
      rank       = 0
      state      = "enabled"
      condition {
        condition_type = "andBlock"
        is_negate = "false"
      children {
        condition_type = "ConditionAttrs"
        dictionary_name  = "Radius"
        attribute_name  = "NAS-Port-Type"
        operator = "equals"
        attribute_value = "Ethernet"
        is_negate      = "false"
      }
      children {
        condition_type = "ConditionAttrs"
        dictionary_name  = "Network Access"
        attribute_name  = "EapAuthentication"
        operator = "equals"
        attribute_value = "EAP-TLS"
        is_negate = "false"
      }
    }
  }
}
}

API body that returns 201 Created response

{
            "rule": {
                "default": false,
                "name": "Dot1x EAP-TLS",
                "rank": 0,
                "state": "enabled",
                "condition": {
                    "conditionType": "ConditionAndBlock",
                    "isNegate": false,
                    "children": [
                        {
                            "conditionType": "ConditionAttributes",
                            "isNegate": false,
                            "dictionaryName": "Radius",
                            "attributeName": "NAS-Port-Type",
                            "operator": "equals",
                            "attributeValue": "Ethernet"
                        },
                        {
                            "conditionType": "ConditionAttributes",
                            "isNegate": false,
                            "dictionaryName": "Network Access",
                            "attributeName": "EapAuthentication",
                            "operator": "equals",
                            "attributeValue": "EAP-TLS"
                        }
                    ]
                }
            },
            "identitySourceName": "ISS_AD_Cert",
            "ifAuthFail": "REJECT",
            "ifUserNotFound": "REJECT",
            "ifProcessFail": "DROP"
        }
fmunozmiranda commented 2 years ago

Hi @aussietexan do you have a valid request body (functional on api, tested in postman or something like that) for this resource? if you have it, should you pass it?

aussietexan commented 2 years ago

Hi @fmunozmiranda , the response I posted above has an example request body for the API that returns a '201 Created' response when used in Postman.

fmunozmiranda commented 2 years ago

Hey @aussietexan, I think the problem is in your condition_type values it seems that accepted values are:

  1. ConditionAttributes
  2. ConditionAndBlock
  3. ConditionOrBlock

Could you tested with those changes?

aussietexan commented 2 years ago

Hi @fmunozmiranda , I updated my TF code to use those values rather than the values in the documentation (https://registry.terraform.io/providers/CiscoISE/ciscoise/latest/docs/resources/network_access_policy_set#nested-schema-for-parametersconditionchildren) and both the Policy Set and AuthC Policy resources worked correctly. Please update the documentation to reflect the correct accepted values.

Example TF code

resource "ciscoise_network_access_policy_set" "wired-mm-test" {
  provider = ciscoise.ise31-2
  depends_on = [
    ciscoise_network_device_group.ndg_mm
  ]
  parameters {
    default     = "false"
    name         = "Wired_MM_TEST"
    description = "Wired Monitor Mode TEST"
    rank         = 0
    is_proxy    = "false"
    service_name = "MAB_EAP-TLS"
    state        = "enabled"
    condition {
      condition_type = "ConditionAndBlock"
      is_negate = "false"
      children {
        condition_type = "ConditionAttributes"
        is_negate = "false"
        dictionary_name  = "Radius"
        attribute_name  = "NAS-Port-Type"
        operator = "equals"
        attribute_value = "Ethernet"
      }
      children {
        condition_type = "ConditionAttributes"
        is_negate = "false"
        dictionary_name  = "DEVICE"
        attribute_name  = "Deployment Stage"
        operator = "equals"
        attribute_value = "Deployment Stage#Monitor Mode"
      }
    }
  }
}

resource "ciscoise_network_access_authentication_rules" "mm-authc-eaptls" {
  provider = ciscoise.ise31-2
  parameters {
    identity_source_name = ciscoise_id_store_sequence.iss-ad-cert.item[0].name
    if_auth_fail         = "REJECT"
    if_process_fail      = "DROP"
    if_user_not_found    = "REJECT"
    policy_id = ciscoise_network_access_policy_set.wired-mm-test.parameters[0].id
    rule {
      default    = "false"
      name       = var.authc-policy-eaptls
      rank       = 0
      state      = "enabled"
      condition {
        condition_type = "ConditionAndBlock"
        is_negate = "false"
      children {
        condition_type = "ConditionAttributes"
        dictionary_name  = "Radius"
        attribute_name  = "NAS-Port-Type"
        operator = "equals"
        attribute_value = "Ethernet"
        is_negate      = "false"
      }
      children {
        condition_type = "ConditionAttributes"
        dictionary_name  = "Network Access"
        attribute_name  = "EapAuthentication"
        operator = "equals"
        attribute_value = "EAP-TLS"
        is_negate = "false"
      }
    }
  }
}
}
fmunozmiranda commented 2 years ago

Thanks for feedback, I will update documentation in next realese.