Easier Tacacs Configurations with do_auth
26 09 2009We’ve gone over how you can make your tacacs configuration really secure but complicated. Let’s show how doauth can actually make configuration easier. It’s much easier to edit the doauth.ini file than the tac_plus.conf file. In fact, we can make adding a default user as easy as typing “adduser”.
I would post the compiled code, but it’s too difficult to get a hold of John these days. (Something about a baby, I dunno) It’s trivial to compile:
dan@dan-desktop:~$ python
Python 2.5.2 (r252:60911, Jul 22 2009, 15:35:03)
[GCC 4.2.4 (Ubuntu 4.2.4-1ubuntu3)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pycompile
>>> pycompile.compile("doauth.py")
>>> quit()
First, a starting tacplus.conf file. Which, we’ll never have to edit again:
# My simple tacplus config that never needs to change
key = mykey
accounting file = /var/log/tacplus.acct
default authentication = file /etc/passwd
user = DEFAULT {
member = doauthaccess
}
group = doauthaccess {
default service = permit
service = exec { priv-lvl = 15
idletime = 10 }
enable = file /etc/passwd
after authorization "/usr/bin/python /root/doauth.pyc -i $address -u $user -d $name -l /root/log.txt -f /root/do_auth.ini"
}
Most important – after authorizaion line is one line, not two. The $ means it wrapped.
Now, we add homer and give him access to some show commands. Fist, we do a adduser homer on linux to add the user. This way, when the user wants to change is password, he can any time he wants to with passwd. Next, we edit the do_auth.ini file
[users]
homer =
fewcommands
[fewcommands]
hostallow =
.*
devicepermit =
.*
command_permit =
show users
show int.*
show ip int.*
show controllers.*
And, you’re done. Well, I’d add some tabs to each command that got stripped above(blogs/wiki’s can be annoying), but that’s about it.
Let’s compare that to the tac_plus.conf config:
user = homer {
member = limitedaccess
}
group = limitedaccess {
default service = deny
acl = limited_acl
service = exec {
priv-lvl = 15
idletime = 10
}
cmd = show {
permit "running-config.*"
permit "ip int*"
permit "inter.*"
permit "controllers.*"
}
In my small do_auth python program, we have no permits, no “”, and no {}. Much easier and the no need to restart the daemon. To add an admin user is even easier. Adduser admin in linux, then add:
admin =
adminuser
[adminuser]
hostallow =
.*
devicepermit =
.*
command_permit =
.*
So, our final config is very easy:
[users]
homer =
fewcommands
admin =
adminuser
[fewcommands]
hostallow =
.*
devicepermit =
.*
commandpermit =
show users
show int.*
show ip int.*
show controllers.*
[adminuser]
hostallow =
.*
devicepermit =
.*
commandpermit =
.*
As if this weren’t easy enough, let’s say 99% of your users are these limited access users. Wouldn’t it be nice to just do an adduser and be done without any config modification? All we need is a default user. In our example above we would change to this:
[users]
default =
fewcommands
[fewcommands]
hostallow =
.*
devicepermit =
.*
command_permit =
show users
show int.*
show ip int.*
show controllers.*
Now, whenever we do an adduser, it automatically gets this level of access.
From here, we can make it as simple or as complicated as we want. Restrict them to certain device, make them connect from connect from certain IP’s, ect. We can maybe even begin to work on a web front end. (Maybe someday when I get time…..)
-Dan Schmidt






Excellent guide Dan ! There’s one point that seems uncovered however. What if user Homer need access to specific commands not found on Level1 ?? Is there any way to handle that scenario ?
Level 1? The levels you authorize are set on the device it’s self, they are not set set on the tacacs server.
I really like this and it would make building a front end simple. My only issue is I use login = PAM and tie authentication back to our Active directory through pam_ldap. Can’t seem to get that working here, maybe i am missing something.
You can’t get login = PAM working or can’t get doauth working? doauth is pretty trivial, getting PAM to work with active directory is much more difficult and I can’t help you there. (Have often suggested somebody write a tutorial) Getting the two to work together should not be a problem as after authentication scripts are completely separate from the login process.
This doesn’t appear to work with ASA 8.21 for command authorization. It just spits out; 2010-02-17 16:20:29: Error: Option ‘default’ does not exist in section users in file /etc/tacplus/doauth.ini whenever trying to authorize commands.
Dan, I would like to implement this but have a question first. The way I would like to use it is, default user has no access and then set the privileged user according to their access level. Is there away to do that?
DanH – try ‘DEFAULT’ instead of ‘default’ in your tac_plus.conf
Skip – This code works by commands, not privilege levels. Not that it couldn’t be done, I just did not have a need at the time to modify the tac pairs. You could take priv-lvl = 15 out of the config and deny “enable” to the users you don’t want to enable. Or, put them in a different group in tac_plus.conf, but that means you now have to modify two configuration files instead of one.
The examples above were done in much haste, there might be errors; if other people are actually interested in this, I’ll try to fix it up a bit. My current employer doesn’t use tac_plus, so I don’t have a testing environment any more.
I have done each step as you have directed. However, I cannot log in to my router. However, using tac_plus.conf configuration works well. Anything I need to look out for.
I get the following
telnet 172.17.0.68 Trying 172.17.0.68… Connected to 172.17.0.68. Escape character is ‘^]’.
User Access Verification
Username: xxxx Password: % Authorization failed. Connection closed by foreign host.
Post the log.txt & do_auth,ini
This is my do_auth.ini
alex = admin [admin] hostallow = .* devicepermit = .* command_permit = .*
This is my tacacs cfg
key = xxxxx accounting file = /var/log/tacacc.log default authentication = file /etc/passwd user = DEFAULT { member = doauthaccess } group = doauthaccess { default service = permit service = exec { priv-lvl = 15 } enable = file /etc/passwd after authorization “/usr/bin/python /etc/tacacs/doauth.pyc -i $address -u $user -d $name -l /var/log/log.txt -f /etc/tacacs/do_auth.ini” }
log.txt is empty
Well, you are missing [users] at the top. However, you should still get a log in /var/log/log.txt. Do you get output from “python do_auth.py”? (or .pyc)
Sorry about the [users] section. I actually do have it on the .ini file. I must have missed in during copy. I do get output from doauth.pyc. It prints the content of the doauth.py. What cat do_auth.py would do. Should that be the case?
Not exactly what cat would do – it only prints the help.
So, let’s debug with -D. (don’t run from command line without -D)
python doauth.py -i 10.1.1.1 -u alex -d 192.168.1.1 -l log.txt -f doauth.ini -D
We get errors:
Traceback (most recent call last): File “doauth.py”, line 375, in main() File “doauth.py”, line 281, in main if not (filename in config.read(filename)): File “/usr/lib/python2.6/ConfigParser.py”, line 286, in read self.read(fp, filename) File “/usr/lib/python2.6/ConfigParser.py”, line 510, in _read raise e ConfigParser.ParsingError: File contains parsing errors: doauth.ini [line 3]: ‘admin\n’ ….
I see the problem. No tabs! I can’t seem to print tabs on the wiki, but you need tabs everywhere I have a \t
[users] alex = \tadmin
[admin] hostallow = \t.* devicepermit = \t.* command_permit = \t.*
After than, it’s a lot happier: dan@dan-desktop:~$ python doauth.py -i 10.1.1.1 -u alex -d 192.168.1.1 -l log.txt -f doauth.ini -D dan@dan-desktop:~$ cat log.txt 2010-03-25 18:16:06: User ‘alex’ allowed command ’show users wide’ to device ‘192.168.1.1′ in ‘admin’->’command_permit’
The debug command is hard coded to “show users wide.” I was going to change that to allow a variable, but I was finished with the program and nobody else had any interest in it.
Thanks helpdeskdan, it works fine now. I do appreciate the effort toward helping me resolve this.
Excellent guide, Dan! Does exist any bug about limiting configuration commands? In my doauth.ini I’d restricted the following comands to the specified user: [users] integra = restrito rogerios = admin [restrito] hostallow = .* devicepermit = 192.168.0.2402 commandpermit = show .* quit command_deny = show ver.* conf.* int.* shutdown But it didn’t work! All other features are working (including deny “show version”), but “config ter”, “interface gi 0/1″ and “shutdown” were permited.
Can you help me?
Thanks in advance
Post the log. The log will tell us where it was permitted.
Hello, you have a bug in 1.4 version. Configuration file says “hostallow” but in your code you check agains “hostpermit”.
I did what now? I vaguely remember making a mistake like that, but I thought I fixed it a long time ago.
dan@dan-desktop:~$ egrep hostallow doauth1-4.py hostallow Allow users from this range. Mandatory if hostallow = hostallow = if not matchit(thisgroup, “hostallow”, ipaddr, config, logfile, filename): % (username, ipaddr, thisgroup, “hostallow”)) dan@dan-desktop:~$ egrep hostpermit doauth1-4.py
If people are actually using this, please drop me a line. (As far as I know, nobody is currently using it)
I’m sorry for the mistake. The problem is that in your example inside the code you use “deviceallow”, but in the code you check against “devicepermit”.
:-\ You’re right, thanks
Hi Dan, Your little program does exactly what I have been trying to do in bash shell for several weeks and seems to work perfectly. It just makes tac_plus as powerful as I wanted it to be. Thanks very much for your work and the quality of your documentation !
Thanks, I’m glad there is one person out there whom this has helped!
Hi Dan,
how can i write only several commands which I want to deny. for example I want to deny those commands: no ip route interface gig 0/0 no aaa authentication login default group tacacs+ local no aaa authorization exec default group tacacs+ if-authenticated really thanks for support. Ivan.
Sry 4 late reply, didn’t see comment. This is easy, put the commands you want to deny in commanddeny section, and put a .* in commandpermit.