Development

This commit is contained in:
Matthew Grotke 2026-06-07 17:29:01 -04:00
parent cef2543572
commit 351ce39558
3 changed files with 120 additions and 104 deletions

View file

@ -71,6 +71,7 @@ def auth_mode_save():
eap_protocol = 'eap_peap' eap_protocol = 'eap_peap'
tunneled_reply = 'tunneled_reply' in request.form tunneled_reply = 'tunneled_reply' in request.form
include_length = 'include_length' in request.form include_length = 'include_length' in request.form
mab_fallback = 'mab_fallback' in request.form
inner_protocol = request.form.get('inner_protocol', '') inner_protocol = request.form.get('inner_protocol', '')
_valid_inner = { _valid_inner = {
@ -84,6 +85,7 @@ def auth_mode_save():
if auth_mode == 'eap_password': if auth_mode == 'eap_password':
after['eap_protocol'] = eap_protocol after['eap_protocol'] = eap_protocol
after['tunneled_reply'] = tunneled_reply and eap_protocol in ('eap_peap', 'eap_ttls') after['tunneled_reply'] = tunneled_reply and eap_protocol in ('eap_peap', 'eap_ttls')
after['mab_fallback'] = mab_fallback
if eap_protocol in _valid_inner and inner_protocol in _valid_inner[eap_protocol]: if eap_protocol in _valid_inner and inner_protocol in _valid_inner[eap_protocol]:
after['inner_protocol'] = inner_protocol after['inner_protocol'] = inner_protocol
else: else:
@ -94,6 +96,7 @@ def auth_mode_save():
after.pop('include_length', None) after.pop('include_length', None)
elif auth_mode == 'eap_credential': elif auth_mode == 'eap_credential':
after['include_length'] = include_length after['include_length'] = include_length
after['mab_fallback'] = mab_fallback
after.pop('eap_protocol', None) after.pop('eap_protocol', None)
after.pop('tunneled_reply', None) after.pop('tunneled_reply', None)
after.pop('inner_protocol', None) after.pop('inner_protocol', None)
@ -102,6 +105,7 @@ def auth_mode_save():
after.pop('tunneled_reply', None) after.pop('tunneled_reply', None)
after.pop('inner_protocol', None) after.pop('inner_protocol', None)
after.pop('include_length', None) after.pop('include_length', None)
after.pop('mab_fallback', None)
cfg.setdefault('radius', {})['options'] = after cfg.setdefault('radius', {})['options'] = after
changes = config_utils.diff_fields(before, after) changes = config_utils.diff_fields(before, after)

View file

@ -100,110 +100,7 @@
}, },
{ {
"type": "card", "type": "card",
"label": "DEFAULT Rule Scope", "label": "Known Clients",
"client_requirement": "client_is_administrator+",
"items": [
{
"type": "p",
"text": "The DEFAULT Rule only applies to unknown devices (those without a DHCP reservation/authorization)."
},
{
"type": "raw_html",
"html": "<br>"
},
{
"type": "form",
"action": "/action/radius/default_rule_save",
"method": "post",
"items": [
{
"type": "field",
"label": "Which RADIUS Clients (authenticators) may apply the DEFAULT rule to unknown devices?",
"name": "apply_to",
"input_type": "select",
"value": "%RADIUS_APPLY_TO%",
"options": [
{"value": "all", "label": "All authenticators"},
{"value": "wireless", "label": "Wireless authenticators only (NAS-Port-Type = Wireless-802.11)"},
{"value": "huntgroup", "label": "Wireless authenticators only (AP huntgroup by IP)"}
],
"hint": "_"
},
{
"type": "field",
"label": "Which of the following authenticators are Wireless Access Points that you wish to add to the huntgroup?",
"name": "ap_ips",
"input_type": "checkbox_group",
"options": "%RADIUS_AP_IPS_OPTIONS%",
"value": "%RADIUS_AP_IPS%",
"hint": "These authenticators are defined on the DHCP Reservations page by denoting a device (such as a managed switch or wireless access point) as a \"RADIUS Client\"."
},
{
"type": "button_row",
"items": [
{
"type": "button_primary",
"action": "/action/radius/default_rule_save",
"method": "post",
"text": "Save"
},
{
"type": "button_cancel",
"text": "Cancel"
}
]
}
]
}
]
},
{
"type": "card",
"label": "Default VLAN",
"client_requirement": "client_is_administrator+",
"items": [
{
"type": "p",
"text": "Unknown devices are assigned to this VLAN. For wired switch ports, also set the fallback network in your managed switch's configuration."
},
{
"type": "raw_html",
"html": "<br>"
},
{
"type": "form",
"action": "/action/radius/default_vlan_save",
"method": "post",
"items": [
{
"type": "field",
"label": "Default VLAN",
"name": "default_vlan",
"input_type": "select",
"value": "%RADIUS_DEFAULT_VLAN%",
"options": "%RADIUS_DEFAULT_VLAN_OPTIONS%",
"hint": "Devices without a DHCP reservation will receive RADIUS authorization to be placed on this VLAN. This may also be selected on the Network Layout page by denoting a VLAN as the \"RADIUS Default\"."
},
{
"type": "button_row",
"items": [
{
"type": "button_primary",
"text": "Save"
},
{
"type": "button_cancel",
"text": "Cancel"
}
]
}
]
}
]
},
{
"type": "card",
"label": "Authentication Mode",
"client_requirement": "client_is_administrator+", "client_requirement": "client_is_administrator+",
"items": [ "items": [
{ {
@ -292,6 +189,120 @@
"type": "raw_html", "type": "raw_html",
"html": "</div>" "html": "</div>"
}, },
{
"type": "raw_html",
"html": "<div id=\"mab-fallback-row\">"
},
{
"type": "field",
"label": "",
"name": "mab_fallback",
"input_type": "checkbox",
"checkbox_label": "Try MAB first before prompting supplicant",
"value": "%RADIUS_MAB_FALLBACK%",
"hint": "When a device fails or skips 802.1X, RADIUS will attempt to authenticate it by MAC address before rejecting it. Useful for networks with a mix of 802.1X-capable and non-802.1X devices."
},
{
"type": "raw_html",
"html": "</div>"
},
{
"type": "button_row",
"items": [
{
"type": "button_primary",
"text": "Save"
},
{
"type": "button_cancel",
"text": "Cancel"
}
]
}
]
}
]
},
{
"type": "card",
"label": "Unknown Clients",
"client_requirement": "client_is_administrator+",
"items": [
{
"type": "p",
"text": "The DEFAULT Rule only applies to unknown devices (those without a DHCP reservation/authorization)."
},
{
"type": "raw_html",
"html": "<br>"
},
{
"type": "form",
"action": "/action/radius/default_rule_save",
"method": "post",
"items": [
{
"type": "field",
"label": "Which RADIUS Clients (authenticators) may apply the DEFAULT rule to unknown devices?",
"name": "apply_to",
"input_type": "select",
"value": "%RADIUS_APPLY_TO%",
"options": [
{"value": "all", "label": "All authenticators"},
{"value": "wireless", "label": "Wireless authenticators only (NAS-Port-Type = Wireless-802.11)"},
{"value": "huntgroup", "label": "Wireless authenticators only (AP huntgroup by IP)"}
],
"hint": "_"
},
{
"type": "field",
"label": "Which of the following authenticators are Wireless Access Points that you wish to add to the huntgroup?",
"name": "ap_ips",
"input_type": "checkbox_group",
"options": "%RADIUS_AP_IPS_OPTIONS%",
"value": "%RADIUS_AP_IPS%",
"hint": "These authenticators are defined on the DHCP Reservations page by denoting a device (such as a managed switch or wireless access point) as a \"RADIUS Client\"."
},
{
"type": "button_row",
"items": [
{
"type": "button_primary",
"text": "Save"
},
{
"type": "button_cancel",
"text": "Cancel"
}
]
}
]
},
{
"type": "hr"
},
{
"type": "p",
"text": "Unknown devices are assigned to this VLAN. For wired switch ports, also set the fallback network in your managed switch's configuration."
},
{
"type": "raw_html",
"html": "<br>"
},
{
"type": "form",
"action": "/action/radius/default_vlan_save",
"method": "post",
"items": [
{
"type": "field",
"label": "Default VLAN",
"name": "default_vlan",
"input_type": "select",
"value": "%RADIUS_DEFAULT_VLAN%",
"options": "%RADIUS_DEFAULT_VLAN_OPTIONS%",
"hint": "Devices without a DHCP reservation will receive RADIUS authorization to be placed on this VLAN. This may also be selected on the Network Layout page by denoting a VLAN as the \"RADIUS Default\"."
},
{ {
"type": "button_row", "type": "button_row",
"items": [ "items": [

View file

@ -122,6 +122,7 @@ def collect_tokens(cfg):
tokens['RADIUS_TUNNELED_REPLY'] = 'true' if fr_opts.get('tunneled_reply', False) else '' tokens['RADIUS_TUNNELED_REPLY'] = 'true' if fr_opts.get('tunneled_reply', False) else ''
tokens['RADIUS_INCLUDE_LENGTH'] = 'true' if fr_opts.get('include_length', False) else '' tokens['RADIUS_INCLUDE_LENGTH'] = 'true' if fr_opts.get('include_length', False) else ''
tokens['RADIUS_MAB_FALLBACK'] = 'true' if fr_opts.get('mab_fallback', False) else ''
vlans = cfg.get('vlans', []) vlans = cfg.get('vlans', [])
default_vlan = next((v['name'] for v in vlans if v.get('radius_default') is True), '') default_vlan = next((v['name'] for v in vlans if v.get('radius_default') is True), '')