Why AAA Is Non-Negotiable on Managed Infrastructure
If your network devices still rely on a shared enable password and a local username list, you’re one leaked credential away from a very bad day. AAA—Authentication, Authorization, and Accounting—is the framework that separates professional network management from the kind of setup that gets audited (and not in a good way).
In this guide, I’m walking through a complete AAA deployment on Cisco IOS-XE using TACACS+ as the protocol and Cisco Identity Services Engine (ISE) as the policy server. We’ll cover everything from initial router configuration to ISE shell profiles and command authorization sets, plus the accounting config that gives you a full audit trail. Real CLI output included.
If you’re new to the Cisco ecosystem, you might want to review the differences between IOS, IOS-XE, and IOS-XR before diving in—some of the AAA syntax diverges between platforms.
AAA Concepts in 30 Seconds
Authentication: Who are you? Validates identity via credentials.
Authorization: What can you do? Controls access based on role.
Accounting: What did you do? Logs all activity for audit.
Two protocols dominate enterprise AAA:
- TACACS+ (TCP/49): Separates auth/authz/accounting into independent functions; encrypts the entire payload; ideal for device administration.
- RADIUS (UDP/1812-1813): Bundles auth and authz; encrypts only the password field; better suited for network access (802.1X, VPN).
For Cisco device administration, TACACS+ wins. Full stop. The granular command authorization and complete packet encryption make it the right tool for the job. ISE supports both, but its device administration policies are TACACS+-specific.
Lab Topology
For this guide:
- Cisco ISE 3.3 (IP: 10.10.10.50) — Policy Administration Node + Policy Service Node (single-node lab)
- Catalyst 9300 running IOS-XE 17.12.x (management IP: 10.10.10.1)
- Management network: 10.10.10.0/24
Step 1: Configure ISE as a TACACS+ Server
Before touching the router, configure ISE. Log into ISE and navigate to Administration → Network Resources → Network Devices. Add your router as a network device with TACACS+ enabled and a shared secret. Remember this secret—you’ll need it on the router side.
Then navigate to Work Centers → Device Administration → Policy Elements → Results and create two shell profiles:
- Network-Admin: Custom attribute
priv-lvl = 15(full access) - Network-ReadOnly: Custom attribute
priv-lvl = 1(view only)
Create a TACACS+ Command Set for read-only access:
Command Set: ReadOnly-Commands
Permit: show .*
Permit: ping .*
Permit: traceroute .*
Deny: .* (default deny all)
Finally, build a Device Administration Policy Set that matches on device type or location and assigns the correct shell profile based on the user’s Active Directory group.
Step 2: Configure TACACS+ on IOS-XE
Define the TACACS+ Server
! Define ISE as TACACS+ server
tacacs server ISE-PRIMARY
address ipv4 10.10.10.50
key 7 <your-encrypted-secret>
timeout 5
!
! Add a secondary if you have a second ISE PSN
tacacs server ISE-SECONDARY
address ipv4 10.10.10.51
key 7 <your-encrypted-secret>
timeout 5
Use key 0 for a plaintext key during initial config—IOS-XE will encrypt it to type 7 automatically:
tacacs server ISE-PRIMARY
address ipv4 10.10.10.50
key 0 MySharedSecret123!
Create a Server Group
aaa group server tacacs+ ISE-SERVERS
server name ISE-PRIMARY
server name ISE-SECONDARY
ip vrf forwarding Mgmt-vrf
ip tacacs source-interface GigabitEthernet0/0
The ip vrf forwarding Mgmt-vrf line is critical if your management traffic runs in a VRF (common on Cat9K with the dedicated management port). Without it, the TACACS+ packets will try to exit via the default routing table and never reach ISE.
Step 3: Configure AAA Methods
Enable AAA
aaa new-model
This single command is irreversible within a session—once typed, AAA is active. Don’t type it remotely until your TACACS+ config is verified, or you risk locking yourself out. Always configure a local fallback user first.
Create a Local Fallback User
username LOCAL_ADMIN privilege 15 algorithm-type scrypt secret Str0ngL0calP@ss!
Use algorithm-type scrypt (or sha256 at minimum). Never use password—that stores credentials in type 7 “encryption” that takes seconds to reverse.
Authentication
! Login authentication: try ISE first, fall back to local
aaa authentication login VTY_AUTH group ISE-SERVERS local
! Enable (privilege escalation): try ISE first, fall back to local enable password
aaa authentication enable default group ISE-SERVERS enable
Authorization
! Exec authorization: applies shell profile (sets privilege level)
aaa authorization exec VTY_AUTH group ISE-SERVERS local if-authenticated
! Command authorization for all privilege levels
aaa authorization commands 1 VTY_AUTH group ISE-SERVERS local if-authenticated
aaa authorization commands 15 VTY_AUTH group ISE-SERVERS local if-authenticated
! Authorize config commands
aaa authorization config-commands
The if-authenticated keyword is the local fallback behavior—if ISE is unreachable, locally authenticated users get authorized without a second server query. Without this, a TACACS+ outage locks out local users entirely.
Accounting
! Exec accounting: log session start/stop
aaa accounting exec VTY_AUTH start-stop group ISE-SERVERS
! Command accounting: log every command
aaa accounting commands 1 VTY_AUTH start-stop group ISE-SERVERS
aaa accounting commands 15 VTY_AUTH start-stop group ISE-SERVERS
! System events (reloads, etc.)
aaa accounting system default start-stop group ISE-SERVERS
Apply to Line VTY
line vty 0 15
login authentication VTY_AUTH
authorization exec VTY_AUTH
authorization commands 1 VTY_AUTH
authorization commands 15 VTY_AUTH
accounting exec VTY_AUTH
accounting commands 1 VTY_AUTH
accounting commands 15 VTY_AUTH
transport input ssh
transport output none
Note: transport input ssh blocks Telnet entirely. If you’re still using Telnet for device management in 2026, that’s a separate conversation we need to have.
Console Line (Local Only)
line con 0
login authentication default
authorization exec default
The default method list uses the global aaa authentication login default. Configure that to be local-only for the console so a TACACS+ failure doesn’t lock you out of physical access:
aaa authentication login default local
aaa authorization exec default local
Step 4: Lock Down SSH and Management Access
! Generate RSA key for SSHv2
crypto key generate rsa modulus 4096
ip ssh version 2
ip ssh time-out 60
ip ssh authentication-retries 3
ip ssh dh min size 2048
! Only allow SSH from management subnet
ip access-list standard MGMT-ONLY
permit 10.10.10.0 0.0.0.255
deny any log
line vty 0 15
access-class MGMT-ONLY in
Pair this with a Control Plane Policy to rate-limit SSH connection attempts. For a full treatment, see the CoPP guide—SSH brute-force sourced from inside your own network is more common than you’d think.
Step 5: Verification
Test TACACS+ Reachability
Router# test aaa group ISE-SERVERS testuser TestPass123! legacy
Attempting authentication test to server-group ISE-SERVERS using tacacs+
User was successfully authenticated.
Check TACACS+ Server Status
Router# show tacacs
Tacacs+ Server : 10.10.10.50/49 Opens=5 Closes=5 Aborts=0 Errors=0
Packets in=10 Packets out=10
Expected Replies=0 Replies discarded=0
Timeouts=0 Connection Failures=0 Elapsed time=0s
Server is UP
Tacacs+ Server : 10.10.10.51/49 Opens=0 Closes=0 Aborts=0 Errors=0
Packets in=0 Packets out=0
Expected Replies=0 Replies discarded=0
Timeouts=0 Connection Failures=0 Elapsed time=0s
Server is UP
Verify Active Sessions and Accounting
Router# show aaa sessions
Total sessions since last reload: 47
Session Id=12
Unique Id=47
User = sarah
IP Address = 10.10.10.100
Idle Disconnect = 0
IDB = GigabitEthernet0/0
Router# show aaa user all
Unique id 47 is being served by tty line 0
No data for type 1
No data for type 2
No data for type 3
No data for type 4
AAA type EXEC:
service=shell
priv-lvl=15
Debug (Use Carefully in Production)
Router# debug tacacs
Router# debug aaa authentication
Router# debug aaa authorization
Always turn off debug after testing: undebug all
In ISE, go to Operations → TACACS → Live Logs to see real-time authentication, authorization, and accounting records with pass/fail status and matched policy sets.
Step 6: Command Authorization Troubleshooting
The most common complaint after enabling command authorization: “I can’t run any commands.” Here’s the quick checklist:
Check What Policy Matched in ISE
ISE Live Logs will show the matched Device Administration Policy Set and the shell profile returned. If it says priv-lvl=1 when you expected 15, your AD group membership or policy conditions need review.
Router Denying Commands?
Router# debug aaa authorization
AAA/AUTHOR (0x4600003A): Port='tty2' list='VTY_AUTH' type=CMD
service=shell cmd=show running-config
AAA/AUTHOR/TACACS+ (463752650): Processing AV priv-lvl=15
AAA/AUTHOR (0x4600003A): Authorization successful
If you see Authorization failed, the command isn’t in an ISE permit command set for that user. Check ISE → Device Administration → Policy Elements → Results → TACACS Command Sets.
TACACS+ Server Unreachable
Router# show tacacs
Tacacs+ Server : 10.10.10.50/49
Timeouts=10 Connection Failures=3
Server is DEAD
If ISE is marked DEAD, the router falls to the next method in the list (local or if-authenticated). Check reachability, VRF config, and the shared secret (mismatched secrets cause silent failures—the connection opens on TCP/49 but TACACS+ rejects the session).
Verify the Shared Secret
Router# show run | section tacacs server
tacacs server ISE-PRIMARY
address ipv4 10.10.10.50
key 7 0822455D0A1657
Compare the decrypted key with what’s in ISE. Use a type-7 decoder (plenty available offline) to verify they match. A one-character mismatch is the most common deployment mistake.
Recommended ISE Policy Structure
Here’s a clean policy hierarchy for a typical enterprise environment:
Device Admin Policy Sets:
├── Network-Engineers (AD Group: NET-ADMINS)
│ ├── Auth Policy: Allow TACACS+ with AD auth
│ └── Authz Policy: Shell Profile → Network-Admin (priv 15)
│ Command Set: Permit-All
│
├── NOC-ReadOnly (AD Group: NOC-TEAM)
│ ├── Auth Policy: Allow TACACS+ with AD auth
│ └── Authz Policy: Shell Profile → Network-ReadOnly (priv 1)
│ Command Set: ShowOnly-Commands
│
└── Default
└── Authz Policy: Deny All
The key design principle: explicit deny at the bottom of every policy set. Never let the default be “permit unknown.” An ISE deployment without an explicit default-deny is just theater—determined attackers will find the gaps.
Enabling TACACS+ Accounting on ISE Side
By default, ISE stores TACACS+ accounting records locally. To export to a SIEM or syslog server:
- Go to Administration → System → Logging → Remote Logging Targets and add your syslog server.
- Go to Administration → System → Logging → Logging Categories and enable TACACS Accounting to send to your remote target.
This gives you command-level audit logs in your SIEM. Every conf t, every no shutdown, every write mem—timestamped, attributed to a specific AD account, and stored off-device where they can’t be tampered with.
Full Running Config Summary
! Local fallback (configure BEFORE aaa new-model)
username LOCAL_ADMIN privilege 15 algorithm-type scrypt secret Str0ngL0calP@ss!
! Enable AAA
aaa new-model
! TACACS+ servers
tacacs server ISE-PRIMARY
address ipv4 10.10.10.50
key 0 MySharedSecret123!
timeout 5
!
tacacs server ISE-SECONDARY
address ipv4 10.10.10.51
key 0 MySharedSecret123!
timeout 5
! Server group
aaa group server tacacs+ ISE-SERVERS
server name ISE-PRIMARY
server name ISE-SECONDARY
ip vrf forwarding Mgmt-vrf
ip tacacs source-interface GigabitEthernet0/0
! Authentication
aaa authentication login default local
aaa authentication login VTY_AUTH group ISE-SERVERS local
aaa authentication enable default group ISE-SERVERS enable
! Authorization
aaa authorization exec default local
aaa authorization exec VTY_AUTH group ISE-SERVERS local if-authenticated
aaa authorization commands 1 VTY_AUTH group ISE-SERVERS local if-authenticated
aaa authorization commands 15 VTY_AUTH group ISE-SERVERS local if-authenticated
aaa authorization config-commands
! Accounting
aaa accounting exec VTY_AUTH start-stop group ISE-SERVERS
aaa accounting commands 1 VTY_AUTH start-stop group ISE-SERVERS
aaa accounting commands 15 VTY_AUTH start-stop group ISE-SERVERS
aaa accounting system default start-stop group ISE-SERVERS
! SSH hardening
crypto key generate rsa modulus 4096
ip ssh version 2
ip ssh time-out 60
ip ssh authentication-retries 3
! ACL for management access
ip access-list standard MGMT-ONLY
permit 10.10.10.0 0.0.0.255
deny any log
! Console line
line con 0
login authentication default
authorization exec default
! VTY lines
line vty 0 15
login authentication VTY_AUTH
authorization exec VTY_AUTH
authorization commands 1 VTY_AUTH
authorization commands 15 VTY_AUTH
accounting exec VTY_AUTH
accounting commands 1 VTY_AUTH
accounting commands 15 VTY_AUTH
access-class MGMT-ONLY in
transport input ssh
transport output none
Common Gotchas
- Order of operations matters. Configure the local fallback user and method lists before typing
aaa new-model. Better yet, test everything on a non-production device first. - VRF awareness. If management is in a VRF, every AAA-related command needs the VRF context. Miss one and TACACS+ silently fails.
- ISE shared secret is case-sensitive. “Secret123” ≠ “secret123”. TACACS+ connections will establish on TCP/49 but all auth attempts will fail.
- Command authorization can be brutal to debug remotely. Always verify from a console or with a fallback method before enabling command authz on remote sessions.
- ISE licenses. Device Administration (TACACS+) requires a separate license in ISE 3.x—the Plus or Advantage tier. Base license only covers network access (RADIUS). Confirm your entitlement before building the policy.
Wrapping Up
A properly deployed AAA stack with TACACS+ and ISE transforms your network from “shared passwords and hope” to a fully auditable, role-based access control system. Every login is authenticated against your directory, every command is authorized against a policy, and every action is logged with attribution.
The initial setup takes time—mostly in ISE policy configuration and the inevitable debugging of VRF or shared secret issues—but once it’s running, day-to-day management is cleaner and your auditors will thank you.
From here, look at extending ISE to cover 802.1X port authentication using RADIUS, and consider pairing your command accounting data with a SIEM rule that alerts on privilege escalation or configuration changes outside of change windows. For automation of routine tasks that don’t need interactive access, Python with Netmiko and NAPALM can handle templated changes without granting shell access at all.