Hello,
I've been working on configuring a single tac_plus-ng profile that will properly authorize both IOS and IOS-XR NASes. IOS-XR uses the concept of locally defined "task groups" for authorization:
It uses the tacacs attribute "task" for this. Here is an example of an exec authorization request from an IOS device:
---<start packet>---
key used: ...
version: 192, type: 2, seq no: 1, flags: unencrypted
session id: 652f570b, data length: 51
AUTHOR, priv_lvl=1
authen_type=ascii (1)
authen_method=tacacs+ (6)
service=login (1)
user_len=6 port_len=4 rem_addr_len=14 arg_cnt=2
user (len: 6): carter
port (len: 4): tty1
rem_addr (len: 14): ...
arg[0] (len: 13): service=shell
arg[1] (len: 4): cmd*
---<end packet>---
Versus an IOS-XR device:
---<start packet>---
key used: ...
version: 192, type: 2, seq no: 1, flags: unencrypted
session id: d23101db, data length: 63
AUTHOR, priv_lvl=15
authen_type=ascii (1)
authen_method=tacacs+ (6)
service=login (1)
user_len=6 port_len=10 rem_addr_len=14 arg_cnt=3
user (len: 6): carter
port (len: 10): /dev/pts/8
rem_addr (len: 14): ...
arg[0] (len: 13): service=shell
arg[1] (len: 4): cmd*
arg[2] (len: 5): task*
---<end packet>---
If I set "task" when authorizing a non-XR device, it doesn't authorize properly, so I started looking for a way to send certain AV pairs only when the "task*" arg is present. I noticed this in the logs:
nas:service=shell (passed thru)
nas:cmd* (passed thru)
nas:task* svr:absent/deny -> delete task* (i)
I'm not sure how to act on it. I tried using "optional" or "add" instead of "set" for the task attribute, but those just didn't send the AV pair at all. Would the "default attribute = ( permit | deny )" option have an effect here? I tried a few variations of setting that to permit, and didn't see any change in behavior.
I came up with this, which seems to be working properly for both IOS and IOS-XR:
if (service == shell) {
if (cmd == "") {
set priv-lvl = 7
if (arg[task] == "") {
# IOS-XR, not sure if this is the best way to do this
set task = "rx:basic-services"
}
permit
}
if (cmd =~ /^show .*/) {
permit
}
deny
}
I haven't thoroughly tested to make sure this doesn't cause issues with devices from other vendors. Is this the best/only way to achieve what I'm after?
Thanks,
Carter