Administrator users of Fortianalyzer, Fortimanager, and Fortigate authenticated via RADIUS
- Intro
- Decide whether to use Wildcard user on FAZ/FMG/FGT or only specific users.
- RADIUS Configuration - Windows NPS
- Install Network Policy Role (NPS)
- Open NPS management console
- Integrate NPS with local Active Directory
- Create in NPS console RADIUS clients signifying each network device (FGT, FAZ, FMG)
- Create Connection Request Policy for each client
- Create Network Policy for each RADIUS client matching on AD Groups membership for end users
- Fortigate configuration
- Wildcard User with dummy accprofile assigned on Fortinet device with override enabled to get actual profile name from the RADIUS
- Wildcard user with accprofile override enabled and 2 user groups on NPS, one to assign super_admin profile, 2nd - readonly profile
- Specific (not wildcard) user with access profile assigned on Fortinet device
- Specific (not wildcard) user with access profile assigned by FGT AND Group Matching on Fortigate side
- References
Intro
Removing locally stored passwords from the Fortinet devices is a good step in securing the admin access. While you have to keep at least one local admin-level user for disaster recovery scenarios, the day-to-day changes are best being done by admins authenticated remotely via LDAP/TACACS+/LDAP. In this post I wll show how to do it in FGT/FAZ/FMG against RADIUS server. The RADIUS server will be Windows Server 2019 NPS.
Decide whether to use Wildcard user on FAZ/FMG/FGT or only specific users.
Fortinet created a special setting in the administrator users config - Wildcard user authentication, which in GUI is usually called Match all users on remote server.
When you choose the Wildcard user it means Fortinet device is NOT aware of any usernames at all, all users and their passwords are stored on the remote RADIUS server. And if the RADIUS server authenticates any user successfully, FGT/FAZ/FMG will be happy as well and will assign the access profile set for the Wildcard User, or the one sent by RADIUS.
The advantage of the Wildcard User is that we do not need to manage users on the device - disabling/removing/adding - all is being done on RADIUS server. The disadvantage is that if RADIUS server admin makes a mistake and does not restrict what users can authenticate against this FGT/FMG/FA device, ANY valid user on RADIUS server may potentially log in as admin-level user.
The alternative is to use/create specific admin-level users of type RADIUS, that will still check password and autheticate against RADIUS.
Important
|
When there are multiple Wildcard Users configured on the same Fortinet device - the first in the table from top to the bottom match wins. If there are both - specific/individual and Wildcard users present - the specific users always match first, and only after that the Wildcard is tried. |
Additionally, we have to decide whether to enable profile override - when this option is enabled, the profile sent for a user from the RADIUS server overrides the profile set at the Fortinet device. This way we can assign different access profiles to different users, which is desirable.
RADIUS Configuration - Windows NPS
The intial RADIUS configs done on the NPS are the same for all Fortinet devices: Fortigate, FortiManager, and FortiAnalyzer.
Install Network Policy Role (NPS)

Open NPS management console

Integrate NPS with local Active Directory
Note
|
if it is a 1st configuration of NPS, make sure to integrate it with Active Directory (if NPS is installed on DC). |

Create in NPS console RADIUS clients signifying each network device (FGT, FAZ, FMG)
Next, we create RADIUS clients for each Fortinet device that needs to authenticate against this NPS using their IPs and setting shared secret.
Fortigate (10.100.104.13):

FAZ (10.100.104.17):

FMG (10.100.104.252):

Create Connection Request Policy for each client
-
Next, is the Connection Policy. I will be matching on RADIUS Client IPs (i.e. the same IPs I used in RADIUS client creation above) as condition:
FGT




After that just click on Next, as Group membership for users on AD we will specify in Network Policy in the next step, not in the Connection Request Policy.


We create the same Connection Request Policies for FMG and FAZ, and they differ only by RADIUS Client IP.
Create Network Policy for each RADIUS client matching on AD Groups membership for end users
In this AD topology, I created 4 AD users adminad1,…admiad4, then created a new AD Group named AllFGTAdmins and added all 4 users to it. We will next match RADIUS Network Policy on this AD Group, i.e. only members of this AD group will be able to authenticate according to NPS Network Policy. This way we prevent the mistake of allowing ANY valid AD user to authenticate against our Fortinet devices. In later examples of assigning Access Profiles from RADIUS, I will add new Groups and make them more granular.

Here I set as condition in the Network Policy matching on the AD group membership and select just AllFGTAdmins group:

-
Windows 2019 only - there is a bug in this version of Windows that even though it has default Allow rule for incoming RADIUS requests enabled, the Windows Firewall still blocks incoming RADIUS requests from all. The workaround is either to disable Windows Firewall on Server 2019, or create a Custom Inbound Rule for the same ports UDP 1812 (RADIUS) and 1813 (ACCOUNTING). In the screenshot below I created a custom Inbound Rule:

-
Message Authenticator problem - starting with FortiOS 7.2.10, 7.4.5 and 7.6.1 Fortinet hardened their RADIUS handling in the Fortigates to mitigate Blast RADIUS vulnerability (CVE-2024-3596). What was optional (Message-Authenticator attribute) in the RADIUS communication, Fortinet made obligatory, but Server 2019 NPS does NOT have it enabled by default and thus any RADIUS authentication attempt will be dropped by the Fortigate.
Running dia deb app fnbamd -1, dia deb en will show the following error:
rad_udp_recv-Recved 250 bytes. Buf sz 8192 _rad_chk_resp_authenticator-The Message Authenticator validation is mandatory now _rad_chk_resp_authenticator-No Message Authenticator nbamd_rad_validate_pkt-Invalid digest rad_rxtx-Error validating radius rsp
And if we do packet capture on the Fortigate, we will see that Fortigate does include this Message Authenticator RADIUS attribute, but the response from NPS does not, and as a result - Fortigate drops successfully authenticated user connection.

To fix this, enable the following option in NPS Console:

Note
|
If your Server 2019 is not regularly updated, enabling this option will be not enough - you have to have security patches from Microsoft installed as well, see https://support.microsoft.com/en-us/topic/july-9-2024-kb5040430-os-build-17763-6054-0bb10c24-db8c-47eb-8fa9-9ebc06afa4e7 |
Fortigate configuration
Create a RADIUS user to represent the RADIUS server
config user radius edit "RAD1" set server "10.100.104.184" set secret ENC xl1PiA set auth-type ms_chap_v2 // Optional - just make sure the same config on NPS next end
Create a user group to include this RADIUS user
config user group edit "RAdminGroup" set member "RAD1" next end
Create (here) a wildcard admin account and assign RADIUS-containing user group
config system admin edit "RAdmins" set remote-auth enable set accprofile "super_admin" set vdom "root" set password FLDm,bnK>JHDF // To use if RADIUS server is down set wildcard enable set remote-group "RAdminGroup" next end
Wildcard User with dummy accprofile assigned on Fortinet device with override enabled to get actual profile name from the RADIUS
We use Vendor Specifc Attirbute (VSA) of 12356 for the Fortinet as vendor, and the attribute 6 Fortinet-Access-Profile which is a string to list accprofile existing on the Fortinet device (you cannot create accprofile on RADIUS, just send its name). See in the References link to all VSA attributes of Fortinet.
Fortigate
To allow the Access Profile to be overriden, we enable this option on admin user (option exists for regular admin users as well as Wildcard users). Also, as a best practice, we create an empty access profile and assign it to this Wildcard user instead of the "super_admin" I assigned above:
config system accprofile edit "noaccess" next end
config system admin edit "RAdmins" set remote-auth enable set accprofile "noaccess" set vdom "root" set wildcard enable set remote-group "RAdminGroup" set accprofile-override enable <-- ENABLE OVERRIDE next end
User Group containing the RADIUS object:
config user group edit "RAdminGroup" set member "RAD1" next end
Now let’s set VSA 6 on NPS to the accprofile name of super_admin:

And trying successfully to log in with user adminad4 I get the correct super_admin profile from the RADIUS server sent VSA Attribute 6:
[1216] fnbamd_rad_validate_pkt-RADIUS resp code 2 [912] __rad_rxtx- [1286] fnbamd_rad_process-Result from radius svr 'RAD1' is 0, req 11553634668545 [545] fnbamd_rad_get_vsas-FORTINET attr, type 6, val super_admin
-
Debug (dia deb fnbamd -1)
Before doing any debug we have to understand what messages RADIUS exchanges, what they mean and such as debug lists numeric codes only.
Most popular RADIUS request/response messages/codes as per RFC:
Code | Description |
---|---|
1 |
Access-Request, sent by RADIUS client to the server to authenticate a user. |
2 |
Access-Accept, response from RADIUS server when authenticaiton is successful. |
3 |
Access-Reject, response from RADIUS server when auth has failed. |
4 |
Accounting-Request, request from client to server to start Accounting. |
5 |
Accounting-Response, response to ACK the accounting request |
11 |
Access-Challenge, sent by server to request additional info - usually MFA. |
40 |
Disconnect-Request, sent by the RADIUS server to the client in order to terminate a user session, more relevant to switches/WiFi and IEEE 802.1X. |
41 |
Disconnect-Response, ACK by the RADIUS client to the server. |
43 |
Change-of-Authorization Request (CoA), sent by RADIUS to the client, and contain information for dynamically changing session authorizations. |
44 |
CoA-Response. |
Debug output of successful login with user adminad1
with Wildcard admin user:
FGT-Perimeter # [1757] handle_req-Rcvd auth req 10020305883137 for adminad1 in opt=00014001 prot=9 svc=6 [333] __compose_group_list_from_req-Group 'RAdminGroup', type 1 <-- FOUND USER GROUP WITH RADIUS [508] create_auth_session-Session created for req id 10020305883137
Next FGT is counting all other remote servers configured (none in this case) until reaches RAD1
RADIUS server
10.100.104.184 using MS-CHAP2 (configured, not default) and authenticates against it:
[590] fnbamd_cfg_get_tac_plus_list- [425] __fnbamd_cfg_get_tac_plus_list_by_admin- [606] fnbamd_cfg_get_tac_plus_list-Total tac+ servers to try: 0 [840] fnbamd_cfg_get_ldap_list- [613] __fnbamd_cfg_get_ldap_list_by_admin- [856] fnbamd_cfg_get_ldap_list-Total LDAP servers to try: 0 [416] ldap_start-Didn't find ldap servers [316] radius_start-eap_local=0 [896] fnbamd_cfg_get_radius_list- [675] __fnbamd_cfg_get_radius_list_by_admin- [456] fnbamd_rad_get-vfid=0, name='RAD1' [805] __rad_auth_ctx_insert-Loaded RADIUS server 'RAD1' [663] __add_admin_rad_svr-Loaded RADIUS server 'RAD1' for admin user 'RAdmins' [818] __rad_auth_ctx_insert_all_usergroup- [918] fnbamd_cfg_get_radius_list-Total rad servers to try: 1 [1025] fnbamd_cfg_radius_clear_reachability-Clearing RAD server reachability RAD1:10.100.104.184 [936] fnbamd_rad_get_auth_server- [1172] fnbamd_rad_auth_ctx_init-User ha_relay? 0. [295] fnbamd_radius_get_next_auth_prot-Next auth prot MS-CHAPv2 [1107] __auth_ctx_svr_push-Added addr 10.100.104.184:1812 from rad 'RAD1' [930] __fnbamd_rad_get_next_addr-Next available address of rad 'RAD1': 10.100.104.184:1812. [1125] __auth_ctx_start-Connection starts RAD1:10.100.104.184, addr 10.100.104.184:1812 proto: UDP [280] __rad_udp_open-Opened radius socket 10, sa_family 2 [945] __rad_conn_start-Socket 10 is created for rad 'RAD1'. [807] __rad_add_job_timer- [439] fnbamd_cfg_get_pop3_list- [417] __fnbamd_cfg_get_pop3_list_by_group- [422] __fnbamd_cfg_get_pop3_list_by_group-Group 'RAdminGroup' [449] fnbamd_cfg_get_pop3_list-Total pop3 servers to try: 0 [434] start_remote_auth-Total 1 server(s) to try [1900] handle_req-r=4 [828] __rad_rxtx-fd 10, state 1(Auth) [830] __rad_rxtx-Stop rad conn timer. [837] __rad_rxtx- [605] fnbamd_rad_make_access_request-
Composes Access-Request (code 1) message to the RADIUS server, using default (not set to custom) source IP, UDP , to the default port 1812:
[328] __create_access_request-Compose RADIUS request [588] __create_access_request-Created RADIUS Access-Request. Len: 215. [1171] fnbamd_socket_update_interface-vfid is 0, intf mode is 0, intf name is , server address is 10.100.104.184:1812, source address is null, protocol number is 17, oif id is 0 [353] __rad_udp_send-oif=0, intf_sel.mode=0, intf_sel.name= [868] __rad_rxtx-Sent radius req to server 'RAD1': fd=10, IP=10.100.104.184(10.100.104.184:1812) code=1 id=3 len=215 [877] __rad_rxtx-Start rad conn timer. [828] __rad_rxtx-fd 10, state 1(Auth) [830] __rad_rxtx-Stop rad conn timer. [880] __rad_rxtx- [431] __rad_udp_recv-Recved 268 bytes. Buf sz 8192
Adds attribute Message Autenticator:
[1125] __rad_chk_resp_authenticator-The Message Authenticator validation is mandatory now [1148] __rad_chk_resp_authenticator-ret=0
RADIUS server response is success: code 2 (ACCESS-ACCEPT):
[1216] fnbamd_rad_validate_pkt-RADIUS resp code 2 [912] __rad_rxtx-
Next is the FNBAMD daemon final result (see table below for values, 0 = success)
[1286] fnbamd_rad_process-Result from radius svr 'RAD1' is 0, req 10020305883137 [868] fnbamd_radius_parse_mschapv2_attr-Decoding TYPE_MS_MPPE_Recv_Key [791] __radius_decode_mppe_key-Key len after decode 16 [879] fnbamd_radius_parse_mschapv2_attr-Decoding TYPE_MS_MPPE_Send_Key [791] __radius_decode_mppe_key-Key len after decode 16 [1485] fnbamd_rad_process-Challenged: 0, FTK_Challenge: 0, CHG_PWD: 0, Invaid_Digest: 0, State_Len: 0 [627] fnbam_user_auth_group_match-req id: 10020305883137, server: RAD1, local auth: 0, dn match: 0 [206] find_matched_usr_grps-Passed group matching [909] update_auth_token_session-config does not require 2fa [239] fnbamd_comm_send_result-Sending result 0 (nid 0) for req 10020305883137, len=2641 [600] destroy_auth_session-delete session 10020305883137 [1347] fnbamd_rads_destroy- [516] fnbamd_rad_auth_ctx_free-Freeing 'RAD1' ctx
FNBAMD authentication daemon response codes in the debug:
Code | Description |
---|---|
0 |
Success |
1 |
Deny |
2 |
Challenged (password renewal or token is needed) |
3 |
unknown |
4 |
Pending |
5 |
Error |
6 |
Framed IP Conflict |
7 |
Token code is required |
8 |
Need another token due to the previous one is out of sync |
9 |
Response Buffer is too small |
10 |
Authentication time out |
11 |
Max Concurrent authentication sessions are reached |
12 |
Token code is already used. |
-
Debug of failed authentication
Here I am using the user adminad5
which exists in AD, and password is correct BUT he is not part of the FGTAllAdmins
AD group on the RADIUS server. And therefore, will not match the Network Policy of the RADIUS NPS on Server 2019 and thus NPS will reject it.
Intial process is the same as the above example of successful authentication, up to getting aresponse from the RADIUS:
[1757] handle_req-Rcvd auth req 10269421789186 for adminad5 in opt=00014001 prot=9 svc=6 [333] __compose_group_list_from_req-Group 'RAdminGroup', type 1 [508] create_auth_session-Session created for req id 10269421789186 [590] fnbamd_cfg_get_tac_plus_list- [425] __fnbamd_cfg_get_tac_plus_list_by_admin- [606] fnbamd_cfg_get_tac_plus_list-Total tac+ servers to try: 0 [840] fnbamd_cfg_get_ldap_list- [613] __fnbamd_cfg_get_ldap_list_by_admin- [856] fnbamd_cfg_get_ldap_list-Total LDAP servers to try: 0 [416] ldap_start-Didn't find ldap servers [316] radius_start-eap_local=0 [896] fnbamd_cfg_get_radius_list- [675] __fnbamd_cfg_get_radius_list_by_admin- [456] fnbamd_rad_get-vfid=0, name='RAD1' [805] __rad_auth_ctx_insert-Loaded RADIUS server 'RAD1' [663] __add_admin_rad_svr-Loaded RADIUS server 'RAD1' for admin user 'RAdmins' [818] __rad_auth_ctx_insert_all_usergroup- [918] fnbamd_cfg_get_radius_list-Total rad servers to try: 1 [936] fnbamd_rad_get_auth_server- [1172] fnbamd_rad_auth_ctx_init-User ha_relay? 0. [295] fnbamd_radius_get_next_auth_prot-Next auth prot MS-CHAPv2 [1107] __auth_ctx_svr_push-Added addr 10.100.104.184:1812 from rad 'RAD1' [930] __fnbamd_rad_get_next_addr-Next available address of rad 'RAD1': 10.100.104.184:1812. [1125] __auth_ctx_start-Connection starts RAD1:10.100.104.184, addr 10.100.104.184:1812 proto: UDP [280] __rad_udp_open-Opened radius socket 10, sa_family 2 [945] __rad_conn_start-Socket 10 is created for rad 'RAD1'. [807] __rad_add_job_timer- [439] fnbamd_cfg_get_pop3_list- [417] __fnbamd_cfg_get_pop3_list_by_group- [422] __fnbamd_cfg_get_pop3_list_by_group-Group 'RAdminGroup' [449] fnbamd_cfg_get_pop3_list-Total pop3 servers to try: 0 [434] start_remote_auth-Total 1 server(s) to try [1900] handle_req-r=4 [828] __rad_rxtx-fd 10, state 1(Auth) [830] __rad_rxtx-Stop rad conn timer. [837] __rad_rxtx- [605] fnbamd_rad_make_access_request- [328] __create_access_request-Compose RADIUS request [588] __create_access_request-Created RADIUS Access-Request. Len: 215. [1171] fnbamd_socket_update_interface-vfid is 0, intf mode is 0, intf name is , server address is 10.100.104.184:1812, source address is null, protocol number is 17, oif id is 0 [353] __rad_udp_send-oif=0, intf_sel.mode=0, intf_sel.name= [868] __rad_rxtx-Sent radius req to server 'RAD1': fd=10, IP=10.100.104.184(10.100.104.184:1812) code=1 id=5 len=215 [877] __rad_rxtx-Start rad conn timer. [828] __rad_rxtx-fd 10, state 1(Auth) [830] __rad_rxtx-Stop rad conn timer. [880] __rad_rxtx- [431] __rad_udp_recv-Recved 60 bytes. Buf sz 8192 [1125] __rad_chk_resp_authenticator-The Message Authenticator validation is mandatory now [1148] __rad_chk_resp_authenticator-ret=0
What differs is the RADIUS server response - here it is 3 (ACCESS-REJECT), also FNBAMD daemon final result is 1 (DENY):
[1216] fnbamd_rad_validate_pkt-RADIUS resp code 3 [624] fnbamd_rad_extract_chap_error-CHAP err: E=649 R=0 V=3 [1028] __rad_error-Ret 1, st = 1. [295] fnbamd_radius_get_next_auth_prot-Next auth prot ?? [1077] __rad_error- [306] __rad_udp_close-closed. [964] __rad_conn_stop-Stop rad conn timer. [1286] fnbamd_rad_process-Result from radius svr 'RAD1' is 1, req 10269421789186
FortiAnalyzer
-
Create RADIUS user to set parameters for communication with the RADIUS server:
config system admin radius edit "RAD-184" set server "10.100.104.184" set secret ENC NTEwNjAxNDMzN set auth-type mschap2 next end
-
Create a Wildcard admin-level user, set profile to built-in profile w/o actual permissions, set ADOM to "all", to be later overridden by the RADIUS server response (as a best practice option you could create a new ADOM w/o any devices in it and use this ADOM as default log-in ADOM):
config system admin user edit "RAwildcard" set profileid "No_Permission_User"<-- BUILT-IN PROFILE set adom-access all set user_type radius set radius_server "RAD-184" config meta-data edit "Contact Email" next edit "Contact Phone" next end set wildcard enable set ext-auth-accprofile-override enable set ext-auth-adom-override enable next end
FortiManager
The config in FMG is pretty much identical to the FAZ, so I will only show this example.
-
Create RADIUS server
config system admin radius edit "RAD1" set server "10.100.104.184" set secret ENC MTUxMTg4NTA set auth-type mschap2 next end
Or in GUI System Settings → Remote Authentication:

-
Create Wildcard user

config system admin user edit "RAWildcard" set profileid "No_Permission_User" set adom-access all set policy-package "all_policy_packages" set policy-block "all_policy_blocks" set user_type radius set radius_server "RAD1" config meta-data edit "Contact Email" next edit "Contact Phone" next end set wildcard enable set ext-auth-accprofile-override enable set ext-auth-adom-override enable next end
And the same drill - create NPS Policy on RADIUS server to send FMG at least VSA Attribute 6 - name of the access profile, and possibly VSA Attribute 3 - ADOM name.
-
Debug on FMG dia deb app auth 8
connecting to server 0: 10.100.104.184 ip=10.100.104.184 port=1812/udp send request: type=mschap2 id=35 got reply: code=accept(2) id=35 Message-Authenticator: len=16 Ftnt-Profile: Super_User Ftnt-Adom: root 0-7: len=4 0-6: len=4 0-25: len=44 311-17: len=34 311-16: len=34 311-26: pS=EB01A13608E95CC4F996F80FD2CE58D3665C1DAB 311-10: pARGO success success
Additional logs on authentication failure can be found in System Settings → Event Logs, but they are not very detailed.
Here is example of successful and failed logins:

Wildcard user with accprofile override enabled and 2 user groups on NPS, one to assign super_admin profile, 2nd - readonly profile
As the decision what accprofile to assign to a user based on user’s group membership in AD is done totally on the NPS side, all configs are being done on NPS side. The Fortinet device side uses the regular Wildcard user with accprofile override enabled.
Fortigate
NPS configs. Here I create 2 Network Policies - FGT-readonly and FGT-superadmin. The 1st will assign any user in the AD Group FGTreadonly the accprofile (via VSA Attribute) "readonly" located on the Fortigate already. Users in the AD group FGTsuperadmin, after authentication will get profile "super_admin". To the FGTreadonly group I added only adminad5 user, and to the FGTsuperadmin AD Group adminad4, adminad3 etc.
-
NPS, FGT-readonly policy:


-
NPS, FGT-superadmin policy:


FortiManager
For this and the next example I will only show Fortianalyzer configs as in both cases the configuration is the same for both FAZ & FMG.
Fortianalyzer
The NPS side is the same as for FGT - create 2 new Network Policies with Conditions of RADIUS Client IP (FAZ) and user group membership, sending for each policy different accprofile name via VSA Attribute 6 - "readonly" and "Super_User" (there is no "super_admin" profile in FAZ unless you create a custom one with that name).
-
readonly Network Policy of NPS for FAZ:


-
super_user Network Policy of NPS:

Fortianalyzer with overriding not only accprofile but ADOM of the user as well
Fortinet have additional helpful VSA Attribute - 3 Fortinet-Vdom-Name which when sent from RADIUS can be used by Fortigate/FAZ/FMG/etc to override the default VDOM/ADOM the user can access.
NPS: For this I created a new AD Group "FAZ-syslogadom" that contains only adminad8 user. I create then new Network Policy to match FAZ IP and this AD Group. And finally, I set not only VSA Attribute 6 - accprofile, but also VSA Attribute 3 - ADOM name to "Syslog" to be sent by RADIUS server.
Note
|
As I want to assign this user write/read full rights BUT to the specific ADOM he has been assigned to, I have to create a new accprofile where "ADOM" settings is "Read only", so this user cannot change to a different ADOM after log in. If I were to assign it the built-in "Super_User" profile, this would allow the user to change to another ADOM freely. |
Here is the accprofile I created:

And on CLI:
config system admin profile edit "ADOMSuper_User" set system-setting read-write set adom-switch read set device-manager read-write set device-op read-write set device-wan-link-load-balance read-write set device-ap read-write set device-fortiswitch read-write set device-fortiextender read-write set adom-lock read-write set device-policy-package-lock read-write set extension-access read-write set log-viewer read-write set fabric-viewer read-write set report-viewer read-write set event-management read-write set update-incidents read-write set triage-events read-write set run-report read-write set execute-playbook read-write set script-access read-write set fgt-gui-proxy disable set ips-lock none next end

FAZ Debug (dia deb app auth -1)
Case 1: Debug of successful authentication with the user adminad7 getting "readonly" profile with access to all ADOMs:
FAZ-AWS # diagnose debug application auth -1 FAZ-AWS # dia deb enab FAZ-AWS # s9: auth request: user=adminad7 from=GUI(10.100.104.13) s9: wildcard admin: RAwildcard s9: start radius: RAD-184 s9:RAD-184: connect to server 0: 10.100.104.184 ip=10.100.104.184 port=1812 s9:RAD-184: send request: type=mschap2 id=6 s9:RAD-184: got reply: code=accept(2) id=6 s9:RAD-184: 0-80: jZ9:RAD-184: ftnt-profile: readonly s9:RAD-184: 0-7: len=4 s9:RAD-184: 0-6: len=4 s9:RAD-184: 0-25: len=44 s9:RAD-184: 311-17: len=34 s9:RAD-184: 311-16: len=34 s9:RAD-184: 311-26: 7S=55F620A3763E7D99149FFBCC96AEDF195E6C862E s9:RAD-184: 311-10: 7ARGO s9:RAD-184: success s9: profile from server: readonly s9: wildcard admin matched: RAwildcard s9: profile-override: readonly s9: no adom from server, use adoms in admin setting s9: auth result: success
-
Case 2: Here I mis-spelled access profile name "super_user" instead of "Super_User" and got an error that such profile does not exist on FAZ and user log in was rejected:
s11: auth request: user=adminad4 from=GUI(10.100.104.13) s11: wildcard admin: RAwildcard s11: start radius: RAD-184 s11:RAD-184: connect to server 0: 10.100.104.184 ip=10.100.104.184 port=1812 s11:RAD-184: send request: type=mschap2 id=8 s11:RAD-184: got reply: code=accept(2) id=8 s11:RAD-184: 0-80: len=16 s11:RAD-184: ftnt-profile: super_user s11:RAD-184: 0-7: len=4 s11:RAD-184: 0-6: len=4 s11:RAD-184: 0-25: len=44 s11:RAD-184: 311-17: len=34 s11:RAD-184: 311-16: len=34 s11:RAD-184: 311-26: 689AEA94593EF06B7659C41254F31B68A85D628 s11:RAD-184: 311-10: O s11:RAD-184: success s11: profile from server: super_user (invalid) s11: wildcard admin matched: RAwildcard s11: no valid profile from server s11: auth result: denied
-
Case 3: Debug of successful log in of adminad8 getting accprofile ADOMSuper_User and being forced to the ADOM "Syslog":
s15: auth request: user=adminad8 from=GUI(10.100.104.13) s15: wildcard admin: RAwildcard s15: start radius: RAD-184 s15:RAD-184: connect to server 0: 10.100.104.184 ip=10.100.104.184 port=1812 s15:RAD-184: send request: type=mschap2 id=12 s15:RAD-184: got reply: code=accept(2) id=12 s15:RAD-184: 0-80: len=16 s15:RAD-184: ftnt-adom: Syslog s15:RAD-184: ftnt-profile: ADOMSuper_User s15:RAD-184: 0-7: len=4 s15:RAD-184: 0-6: len=4 s15:RAD-184: 0-25: len=44 s15:RAD-184: 311-17: len=34 s15:RAD-184: 311-16: len=34 s15:RAD-184: 311-26: 12AC271969CF7E420358CD1B621D7022BAA5352 s15:RAD-184: 311-10: O s15:RAD-184: success s15: profile from server: ADOMSuper_User s15: wildcard admin matched: RAwildcard s15: profile-override: ADOMSuper_User s15: adom-override: Syslog s15: auth result: success
Specific (not wildcard) user with access profile assigned on Fortinet device
When creating individual users on Fortinet device it is logical to assign them the needed access profile as well.
I create a new Network Policy on Server 2019 here to all ALL Domain Users to be able to authenticate to simplify the case (the Group matching on NPS would work as well).

And I disabled the NPS policy matching on AllFGTAdmins group in AD (moving it down would still leave it active and match on it).
Next, I remove the Wildcard admin account on Fortigate to prevent the case of ANY Domain User connecting as admin (the new user would NOT use this Wildcard anyway, but for security sake). The alternative would be to create NPS Policy for a specific AD Group of which this user is member of:
config sys admin del RAdmins
And create a new admin user adminad5 to be authenticated against NPS:
config system admin edit "adminad5" set remote-auth enable set accprofile "super_admin" set vdom "root" set remote-group "RAdminGroup" set password ENC SH2cnkEXtY next end
Verifying on CLI:
FGT-Perimeter # diagnose test authserver radius RAD1 mschap2 adminad5 secr3t authenticate 'adminad5' against 'mschap2' succeeded, server=primary assigned_rad_session_id=9771184754689 session_timeout=0 secs idle_timeout=0 secs!
Specific (not wildcard) user with access profile assigned by FGT AND Group Matching on Fortigate side
RADIUS has no notion of Groups on Fortinet device, but we do have an option to use VSA Fortinet-specific Attribute Fortinet-Group-Name code 1 as a String - we just set in Network Policy of NPS for matching conditions to send some custom string (doesn’t have to match the user’s Group in AD) which Fortigate will match to the string we configure in Fortigate as well. If the string in FGT matches the string the RADIUS sends when a user successfully autheticated, Fortigate will allow it as well. When using this feature with VPN Groups on Fortigate, it makes sense to match the existing groups exactly.
Config on the NPS side steps:

Configure "group" matching on the Fortigate, remember - it is just string against string matching, also it is case-sensitive:
config user group edit "RAdminGroup" set member "RAD1" config match edit 1 set server-name "RAD1" set group-name "FGTADMINS" next end next end
Debug (excerpts only, as much of it is the same as above):
User adminad5 matches RADIUS User Group on the FGT:
[1757] handle_req-Rcvd auth req 10265108312068 for adminad5 in [333] __compose_group_list_from_req-Group 'RAdminGroup', type 1 [456] fnbamd_rad_get-vfid=0, name='RAD1' [805] __rad_auth_ctx_insert-Loaded RADIUS server 'RAD1' [663] __add_admin_rad_svr-Loaded RADIUS server 'RAD1' for admin user 'adminad5'
RADIUS response (success):
[1125] __rad_chk_resp_authenticator-The Message Authenticator validation is mandatory now [1148] __rad_chk_resp_authenticator-ret=0 [1216] fnbamd_rad_validate_pkt-RADIUS resp code 2
AFTER successfully authenticating the user adminad5 by RADIUS, next step is to match on the string sent as VSA Attribute - these actions are independent, RADIUS may send SUCCESS but then FGT will fail user if the VSA Attribute doesn’t match:
[1286] fnbamd_rad_process-Result from radius svr 'RAD1' is 0, req 10265108312068 [502] fnbamd_rad_get_vsas-FORTINET attr, type 1, val FGTADMINS [868] fnbamd_radius_parse_mschapv2_attr-Decoding TYPE_MS_MPPE_Recv_Key [791] __radius_decode_mppe_key-Key len after decode 16 [879] fnbamd_radius_parse_mschapv2_attr-Decoding TYPE_MS_MPPE_Send_Key [791] __radius_decode_mppe_key-Key len after decode 16 [1485] fnbamd_rad_process-Challenged: 0, FTK_Challenge: 0, CHG_PWD: 0, Invaid_Digest: 0, State_Len: 0 [627] fnbam_user_auth_group_match-req id: 10265108312068, server: RAD1, local auth: 0, dn match: 0 [581] __group_match-Check if RAD1 is a group member [587] __group_match-Group 'RAdminGroup' passed group matching [590] __group_match-Add matched group 'RAdminGroup'(3)
-
Example of failed login on group-name string mismatch. Below is debug of when I intentionally put group-name on FGT in lower case, while it is upper case on RADIUS:
edit "RAdminGroup" set member "RAD1" config match edit 1 set server-name "RAD1" set group-name "fgtadmins" next end next end
Pay attention to the RADIUS response code - 2 (success), but in the 2nd step of matching the string, FGT fails the user:
[1216] fnbamd_rad_validate_pkt-RADIUS resp code 2 [912] __rad_rxtx- [1286] fnbamd_rad_process-Result from radius svr 'RAD1' is 0, req 10265108312067 [502] fnbamd_rad_get_vsas-FORTINET attr, type 1, val FGTADMINS [868] fnbamd_radius_parse_mschapv2_attr-Decoding TYPE_MS_MPPE_Recv_Key [791] __radius_decode_mppe_key-Key len after decode 16 [879] fnbamd_radius_parse_mschapv2_attr-Decoding TYPE_MS_MPPE_Send_Key [791] __radius_decode_mppe_key-Key len after decode 16 [1485] fnbamd_rad_process-Challenged: 0, FTK_Challenge: 0, CHG_PWD: 0, Invaid_Digest: 0, State_Len: 0 [627] fnbam_user_auth_group_match-req id: 10265108312067, server: RAD1, local auth: 0, dn match: 0 [581] __group_match-Check if RAD1 is a group member [209] find_matched_usr_grps-Failed group matching
Fortianalyzer
FAZ also has the option of matching on Group Name sent from RADIUS. It is useful when using wildcard users and authenticating against the same NPS server - we cannot in such case allow any Domain Users as matching condition in NPS Policy, as this would allow any AD users that do not exist on FAZ but do exist in AD to authenticate.
Task: create RADIUS-authenticated user adminad9 on FAZ, when it connects assign it profile ADOMSuper_User and limit his access to the FGT-only ADOM.
So for this, I create user adminad9 on both FAZ and AD. I create a new AD Group FGT-only-adom which will have as a member just user adminad9. And then create NPS Policy matching user on AD Group FGT-only-adom and sending with the response also Fortinet VSA Attribute 1 Group-Name to be additional match on the FAZ side.
-
User adminad9 on the FAZ:
Using the same RADIUS server:
config system admin radius edit "RAD-184" set server "10.100.104.184" set secret ENC MTY2NTg3Nj set auth-type mschap2 next end
The user with the matching condition of string "FGT-only":
FAZ-AWS # show sys admin user adminad9 config system admin user edit "adminad9" set profileid "ADOMSuper_User" set adom-access specify set adom "FGT-only" (1) set dev-group "FGT-Perimeter-firewalls" (2) set user_type radius set radius_server "RAD-184" config meta-data edit "Contact Email" next edit "Contact Phone" next end set ext-auth-group-match "FGT-only" (3) set use-global-theme disable set user-theme autumn (4) next end
-
Limit to this ADOM only
-
(Opt) Inside the ADOM, limit access to this device group only
-
Match on this string sent as VSA Attribute "Group-Name", fail if no match
-
(Opt) Set the GUI Theme for this user
-
NPS Policy:
-


After log in, the user cannot change ADOM, and has Autumn as the theme:

-
Debug
s16: auth request: user=adminad9 from=GUI(10.100.104.13) s16: found admin: adminad9 s16: start radius: RAD-184 s16:RAD-184: connect to server 0: 10.100.104.184 ip=10.100.104.184 port=1812 s16:RAD-184: send request: type=mschap2 id=13 s16:RAD-184: got reply: code=accept(2) id=13 s16:RAD-184: 0-80: len=16 s16:RAD-184: ftnt-group: FGT-only <-- GROUP-NAME SENT FROM RADIUS s16:RAD-184: 0-7: len=4 s16:RAD-184: 0-6: len=4 s16:RAD-184: 0-25: len=44 s16:RAD-184: 311-17: len=34 s16:RAD-184: 311-16: len=34 s16:RAD-184: 311-26: GS=9ACFB7F404F0530F90AE097C95C0A69B119B250D s16:RAD-184: 311-10: GARGO s16:RAD-184: success s16: auth result: success
References
I also write cheat sheets/scripts/guides to help in daily work, so make sure to check out my Github at https://github.com/yuriskinfo and https://www.linkedin.com/in/yurislobodyanyuk/