Fortinet FortiGate
This page covers administrative access to a FortiGate over TACACS+. It is the device-side counterpart to TACACS+.
FortiGate is the odd one out in this cookbook, and it is worth saying why before any configuration appears.
Verified on
Section titled “Verified on”| Platform | Software | What was verified |
|---|---|---|
| FortiGate-VM64 | FortiOS v7.6.7 build 3704 (GA) | TACACS+ authentication and authorization, admin-profile assignment, group matching, wildcard remote admin, single VDOM (root), NAT mode, standalone |
RADIUS administrative login is also supported. The seeded Fortinet FortiGate RADIUS
template returns a single mandatory attribute — Fortinet-Group-Name, VSA 1 under
vendor ID 12356 — whose value must name a group configured on the firewall, and defaults
the reply to Service-Type = Login-User with a session timeout of 28800 s and an idle
timeout of 600 s. That path was not part of this test and is not documented further here.
How the pieces fit together
Section titled “How the pieces fit together”FortiGate needs three objects to cooperate, and each one can be individually correct while the chain as a whole fails. Read this before the configuration, because the error messages will not tell you which link broke.
| Object | What it does |
|---|---|
user tacacs+ | The server itself — address, key, source IP, and whether authorization is requested at all |
user group | Ties the group name Taranac returns to a local group the firewall understands |
system admin | The wildcard admin entry that lets unknown-but-authenticated users log in, and decides whether Taranac’s profile choice is honoured |
The login flow runs: authenticate against Taranac → request authorization from Taranac → match the returned group against a local group → apply the returned admin profile.
What Taranac returns
Section titled “What Taranac returns”Taranac’s end of that chain is one TACACS+ profile built on the seeded Fortinet
FortiGate template. It authorizes the fortigate service — not shell — and the
template defines exactly three AV-pairs:
| AV-pair | Sent as | Required | What it carries |
|---|---|---|---|
admin_prof | admin_prof = … | Yes | The admin profile name, which has to exist on that firewall. Template default super_admin |
memberof | memberof = … | No | The group name the config match block in step 2 compares against |
vdom | vdom = … | No, repeatable | The VDOM(s) the admin may enter — one AV-pair per VDOM. Empty means the default VDOM |
There is nothing else. The template declares no command authorization, which is why the
profile form hides its Command Set section for a FortiGate profile, and no enable
support — the Enable section is still on the form (it is not gated on the template), but
FortiOS has no escalation step for it to reach, so anything set there is inert. Everything
the firewall does with the login after that is its own accprofile.
The configuration
Section titled “The configuration”1. The TACACS+ server
Section titled “1. The TACACS+ server”config user tacacs+ edit "TARANAC" set server "10.0.0.20" set key <TACACS_SECRET> set authorization enable set source-ip "10.0.0.11" nextendset key takes the shared secret as plaintext when you type it, and it must equal the
secret on this device’s record in Taranac. A later show prints it back as
set key ENC <blob> — that is the stored form, not something to paste into another
firewall by hand.
set source-ip pins the address the FortiGate uses to reach the server, which is what
Taranac matches against the registered device. If it disagrees with the address on the
device’s entry, the request is dropped as coming from an unknown client and nothing is
written to the Taranac logs. See Network devices.
2. The user group
Section titled “2. The user group”config user group edit "TACACS-ADMINS" set member "TARANAC" config match edit 1 set server-name "TARANAC" set group-name "FGT_access" next end nextendThe match block is the join between the two systems. group-name must equal the value
Taranac returns in the memberof attribute of the FortiGate authorization profile —
here, FGT_access. They are two independently-edited strings in two different products
that must agree exactly, which makes this the most common place for a working setup to
break after someone renames something.
set member "TARANAC" makes the TACACS+ server a member of the group.
3. The wildcard admin
Section titled “3. The wildcard admin”config system admin edit "tacacs-wildcard" set vdom "root" set remote-auth enable set accprofile "super_admin" set remote-group "TACACS-ADMINS" set wildcard enable set accprofile-override enable nextendwildcard enable is what makes this scale: one admin entry serves every user in the
group, instead of a local entry per person. remote-group points at the group from step 2.
4. The authentication timeout
Section titled “4. The authentication timeout”config system global set remoteauthtimeout 30endThis is the FortiGate’s timer for remote authentication, and it is the one to raise for push MFA. Taranac holds the exchange open while the user approves the push on their phone — up to about 30 seconds. FortiOS defaults to a much shorter value, at which the firewall gives up before anyone can reach into a pocket and the login simply fails.
The effective window is the smaller of this value and Taranac’s own server-side cap, so raise both together.
A note on admin profiles
Section titled “A note on admin profiles”config system accprofile edit "prof_admin" set secfabgrp read-write ... set cli-config enable nextendshow system accprofile does not necessarily list every profile that exists —
super_admin was in active use on the tested firewall and does not appear in this output.
Do not conclude from a missing entry that a profile is undefined; the name Taranac returns
only has to be valid on the firewall, not visible here.
Verify it
Section titled “Verify it”FortiGate’s fnbamd daemon handles remote authentication, and its debug output is by far
the most informative diagnostic on this platform — it shows exactly what Taranac returned
and how the firewall interpreted it.
diagnose debug enablediagnose debug application fnbamd -1It self-disables after 30 minutes. Now log in from another session. A successful login produces this (elided to the lines that matter):
[1784] handle_req-Rcvd auth req … for taranac in opt=00014001 prot=9 svc=6[336] __compose_group_list_from_req-Group 'TACACS-ADMINS', type 1[414] __add_admin_tac_plus_svr-Loaded TAC+ server 'TARANAC' for admin user 'tacacs-wildcard'[94] fnbamd_tac_plus_get_next_authen_type-Next authen type pap[389] __tac_plus_tcps_open-… addr 10.0.0.20, src_ip 10.0.0.11 …[300] fnbamd_tac_plus_make_authen_request-Building authen start packet: authen_type=2(pap)[509] fnbamd_tac_plus_validate_authen_reply-TAC+ authen type=2, result=1(pass)[117] __tac_plus_next_state-State: 'Authen' -> 'Author'[435] fnbamd_tac_plus_make_author_request-Building author req packet: authen_type=2(pap)[595] __parse_author_reply_args-arg cnt 3[363] __add_group-Authorization group 'FGT_access'[375] __set_admin_prof-Authorization admin profile 'super_admin'[206] find_matched_usr_grps-Passed group matching[280] fnbamd_comm_send_result-Sending result 0 …Read it as a checklist — each line confirms one link in the chain:
| Line | What it proves |
|---|---|
Loaded TAC+ server … for admin user 'tacacs-wildcard' | The wildcard admin entry was selected |
src_ip 10.0.0.11 | The source address Taranac will match against the device record |
authen … result=1(pass) | The password was accepted |
State: 'Authen' -> 'Author' | set authorization enable is in effect — absent if it is not |
Authorization group 'FGT_access' | Taranac’s memberof value arrived |
Authorization admin profile 'super_admin' | Taranac’s admin_prof value arrived |
Passed group matching | The config match block agreed with the returned group |
Sending result 0 | Success (1 is failure) |
Testing without risking a session
Section titled “Testing without risking a session”diagnose test authserver tacacs+ TARANAC ad_user1 <password>The first argument is the server name as configured, not its address. Passing an IP
returns '10.0.0.20' is not a valid tac_plus server name, which reads like a
configuration fault and is not one.
On success the command ends with the assigned profile. On failure:
authenticate user 'ad_user1' on server 'TARANAC' failedAdmin profile: <none>One wrong password, three rejections
Section titled “One wrong password, three rejections”This is the platform behaviour most likely to surprise you, and it is only visible in the debug output:
Building authen start packet: authen_type=2(pap) → TAC+ authen type=2, result=2(fail)Next authen type mschapBuilding authen start packet: authen_type=5(mschap) → TAC+ authen type=5, result=2(fail)Next authen type chapBuilding authen start packet: authen_type=3(chap) → TAC+ authen type=3, result=2(fail)Next authen type ??When PAP is rejected, FortiGate does not give up — it retries the same credentials as MS-CHAP, then as CHAP, each on its own fresh TCP connection, before declaring failure.
A successful login never starts the cascade — PAP passes on the first exchange and the chain stops there. So the cascade in your logs is always a failure signature, which makes it useful: three rejections with ascending authentication types is a wrong password, not a broken server.
Command accounting
Section titled “Command accounting”FortiGate has no per-command authorization, but it does send per-command accounting — in a shape no other platform in this cookbook uses.
The record arrives under service=fortigate, and the standard cmd attribute holds only a
category word: Config, Show, Diagnose or Execute. The command itself sits in a
separate reason AV-pair, alongside an event naming what kind of record it is:
event=cmd_acct stop_time=… reason="diagnose sys ha status" cmd=Diagnoseevent=sys_acct stop_time=… reason="Edit firewall.address 2.2.2.2" cmd=ConfigRead literally, every FortiGate command in the accounting log would read Diagnose or
Config — which is exactly what it did until 1.2.1. Taranac now recognises a FortiGate
record from service=fortigate in the AV-pairs alone, with no database lookup, and uses the
reason value as the command — in the log views and in the syslog export alike. A record
that carries no reason (a login_acct event, for one) keeps its category word rather than
being blanked.
Worth noticing in that second line: FortiGate reports configuration changes through the
same channel, so the accounting log on this platform contains change detail —
Edit firewall.address 2.2.2.2 — that most platforms never send at all.
FortiGate as an 802.1X authenticator
Section titled “FortiGate as an 802.1X authenticator”Taranac’s NAC vendor dictionary carries a fortinet entry — Fortinet FortiGate /
FortiSwitch, vendor ID 12356 — so the platform can also be used as an 802.1X authenticator
against Taranac’s RADIUS side. None of it was exercised in the test above; the table below is
what the dictionary declares, not what has been verified here.
| What | How Taranac encodes it |
|---|---|
| VLAN | Tunnel-Type / Tunnel-Medium-Type / Tunnel-Private-Group-ID |
| Named ACL | Filter-Id |
| Session timeout | Session-Timeout + Termination-Action = RADIUS-Request |
| VLAN change | A real CoA-Request carrying the tunnel triplet |
| Re-authentication | A Disconnect. The entry declares no native CoA reauth, so the endpoint reconnects instead of re-authenticating in place |
| Port bounce · port disable | Unsupported — nothing is sent |
| Downloadable ACL · URL redirect | Not declared. URL redirect is declared by Cisco IOS / IOS-XE alone |
Neither of those last two rows is a gap peculiar to FortiGate. vlan_change is a real
CoA-Request on all sixteen vendors in the dictionary — the one near-universal native
action — while native coa_request re-authentication is declared by three entries only:
Cisco IOS / IOS-XE, Cisco NX-OS and Juniper. FortiGate is not among them, so Re-authenticate
in a NAC policy resolves to a Disconnect here and the endpoint has to come back on its own.
Which entry a request is answered with is resolved in this order: the dictionary entry pinned
on the device record, then auto-detection from a vendor attribute in the request (for this
entry, Fortinet-Group-Name), then the device’s free-text Vendor field, then the generic
RFC entry. Pinning it on the device is the only one of those that is deterministic.
What is not yet verified
Section titled “What is not yet verified”- RADIUS administrative login. The seeded template is described above; the path itself was not exercised.
- Multi-VDOM. Everything here was verified on a single VDOM (
root). The repeatablevdomAV-pair has not been tested against a multi-VDOM firewall. - 802.1X. The
fortinetdictionary entry has not been exercised against a FortiGate or a FortiSwitch — the table above is a declaration, not a result. - The device-side accounting switch. The accounting records above came from a production firewall; which FortiOS setting turns them on was not part of the rebuild on the VM.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Likely cause |
|---|---|
Everyone logs in as super_admin regardless of policy | accprofile-override disabled, so the admin entry’s local accprofile wins. Or authorization disabled on the server, so no profile is ever requested. |
Login works, no Author phase in the debug | set authorization enable missing on the user tacacs+ entry. |
| Login rejected, nothing in the Taranac logs | source-ip does not match the address registered for this device. |
Passed group matching never appears | The group-name in the config match block does not equal Taranac’s memberof value — or the template still spells the attribute member_of (pre-1.2.2). |
| Push MFA always fails | remoteauthtimeout too low — raise it to 30 and match the server-side cap. |
| MFA prompt never appears | Expected: PAP has no second step. Use concatenated password+OTP, or push. |
is not a valid tac_plus server name | diagnose test authserver takes the server’s configured name, not its IP. |
| Three failed auths per bad password | Expected — the PAP → MS-CHAP → CHAP cascade. |
Unknown action 0 on every command | You are inside a config context. end first, or use show <path> from the root prompt. |
Authentication succeeds and no admin_prof ever arrives, on Taranac 1.1.1 or earlier | The profile is built on a non-shell vendor template, and the deployed daemon config reduced it to a shell / privilege-15 block. Fixed in 1.1.2. |
Accounting shows Config / Show / Diagnose / Execute where the command should be | Pre-1.2.1 behaviour — or a TACACS+ configuration that has not been generated and deployed again since the upgrade. |
| You cannot find where to set an enable secret for FortiGate | There is nowhere: FortiOS has no separate escalation step, the profile arrives with the login, and the template declares no enable support. Taranac’s $enab<N>$ escalation handling (1.2.5) covers Cisco IOS / IOS-XE, Cisco Business, H3C Comware 7 and Eltex ESR — never this platform. |
Related
Section titled “Related”- Device configuration — conventions and the rest of the cookbook
- Cisco IOS / IOS-XE — a platform with per-command authorization
- Network devices — registering the device and its secret
- TACACS+ — profiles and templates
- AAA policy — the rules that decide which profile a login gets
- AAA logs — where the accounting records above are read
- NAC policy — the vendor dictionary and how a CoA is delivered