netascode / terraform-ise-nac-ise Goto Github PK
View Code? Open in Web Editor NEWTerraform Cisco ISE Network-as-Code Module
Home Page: https://registry.terraform.io/modules/netascode/nac-ise/ise
License: Apache License 2.0
Terraform Cisco ISE Network-as-Code Module
Home Page: https://registry.terraform.io/modules/netascode/nac-ise/ise
License: Apache License 2.0
When creating a Device Admin Policy set with the nested authentication_rules and authorization_rules blocks, the command_sets attribute is not captured and read into the TF plan/apply operation. As such, the AuthZ Policy created in ISE is lacking the Command Sets value.
ise:
device_administration:
policy_sets:
## Create Device Admin Policy Set - Routers and Switches
- name: Routers and Switches
description: Cisco Routers and Switches
condition:
type: ConditionOrBlock
children:
- type: ConditionAttributes
attribute_name: DEVICE:Device Type
operator: equals
attribute_value: "All Device Types#Cisco Switch"
- type: ConditionAttributes
attribute_name: DEVICE:Device Type
operator: equals
attribute_value: "All Device Types#Cisco Router"
service_name: PAP
authentication_rules:
- name: PAP
condition:
type: ConditionAttributes
attribute_name: Network Access:AuthenticationMethod
operator: equals
attribute_value: PAP_ASCII
identity_source_name: ISELAB_AD
authorization_rules:
- name: Router Switch ReadOnly
condition:
type: ConditionAndBlock
children:
- type: ConditionOrBlock
children:
- type: ConditionAttributes
attribute_name: DEVICE:Device Type
operator: equals
attribute_value: All Device Types#Cisco Router
- type: ConditionAttributes
attribute_name: DEVICE:Device Type
operator: equals
attribute_value: All Device Types#Cisco Switch
- type: ConditionAttributes
attribute_name: ISELAB_AD:ExternalGroups
operator: equals
attribute_value: "trappedunderise.com/Users/Net Monitor"
profile: IOS_Admin_Priv10
commands_sets:
- PermitShowCommands
Terraform will perform the following actions:
# module.ise.ise_device_admin_authorization_rule.device_admin_authorization_rule_0["Routers and Switches/Router Switch ReadOnly"] will be created
+ resource "ise_device_admin_authorization_rule" "device_admin_authorization_rule_0" {
+ children = [
+ {
+ children = [
+ {
+ attribute_name = "Device Type"
+ attribute_value = "All Device Types#Cisco Router"
+ condition_type = "ConditionAttributes"
+ dictionary_name = "DEVICE"
+ is_negate = false
+ operator = "equals"
},
+ {
+ attribute_name = "Device Type"
+ attribute_value = "All Device Types#Cisco Switch"
+ condition_type = "ConditionAttributes"
+ dictionary_name = "DEVICE"
+ is_negate = false
+ operator = "equals"
},
]
+ condition_type = "ConditionOrBlock"
+ is_negate = false
},
+ {
+ attribute_name = "ExternalGroups"
+ attribute_value = "trappedunderise.com/Users/Net Monitor"
+ condition_type = "ConditionAttributes"
+ dictionary_name = "ISELAB_AD"
+ is_negate = false
+ operator = "equals"
},
]
+ condition_is_negate = false
+ condition_type = "ConditionAndBlock"
+ default = false
+ id = (known after apply)
+ name = "Router Switch ReadOnly"
+ policy_set_id = "813c3812-fec1-4bd0-a78f-4d95c79a6cfb"
+ profile = "IOS_Admin_Priv10"
+ state = "enabled"
}
When configuration an Allowed Protocols list that includes enabling the EAP-TLS stateless session resume option, Terraform throws a Client Error due to missing required settings.
│ Error: Client Error
│
│ with module.ise.ise_allowed_protocols.allowed_protocols["MAB_Dot1x"],
│ on .terraform/modules/ise/ise_network_access.tf line 1, in resource "ise_allowed_protocols" "allowed_protocols":
│ 1: resource "ise_allowed_protocols" "allowed_protocols" {
│
│ Failed to configure object (PUT), got error: HTTP Request failed: StatusCode 400, Message: Validation Error - Mandatory fields
│ missing: [EapTlsEnableStatelessSessionResume is allowed but the following field is missing: EapTlsSessionTicketTtl,
│ EapTlsEnableStatelessSessionResume is allowed but the following field is missing: EapTlsSessionTicketTtlUnits,
│ EapTlsEnableStatelessSessionResume is allowed but the following field is missing: EapTlsSessionTicketPrecentage], {
│ "ERSResponse" : {
│ "operation" : "PUT-update-allowedprotocols",
│ "messages" : [ {
│ "title" : "Validation Error - Mandatory fields missing: [EapTlsEnableStatelessSessionResume is allowed but the following field is missing: EapTlsSessionTicketTtl, EapTlsEnableStatelessSessionResume is allowed but the following field is missing: EapTlsSessionTicketTtlUnits, EapTlsEnableStatelessSessionResume is allowed but the following field is missing: EapTlsSessionTicketPrecentage]",
│ "type" : "ERROR",
│ "code" : "Application resource validation exception"
│ } ],
│ "link" : {
│ "rel" : "related",
│ "href" : "https://ise32-3.ise.trappedunderise.com/ers/config/allowedprotocols/56bdbe30-c646-11ee-b966-ead89af9fdb3",
│ "type" : "application/xml"
│ }
│ }
│ }
ise:
network_access:
policy_elements:
allowed_protocols:
- name: MAB_Dot1x
description: MAB, EAP-TLS, and TEAP protocols
process_host_lookup: true
allow_pap_ascii: false
allow_eap_md5: false
allow_eap_tls: true
eap_tls:
enable_stateless_session_resume: true
allow_eap_ttls: false
allow_eap_fast: false
allow_peap: false
allow_teap: true
teap:
enable_eap_chaining: true
eap_tls_auth_of_expired_certs: true
The TF provider includes objects for these settings, but the data model does not reference these options. There should be defaults and schema to modify these options.
eap_tls_session_ticket_ttl = 5
eap_tls_session_ticket_ttl_unit = "DAYS"
eap_tls_session_ticket_percentage = 5
When creating a Policy Set with nested conditions, TF throws a Client Error due to missing dictionaryName values. The values exist in the YAML, but the terraform plan does not show the 'dictionary_name' or 'dictionary_value' attributes.
Depending on the dictionary and condition being configured, the dictionary_value is not always null.
ise:
network_access:
policy_sets:
- name: Wired MM
description: Wired Monitor Mode
condition:
type: ConditionAndBlock
children:
- type: ConditionAttributes
dictionary_name: Radius
attribute_name: NAS-Port-Type
operator: equals
dictionary_value: null
attribute_value: Ethernet
- type: ConditionAttributes
dictionary_name: DEVICE
attribute_name: Deployment Stage
operator: equals
dictionary_value: null
attribute_value: Deployment Stage#Monitor Mode
service_name: MAB_Dot1x
Terraform will perform the following actions:
# module.ise.ise_network_access_policy_set.network_access_policy_set_0["Wired MM"] will be created
+ resource "ise_network_access_policy_set" "network_access_policy_set_0" {
+ children = [
+ {
+ attribute_name = "NAS-Port-Type"
+ attribute_value = "Ethernet"
+ condition_type = "ConditionAttributes"
+ is_negate = false
+ operator = "equals"
},
+ {
+ attribute_name = "Deployment Stage"
+ attribute_value = "Deployment Stage#Monitor Mode"
+ condition_type = "ConditionAttributes"
+ is_negate = false
+ operator = "equals"
},
]
+ condition_is_negate = false
+ condition_type = "ConditionAndBlock"
+ description = "Wired Monitor Mode"
+ id = (known after apply)
+ is_proxy = false
+ name = "Wired MM"
+ service_name = "MAB_Dot1x"
+ state = "enabled"
}
Plan: 1 to add, 0 to change, 0 to destroy.
module.ise.ise_network_access_policy_set.network_access_policy_set_0["Wired MM"]: Creating...
module.ise.ise_network_access_policy_set.network_access_policy_set_0["Wired MM"]: Still creating... [10s elapsed]
module.ise.ise_network_access_policy_set.network_access_policy_set_0["Wired MM"]: Still creating... [20s elapsed]
╷
│ Error: Client Error
│
│ with module.ise.ise_network_access_policy_set.network_access_policy_set_0["Wired MM"],
│ on .terraform/modules/ise/ise_network_access.tf line 311, in resource "ise_network_access_policy_set" "network_access_policy_set_0":
│ 311: resource "ise_network_access_policy_set" "network_access_policy_set_0" {
│
│ Failed to configure object (POST), got error: HTTP Request failed: StatusCode 400, Message: , {
│ "message" : "condition.children[1].dictionaryName, must not be null, condition.children[0].dictionaryName, must not be null",
│ "code" : 400
│ }
resource "ise_network_access_policy_set" "ps_wired_mm" {
name = var.ps_wired_mm_name
description = "Wired Monitor Mode"
rank = 0
service_name = ise_allowed_protocols.mab_dot1x.name
state = "enabled"
is_proxy = false
condition_is_negate = false
condition_type = "ConditionAndBlock"
children = [
{
condition_type = "ConditionAttributes"
is_negate = false
dictionary_name = "Radius"
attribute_name = "NAS-Port-Type"
operator = "equals"
attribute_value = "Ethernet"
},
{
condition_type = "ConditionAttributes"
is_negate = false
dictionary_name = "DEVICE"
attribute_name = ise_network_device_group.ndg_deployment_stage.root_group
operator = "equals"
attribute_value = "Deployment Stage#Monitor Mode"
},
]
}
Identity Source Sequence is needed for most certificate-based authentication.
The TF provider defines this resource:
https://registry.terraform.io/providers/CiscoDevNet/ise/latest/docs/resources/identity_source_sequence
When creating more than one Device Admin Policy Set, Terraform throws a Planning failed error for "Inconsistent conditional result types"
If I comment out the second Policy Set block, there are no issues with the create/update operations.
Planning failed. Terraform encountered an error while generating this plan.
╷
│ Error: Inconsistent conditional result types
│
│ on .terraform/modules/ise/ise_device_admin.tf line 161, in locals:
│ 161: device_admin_policy_sets = var.manage_device_administration ? [
│ 162: for ps in try(local.ise.device_administration.policy_sets, []) : {
│ 163: condition_type = try(ps.condition.type, local.defaults.ise.device_administration.policy_sets.condition.type, null)
│ 164: condition_is_negate = try(ps.condition.is_negate, local.defaults.ise.device_administration.policy_sets.condition.is_negate, null)
│ 165: condition_attribute_name = strcontains(try(ps.condition.attribute_name, local.defaults.ise.device_administration.policy_sets.condition.attribute_name, ""), ":") ? split(":", try(ps.condition.attribute_name, local.defaults.ise.device_administration.policy_sets.condition.attribute_name, null))[1] : try(ps.condition.attribute_name, local.defaults.ise.device_administration.policy_sets.condition.attribute_name, null)
│ 166: condition_attribute_value = strcontains(try(ps.condition.attribute_value, local.defaults.ise.device_administration.policy_sets.condition.attribute_value, ""), ":") ? split(":", try(ps.condition.attribute_value, local.defaults.ise.device_administration.policy_sets.condition.attribute_value, null))[1] : try(ps.condition.attribute_value, local.defaults.ise.device_administration.policy_sets.condition.attribute_value, null)
│ 167: condition_dictionary_name = strcontains(try(ps.condition.attribute_name, local.defaults.ise.device_administration.policy_sets.condition.attribute_name, ""), ":") ? split(":", try(ps.condition.attribute_name, local.defaults.ise.device_administration.policy_sets.condition.attribute_name, null))[0] : null
│ 168: condition_dictionary_value = strcontains(try(ps.condition.attribute_value, local.defaults.ise.device_administration.policy_sets.condition.attribute_value, ""), ":") ? split(":", try(ps.condition.attribute_value, local.defaults.ise.device_administration.policy_sets.condition.attribute_value, null))[0] : null
│ 169: condition_id = contains(local.known_conditions_device_admin, try(ps.condition.name, "")) ? ise_device_admin_condition.device_admin_condition[ps.condition.name].id : try(data.ise_device_admin_condition.device_admin_condition[ps.condition.name].id, null)
│ 170: condition_operator = try(ps.condition.operator, local.defaults.ise.device_administration.policy_sets.condition.operator, null)
│ 171: description = try(ps.description, local.defaults.ise.device_administration.policy_sets.description, null)
│ 172: is_proxy = try(ps.is_proxy, local.defaults.ise.device_administration.policy_sets.is_proxy)
│ 173: name = ps.name
│ 174: service_name = try(ps.service_name, local.defaults.ise.device_administration.policy_sets.service_name)
│ 175: state = try(ps.state, local.defaults.ise.device_administration.policy_sets.state)
│ 176: rank = try(ps.rank, local.defaults.ise.device_administration.policy_sets.rank, null)
│ 177: children = try([for i in ps.condition.children : {
│ 178: attribute_name = strcontains(try(i.attribute_name, local.defaults.ise.device_administration.policy_sets.condition.attribute_name, ""), ":") ? split(":", try(i.attribute_name, local.defaults.ise.device_administration.policy_sets.condition.attribute_name, null))[1] : try(i.attribute_name, local.defaults.ise.device_administration.policy_sets.condition.attribute_name, null)
│ 179: attribute_value = strcontains(try(i.attribute_value, local.defaults.ise.device_administration.policy_sets.condition.attribute_value, ""), ":") ? split(":", try(i.attribute_value, local.defaults.ise.device_administration.policy_sets.condition.attribute_value, null))[1] : try(i.attribute_value, local.defaults.ise.device_administration.policy_sets.condition.attribute_value, null)
│ 180: dictionary_name = strcontains(try(i.attribute_name, local.defaults.ise.device_administration.policy_sets.condition.attribute_name, ""), ":") ? split(":", try(i.attribute_name, local.defaults.ise.device_administration.policy_sets.condition.attribute_name, null))[0] : null
│ 181: dictionary_value = strcontains(try(i.attribute_value, local.defaults.ise.device_administration.policy_sets.condition.attribute_value, ""), ":") ? split(":", try(i.attribute_value, local.defaults.ise.device_administration.policy_sets.condition.attribute_value, null))[0] : null
│ 182: condition_type = try(i.type, local.defaults.ise.device_administration.policy_sets.condition.type, null)
│ 183: is_negate = try(i.is_negate, local.defaults.ise.device_administration.policy_sets.condition.is_negate, null)
│ 184: operator = try(i.operator, local.defaults.ise.device_administration.policy_sets.condition.operator, null)
│ 185: id = contains(local.known_conditions_device_admin, try(i.name, "")) ? ise_device_admin_condition.device_admin_condition[i.name].id : try(data.ise_device_admin_condition.device_admin_condition[i.name].id, null)
│ 186: children = try([for j in i.children : {
│ 187: attribute_name = strcontains(try(j.attribute_name, local.defaults.ise.device_administration.policy_sets.condition.attribute_name, ""), ":") ? split(":", try(j.attribute_name, local.defaults.ise.device_administration.policy_sets.condition.attribute_name, null))[1] : try(j.attribute_name, local.defaults.ise.device_administration.policy_sets.condition.attribute_name, null)
│ 188: attribute_value = strcontains(try(j.attribute_value, local.defaults.ise.device_administration.policy_sets.condition.attribute_value, ""), ":") ? split(":", try(j.attribute_value, local.defaults.ise.device_administration.policy_sets.condition.attribute_value, null))[1] : try(j.attribute_value, local.defaults.ise.device_administration.policy_sets.condition.attribute_value, null)
│ 189: dictionary_name = strcontains(try(j.attribute_name, local.defaults.ise.device_administration.policy_sets.condition.attribute_name, ""), ":") ? split(":", try(j.attribute_name, local.defaults.ise.device_administration.policy_sets.condition.attribute_name, null))[0] : null
│ 190: dictionary_value = strcontains(try(j.attribute_value, local.defaults.ise.device_administration.policy_sets.condition.attribute_value, ""), ":") ? split(":", try(j.attribute_value, local.defaults.ise.device_administration.policy_sets.condition.attribute_value, null))[0] : null
│ 191: condition_type = try(j.type, local.defaults.ise.device_administration.policy_sets.condition.type, null)
│ 192: is_negate = try(j.is_negate, local.defaults.ise.device_administration.policy_sets.condition.is_negate, null)
│ 193: operator = try(j.operator, local.defaults.ise.device_administration.policy_sets.condition.operator, null)
│ 194: id = contains(local.known_conditions_device_admin, try(j.name, "")) ? ise_device_admin_condition.device_admin_condition[j.name].id : try(data.ise_device_admin_condition.device_admin_condition[j.name].id, null)
│ 195: }], null)
│ 196: }], null)
│ 197: }
│ 198: ] : []
│ ├────────────────
│ │ data.ise_device_admin_condition.device_admin_condition is object with no attributes
│ │ ise_device_admin_condition.device_admin_condition is object with no attributes
│ │ local.defaults.ise.device_administration.policy_sets is object with 7 attributes
│ │ local.defaults.ise.device_administration.policy_sets.condition is object with 2 attributes
│ │ local.defaults.ise.device_administration.policy_sets.condition.is_negate is false
│ │ local.defaults.ise.device_administration.policy_sets.is_proxy is false
│ │ local.defaults.ise.device_administration.policy_sets.state is "enabled"
│ │ local.ise.device_administration.policy_sets is tuple with 2 elements
│ │ local.known_conditions_device_admin is empty tuple
│
│ The true result value has the wrong type: element types must all match for conversion to list.
ise:
device_administration:
policy_sets:
## Create Device Admin Policy Set - Routers and Switches
- name: Routers and Switches
description: Cisco Routers and Switches
condition:
type: ConditionOrBlock
children:
- type: ConditionAttributes
attribute_name: DEVICE:Device Type
operator: equals
attribute_value: "All Device Types#Cisco Switch"
- type: ConditionAttributes
attribute_name: DEVICE:Device Type
operator: equals
attribute_value: "All Device Types#Cisco Router"
service_name: PAP
### Create Device Admin Policy Set - Wireless Controllers
- name: Wireless Controllers
description: Cisco Wireless LAN Controllers
condition:
type: ConditionAttributes
attribute_name: DEVICE:Device Type
operator: equals
attribute_value: "All Device Types#Cisco WLC"
service_name: PAP
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.