This guide will walk you through the setup of a Linux based TACACS+ Authentication Server, using Ubuntu 18.04 (tested on Ubuntu 16.04 as well) that authenticates against a Windows Active Directory LDAP(S).
This guide assumes that you are familiar with installing and configuring a Ubuntu Server and can deploy or have already deployed a Windows Active Directory infrastructure.
Prerequisites
- Windows Server 2016 with Active Directory Services (Domain Controller or Read-Only Domain Controller)
- Ubuntu Server (tested on 16.04 LTS or 18.04 LTS)
Basic Network Topology
Below is an example network topology commonly found in a small to medium sized network.

Windows Active Directory Requirements
First, we will setup the required items in our Active Directory system.
- Create a service account that TACACS will use to bind and authenticate to our AD infrastructure. Be sure to use a secure password (16 characters or longer).
This is needed because Active Directory does not allow anonymous bindings by default and will not allow you to search the AD tree if you are not authenticated.
The user does not need any special permissions or group memberships.

- Create two security groups that TACACS will match against to identify what users and permission levels to assign authenticated users. In this example, we will create two security roles. The first being “ADMIN” level permissions, and the second being “TECHNICIAN” level permissions.

- Now create two user accounts, one for each type of user security level and add them to the security group associated with their account.
Username “test.admin” is a member of security group “R_ADMINS” and Username “test.tech” is a member of security group “R_TECHS” in our example
TACACS+ Server Installation
Lets move on to the TACACS Server installation on our Ubuntu Server. First, SSH into your Ubuntu Server and install the required packages.
packages="build-essential libnet-ldap-perl libpcre3-dev ntp ntpdate"
sudo apt-get install -y ${packages}
packages="build-essential libnet-ldap-perl libpcre3-dev ntp ntpdate"
sudo apt-get install -y ${packages}
packages="build-essential libnet-ldap-perl libpcre3-dev ntp ntpdate"
sudo apt-get install -y ${packages}
Next, we are going to download the TACACS+ Server packages that includes the MAVIS (LDAP) authentication packages. This is provided by Marc Huber at pro-bono-publico.de.
wget http://www.pro-bono-publico.de/projects/src/DEVEL.201712190728.tar.bz2 -O tacacs_plus.tar.bz2
bzip2 -dc tacacs_plus.tar.bz2 | tar xvfp -
wget http://www.pro-bono-publico.de/projects/src/DEVEL.201712190728.tar.bz2 -O tacacs_plus.tar.bz2
bzip2 -dc tacacs_plus.tar.bz2 | tar xvfp -
mv PROJECTS tac_plus
wget http://www.pro-bono-publico.de/projects/src/DEVEL.201712190728.tar.bz2 -O tacacs_plus.tar.bz2
bzip2 -dc tacacs_plus.tar.bz2 | tar xvfp -
mv PROJECTS tac_plus
Now, we will configure and build the tac_plus packages on our server.
sudo ./configure --etcdir=/etc/tac_plus
cd tac_plus
sudo ./configure --etcdir=/etc/tac_plus
sudo make
sudo make install
cd tac_plus
sudo ./configure --etcdir=/etc/tac_plus
sudo make
sudo make install
We now need to create the logging directories on our server because the package build process does not build these out for us. We will also make sure to set the permission on these directories so that our TACACS Server software can write to them.
sudo mkdir -p /var/log/tac_plus /var/log/tac_plus/access /var/log/tac_plus/accounting /var/log/tac_plus/authentication
sudo chmod -R 755 /var/log/tac_plus
sudo mkdir -p /var/log/tac_plus /var/log/tac_plus/access /var/log/tac_plus/accounting /var/log/tac_plus/authentication
sudo chmod -R 755 /var/log/tac_plus
sudo mkdir -p /var/log/tac_plus /var/log/tac_plus/access /var/log/tac_plus/accounting /var/log/tac_plus/authentication
sudo chmod -R 755 /var/log/tac_plus
You can verify that the permissions were set correctly by running the following command:
stat --format '%a' /var/log/tac_plus
stat --format '%a' /var/log/tac_plus
>> OUTPUT <<
755
stat --format '%a' /var/log/tac_plus
>> OUTPUT <<
755
We now need to verify that our MAVIS packages are working correctly. To do this execute the below command. You should see output as exampled.
/usr/local/lib/mavis/mavis_tacplus_ldap.pl < /dev/null
Default server type is 'tacacs_schema'. You *may* need to change that to 'generic' or 'microsoft'.
LDAP_HOSTS not defined at /usr/local/lib/mavis/mavis_tacplus_ldap.pl line 277, <DATA> line 755.
/usr/local/lib/mavis/mavis_tacplus_ldap.pl < /dev/null
>> OUTPUT <<
Default server type is 'tacacs_schema'. You *may* need to change that to 'generic' or 'microsoft'.
LDAP_HOSTS not defined at /usr/local/lib/mavis/mavis_tacplus_ldap.pl line 277, <DATA> line 755.
/usr/local/lib/mavis/mavis_tacplus_ldap.pl < /dev/null
>> OUTPUT <<
Default server type is 'tacacs_schema'. You *may* need to change that to 'generic' or 'microsoft'.
LDAP_HOSTS not defined at /usr/local/lib/mavis/mavis_tacplus_ldap.pl line 277, <DATA> line 755.
If there are error messages saying “Can’t locate Net/LDAP.pm in @INC”, you need to double-check the configure
and make
commands at the beginning of the guide. Make sure they all completed successfully without any errors.
If your output above matches, then we can continue with adding the configuration for the TACACS server. Create a file tac_plus.cfg
in the /etc/tac_plus
folder.
Once created, we will open that file to add our configuration template.
sudo touch /etc/tac_plus/tac_plus.cfg
sudo chmod 755 /etc/tac_plus/tac_plus.cfg
sudo nano /etc/tac_plus/tac_plus.cfg
sudo touch /etc/tac_plus/tac_plus.cfg
sudo chmod 755 /etc/tac_plus/tac_plus.cfg
sudo nano /etc/tac_plus/tac_plus.cfg
sudo touch /etc/tac_plus/tac_plus.cfg
sudo chmod 755 /etc/tac_plus/tac_plus.cfg
sudo nano /etc/tac_plus/tac_plus.cfg
Next, we will copy and paste in the below template configuration into the tac_plus.cfg
file. You will need to replace the variables that are specific to your configuration. These are identified by {{VARIABLE-NAME}}
in the template configuration.
#!/usr/local/sbin/tac_plus
listen = { address = 0.0.0.0 port = 49 }
#Uncomment the line below for IPv6 support
#listen = { address = :: port = 49 }
access log = /var/log/tac_plus/access/%Y/%m/access-%m-%d-%Y.txt
accounting log = /var/log/tac_plus/accounting/%Y/%m/accounting-%m-%d-%Y.txt
authentication log = /var/log/tac_plus/authentication/%Y/%m/authentication-%m-%d-%Y.txt
mavis module = external {
setenv LDAP_SERVER_TYPE = "microsoft"
#If you are using Microsoft Global Catalog with secure LDAP (SSL)
#setenv LDAP_HOSTS = "ldaps://{{AD-SERVER-IP}}:3269"
#If you are using Microsoft Global Catalog with regular LDAP (non-SSL)
setenv LDAP_HOSTS = "ldap://{{AD-SERVER-IP}}:3268"
setenv LDAP_BASE = "{{LDAP-BASE-DN}}"
## Username ONLY Authentication
setenv LDAP_FILTER = "(&(objectClass=user)(objectClass=person)(sAMAccountName=%s))"
## Username + UPN Authentication [example: user@mydomain.lan]
# setenv LDAP_FILTER = "(&(objectClass=user)(objectClass=person)(userPrincipalName=%s))"
setenv LDAP_USER = "{{LDAP-SERVICE-ACCOUNT-USERNAME}}"
setenv LDAP_PASSWD = "{{LDAP-SERVICE-ACCOUNT-PASSWORD}}"
#Setting UNLIMIT_AD_GROUP_MEMBERSHIP to 0 will cause a NACK response if the AD account is a member of more than one security group
setenv UNLIMIT_AD_GROUP_MEMBERSHIP = 1
#I'm not 100% sure what EXPAND_AD_GROUP_MEMBERSHIP does
setenv EXPAND_AD_GROUP_MEMBERSHIP = 0
#Clear default setting of tacplus for AD_GROUP_PREFIX
setenv AD_GROUP_PREFIX = ""
#Setting REQUIRE_TACACS_GROUP_PREFIX to 1 will cause a NACK response if the AD account is not a member of a security group with the required prefix
setenv REQUIRE_TACACS_GROUP_PREFIX = 1
#DO NOT SET THE USE_TLS ENVIRONMENT VARIABLE
#TLS WILL AUTOMATICALLY BE ENABLED IF NEEDED
#FORCING THIS VARIABLE TO 1 WILL BREAK MAVIS IF TLS IS NEEDED
exec = /usr/local/lib/mavis/mavis_tacplus_ldap.pl
skip missing groups = yes
#Uncomment the line below for IPv6 support
#Uncomment the line below to inject a login prompt
#prompt = "Put your custom welcome message here.\n"
#Change this to your own secure TACACS+ key
key = "{{TACACS-ENCRYPTION-KEY}}"
group = {{AD-ADMIN-GROUP}} {
#Permit all services by default
#Users will need to re-enter their AD password for the enable password (feel free to customize this however you want)
### Cisco IOS Authentication
#Permit all command attributes
default attribute = permit
#Set privilege level to 15 on IOS/XE
#Uncomment the line below for NX-OS support
#set shell:roles="\"network-admin vdc-admin\""
#Uncomment the line below for IOS XR support
#set task = "#root-system"
### Juniper JunOS Authentication
set local-user-name = {{AD-ADMIN-GROUP}}
group = {{AD-TECH-GROUP}} {
#Permit all services by default
#Users will need to re-enter their AD password for the enable password (feel free to customize this however you want)
### Cisco IOS Authentication
#Permit all command attributes
default attribute = permit
#Set privilege level to 15 on IOS/XE
#Uncomment the line below for NX-OS support
#set shell:roles="\"network-admin vdc-admin\""
#Uncomment the line below for IOS XR support
#set task = "#root-system"
### Juniper JunOS Authentication
set local-user-name = {{AD-TECH-GROUP}}
### BEGIN USER ACCOUNT MAPS ###
# user = user@example.net {
# member = {{AD-ADMIN-GROUP}}
# member = {{AD-TECH-GROUP}}
### END USER ACCOUNT MAPS ###
#!/usr/local/sbin/tac_plus
id = spawnd {
listen = { address = 0.0.0.0 port = 49 }
#Uncomment the line below for IPv6 support
#listen = { address = :: port = 49 }
spawn = {
instances min = 1
instances max = 10
}
background = yes
}
id = tac_plus {
access log = /var/log/tac_plus/access/%Y/%m/access-%m-%d-%Y.txt
accounting log = /var/log/tac_plus/accounting/%Y/%m/accounting-%m-%d-%Y.txt
authentication log = /var/log/tac_plus/authentication/%Y/%m/authentication-%m-%d-%Y.txt
mavis module = external {
setenv LDAP_SERVER_TYPE = "microsoft"
#If you are using Microsoft Global Catalog with secure LDAP (SSL)
#setenv LDAP_HOSTS = "ldaps://{{AD-SERVER-IP}}:3269"
#If you are using Microsoft Global Catalog with regular LDAP (non-SSL)
setenv LDAP_HOSTS = "ldap://{{AD-SERVER-IP}}:3268"
setenv LDAP_BASE = "{{LDAP-BASE-DN}}"
setenv LDAP_SCOPE = sub
## Username ONLY Authentication
setenv LDAP_FILTER = "(&(objectClass=user)(objectClass=person)(sAMAccountName=%s))"
## Username + UPN Authentication [example: user@mydomain.lan]
# setenv LDAP_FILTER = "(&(objectClass=user)(objectClass=person)(userPrincipalName=%s))"
setenv LDAP_USER = "{{LDAP-SERVICE-ACCOUNT-USERNAME}}"
setenv LDAP_PASSWD = "{{LDAP-SERVICE-ACCOUNT-PASSWORD}}"
#Setting UNLIMIT_AD_GROUP_MEMBERSHIP to 0 will cause a NACK response if the AD account is a member of more than one security group
setenv UNLIMIT_AD_GROUP_MEMBERSHIP = 1
#I'm not 100% sure what EXPAND_AD_GROUP_MEMBERSHIP does
setenv EXPAND_AD_GROUP_MEMBERSHIP = 0
#Clear default setting of tacplus for AD_GROUP_PREFIX
setenv AD_GROUP_PREFIX = ""
#Setting REQUIRE_TACACS_GROUP_PREFIX to 1 will cause a NACK response if the AD account is not a member of a security group with the required prefix
setenv REQUIRE_TACACS_GROUP_PREFIX = 1
#DO NOT SET THE USE_TLS ENVIRONMENT VARIABLE
#TLS WILL AUTOMATICALLY BE ENABLED IF NEEDED
#FORCING THIS VARIABLE TO 1 WILL BREAK MAVIS IF TLS IS NEEDED
#setenv USE_TLS = 0
exec = /usr/local/lib/mavis/mavis_tacplus_ldap.pl
}
login backend = mavis
user backend = mavis
pap backend = mavis
skip missing groups = yes
host = world {
#Allow any IPv4 device
address = 0.0.0.0/0
#Uncomment the line below for IPv6 support
#address = ::/0
#Uncomment the line below to inject a login prompt
#prompt = "Put your custom welcome message here.\n"
#Change this to your own secure TACACS+ key
key = "{{TACACS-ENCRYPTION-KEY}}"
}
group = {{AD-ADMIN-GROUP}} {
#Permit all services by default
default service = permit
#Users will need to re-enter their AD password for the enable password (feel free to customize this however you want)
enable = login
###
### Cisco IOS Authentication
###
service = shell {
#Permit all commands
default command = permit
#Permit all command attributes
default attribute = permit
#Set privilege level to 15 on IOS/XE
set priv-lvl = 15
#Uncomment the line below for NX-OS support
#set shell:roles="\"network-admin vdc-admin\""
#Uncomment the line below for IOS XR support
#set task = "#root-system"
}
###
### Juniper JunOS Authentication
###
service = junos-exec {
set local-user-name = {{AD-ADMIN-GROUP}}
}
}
group = {{AD-TECH-GROUP}} {
#Permit all services by default
default service = permit
#Users will need to re-enter their AD password for the enable password (feel free to customize this however you want)
enable = login
###
### Cisco IOS Authentication
###
service = shell {
#Permit all commands
default command = permit
#Permit all command attributes
default attribute = permit
#Set privilege level to 15 on IOS/XE
set priv-lvl = 15
#Uncomment the line below for NX-OS support
#set shell:roles="\"network-admin vdc-admin\""
#Uncomment the line below for IOS XR support
#set task = "#root-system"
}
###
### Juniper JunOS Authentication
###
service = junos-exec {
set local-user-name = {{AD-TECH-GROUP}}
}
}
### BEGIN USER ACCOUNT MAPS ###
# user = user@example.net {
# password = mavis
# member = {{AD-ADMIN-GROUP}}
# }
# user = DEFAULT {
# password = mavis
# member = {{AD-TECH-GROUP}}
# }
### END USER ACCOUNT MAPS ###
}
#!/usr/local/sbin/tac_plus
id = spawnd {
listen = { address = 0.0.0.0 port = 49 }
#Uncomment the line below for IPv6 support
#listen = { address = :: port = 49 }
spawn = {
instances min = 1
instances max = 10
}
background = yes
}
id = tac_plus {
access log = /var/log/tac_plus/access/%Y/%m/access-%m-%d-%Y.txt
accounting log = /var/log/tac_plus/accounting/%Y/%m/accounting-%m-%d-%Y.txt
authentication log = /var/log/tac_plus/authentication/%Y/%m/authentication-%m-%d-%Y.txt
mavis module = external {
setenv LDAP_SERVER_TYPE = "microsoft"
#If you are using Microsoft Global Catalog with secure LDAP (SSL)
#setenv LDAP_HOSTS = "ldaps://{{AD-SERVER-IP}}:3269"
#If you are using Microsoft Global Catalog with regular LDAP (non-SSL)
setenv LDAP_HOSTS = "ldap://{{AD-SERVER-IP}}:3268"
setenv LDAP_BASE = "{{LDAP-BASE-DN}}"
setenv LDAP_SCOPE = sub
## Username ONLY Authentication
setenv LDAP_FILTER = "(&(objectClass=user)(objectClass=person)(sAMAccountName=%s))"
## Username + UPN Authentication [example: user@mydomain.lan]
# setenv LDAP_FILTER = "(&(objectClass=user)(objectClass=person)(userPrincipalName=%s))"
setenv LDAP_USER = "{{LDAP-SERVICE-ACCOUNT-USERNAME}}"
setenv LDAP_PASSWD = "{{LDAP-SERVICE-ACCOUNT-PASSWORD}}"
#Setting UNLIMIT_AD_GROUP_MEMBERSHIP to 0 will cause a NACK response if the AD account is a member of more than one security group
setenv UNLIMIT_AD_GROUP_MEMBERSHIP = 1
#I'm not 100% sure what EXPAND_AD_GROUP_MEMBERSHIP does
setenv EXPAND_AD_GROUP_MEMBERSHIP = 0
#Clear default setting of tacplus for AD_GROUP_PREFIX
setenv AD_GROUP_PREFIX = ""
#Setting REQUIRE_TACACS_GROUP_PREFIX to 1 will cause a NACK response if the AD account is not a member of a security group with the required prefix
setenv REQUIRE_TACACS_GROUP_PREFIX = 1
#DO NOT SET THE USE_TLS ENVIRONMENT VARIABLE
#TLS WILL AUTOMATICALLY BE ENABLED IF NEEDED
#FORCING THIS VARIABLE TO 1 WILL BREAK MAVIS IF TLS IS NEEDED
#setenv USE_TLS = 0
exec = /usr/local/lib/mavis/mavis_tacplus_ldap.pl
}
login backend = mavis
user backend = mavis
pap backend = mavis
skip missing groups = yes
host = world {
#Allow any IPv4 device
address = 0.0.0.0/0
#Uncomment the line below for IPv6 support
#address = ::/0
#Uncomment the line below to inject a login prompt
#prompt = "Put your custom welcome message here.\n"
#Change this to your own secure TACACS+ key
key = "{{TACACS-ENCRYPTION-KEY}}"
}
group = {{AD-ADMIN-GROUP}} {
#Permit all services by default
default service = permit
#Users will need to re-enter their AD password for the enable password (feel free to customize this however you want)
enable = login
###
### Cisco IOS Authentication
###
service = shell {
#Permit all commands
default command = permit
#Permit all command attributes
default attribute = permit
#Set privilege level to 15 on IOS/XE
set priv-lvl = 15
#Uncomment the line below for NX-OS support
#set shell:roles="\"network-admin vdc-admin\""
#Uncomment the line below for IOS XR support
#set task = "#root-system"
}
###
### Juniper JunOS Authentication
###
service = junos-exec {
set local-user-name = {{AD-ADMIN-GROUP}}
}
}
group = {{AD-TECH-GROUP}} {
#Permit all services by default
default service = permit
#Users will need to re-enter their AD password for the enable password (feel free to customize this however you want)
enable = login
###
### Cisco IOS Authentication
###
service = shell {
#Permit all commands
default command = permit
#Permit all command attributes
default attribute = permit
#Set privilege level to 15 on IOS/XE
set priv-lvl = 15
#Uncomment the line below for NX-OS support
#set shell:roles="\"network-admin vdc-admin\""
#Uncomment the line below for IOS XR support
#set task = "#root-system"
}
###
### Juniper JunOS Authentication
###
service = junos-exec {
set local-user-name = {{AD-TECH-GROUP}}
}
}
### BEGIN USER ACCOUNT MAPS ###
# user = user@example.net {
# password = mavis
# member = {{AD-ADMIN-GROUP}}
# }
# user = DEFAULT {
# password = mavis
# member = {{AD-TECH-GROUP}}
# }
### END USER ACCOUNT MAPS ###
}
Here is an example of our working tac_plus.cfg
file on our lab servers.
#!/usr/local/sbin/tac_plus
listen = { address = 0.0.0.0 port = 49 }
#Uncomment the line below for IPv6 support
#listen = { address = :: port = 49 }
access log = /var/log/tac_plus/access/%Y/%m/access-%m-%d-%Y.txt
accounting log = /var/log/tac_plus/accounting/%Y/%m/accounting-%m-%d-%Y.txt
authentication log = /var/log/tac_plus/authentication/%Y/%m/authentication-%m-%d-%Y.txt
mavis module = external {
setenv LDAP_SERVER_TYPE = "microsoft"
#If you are using Microsoft Global Catalog with secure LDAP (SSL)
#setenv LDAP_HOSTS = "ldaps://172.16.10.10:3269"
#If you are using Microsoft Global Catalog with regular LDAP (non-SSL)
setenv LDAP_HOSTS = "ldap://172.16.10.10:3268"
setenv LDAP_BASE = "DC=tacacs-lab,DC=datai,DC=net"
## Username ONLY Authentication
setenv LDAP_FILTER = "(&(objectClass=user)(objectClass=person)(sAMAccountName=%s))"
## Username + UPN Authentication [example: user@mydomain.lan]
# setenv LDAP_FILTER = "(&(objectClass=user)(objectClass=person)(userPrincipalName=%s))"
setenv LDAP_USER = "tacacs@tacacs-lab.datai.net"
setenv LDAP_PASSWD = "My3ncryptedP@55w0rd"
#Setting UNLIMIT_AD_GROUP_MEMBERSHIP to 0 will cause a NACK response if the AD account is a member of more than one security group
setenv UNLIMIT_AD_GROUP_MEMBERSHIP = 1
#I'm not 100% sure what EXPAND_AD_GROUP_MEMBERSHIP does
setenv EXPAND_AD_GROUP_MEMBERSHIP = 0
#Clear default setting of tacplus for AD_GROUP_PREFIX
setenv AD_GROUP_PREFIX = ""
#Setting REQUIRE_TACACS_GROUP_PREFIX to 1 will cause a NACK response if the AD account is not a member of a security group with the required prefix
setenv REQUIRE_TACACS_GROUP_PREFIX = 1
#DO NOT SET THE USE_TLS ENVIRONMENT VARIABLE
#TLS WILL AUTOMATICALLY BE ENABLED IF NEEDED
#FORCING THIS VARIABLE TO 1 WILL BREAK MAVIS IF TLS IS NEEDED
exec = /usr/local/lib/mavis/mavis_tacplus_ldap.pl
skip missing groups = yes
#Uncomment the line below for IPv6 support
#Uncomment the line below to inject a login prompt
#prompt = "Put your custom welcome message here.\n"
#Change this to your own secure TACACS+ key
#Permit all services by default
#Users will need to re-enter their AD password for the enable password (feel free to customize this however you want)
### Cisco IOS Authentication
#Permit all command attributes
default attribute = permit
#Set privilege level to 15 on IOS/XE
#Uncomment the line below for NX-OS support
#set shell:roles="\"network-admin vdc-admin\""
#Uncomment the line below for IOS XR support
#set task = "#root-system"
### Juniper JunOS Authentication
set local-user-name = R_ADMINS
#Permit all services by default
#Users will need to re-enter their AD password for the enable password (feel free to customize this however you want)
### Cisco IOS Authentication
#Permit all command attributes
default attribute = permit
#Set privilege level to 15 on IOS/XE
#Uncomment the line below for NX-OS support
#set shell:roles="\"network-admin vdc-admin\""
#Uncomment the line below for IOS XR support
#set task = "#root-system"
### Juniper JunOS Authentication
set local-user-name = R_TECHS
### BEGIN USER ACCOUNT MAPS ###
# user = user@example.net {
### END USER ACCOUNT MAPS ###
#!/usr/local/sbin/tac_plus
id = spawnd {
listen = { address = 0.0.0.0 port = 49 }
#Uncomment the line below for IPv6 support
#listen = { address = :: port = 49 }
spawn = {
instances min = 1
instances max = 10
}
background = yes
}
id = tac_plus {
access log = /var/log/tac_plus/access/%Y/%m/access-%m-%d-%Y.txt
accounting log = /var/log/tac_plus/accounting/%Y/%m/accounting-%m-%d-%Y.txt
authentication log = /var/log/tac_plus/authentication/%Y/%m/authentication-%m-%d-%Y.txt
mavis module = external {
setenv LDAP_SERVER_TYPE = "microsoft"
#If you are using Microsoft Global Catalog with secure LDAP (SSL)
#setenv LDAP_HOSTS = "ldaps://172.16.10.10:3269"
#If you are using Microsoft Global Catalog with regular LDAP (non-SSL)
setenv LDAP_HOSTS = "ldap://172.16.10.10:3268"
setenv LDAP_BASE = "DC=tacacs-lab,DC=datai,DC=net"
setenv LDAP_SCOPE = sub
## Username ONLY Authentication
setenv LDAP_FILTER = "(&(objectClass=user)(objectClass=person)(sAMAccountName=%s))"
## Username + UPN Authentication [example: user@mydomain.lan]
# setenv LDAP_FILTER = "(&(objectClass=user)(objectClass=person)(userPrincipalName=%s))"
setenv LDAP_USER = "tacacs@tacacs-lab.datai.net"
setenv LDAP_PASSWD = "My3ncryptedP@55w0rd"
#Setting UNLIMIT_AD_GROUP_MEMBERSHIP to 0 will cause a NACK response if the AD account is a member of more than one security group
setenv UNLIMIT_AD_GROUP_MEMBERSHIP = 1
#I'm not 100% sure what EXPAND_AD_GROUP_MEMBERSHIP does
setenv EXPAND_AD_GROUP_MEMBERSHIP = 0
#Clear default setting of tacplus for AD_GROUP_PREFIX
setenv AD_GROUP_PREFIX = ""
#Setting REQUIRE_TACACS_GROUP_PREFIX to 1 will cause a NACK response if the AD account is not a member of a security group with the required prefix
setenv REQUIRE_TACACS_GROUP_PREFIX = 1
#DO NOT SET THE USE_TLS ENVIRONMENT VARIABLE
#TLS WILL AUTOMATICALLY BE ENABLED IF NEEDED
#FORCING THIS VARIABLE TO 1 WILL BREAK MAVIS IF TLS IS NEEDED
#setenv USE_TLS = 0
exec = /usr/local/lib/mavis/mavis_tacplus_ldap.pl
}
login backend = mavis
user backend = mavis
pap backend = mavis
skip missing groups = yes
host = mgmtnet {
#Allow any IPv4 device
address = 172.16.10.0/24
#Uncomment the line below for IPv6 support
#address = ::/0
#Uncomment the line below to inject a login prompt
#prompt = "Put your custom welcome message here.\n"
#Change this to your own secure TACACS+ key
key = "dXVHBUYX36nqd3hA"
}
group = R_ADMINS {
#Permit all services by default
default service = permit
#Users will need to re-enter their AD password for the enable password (feel free to customize this however you want)
enable = login
###
### Cisco IOS Authentication
###
service = shell {
#Permit all commands
default command = permit
#Permit all command attributes
default attribute = permit
#Set privilege level to 15 on IOS/XE
set priv-lvl = 15
#Uncomment the line below for NX-OS support
#set shell:roles="\"network-admin vdc-admin\""
#Uncomment the line below for IOS XR support
#set task = "#root-system"
}
###
### Juniper JunOS Authentication
###
service = junos-exec {
set local-user-name = R_ADMINS
}
}
group = R_TECHS {
#Permit all services by default
default service = permit
#Users will need to re-enter their AD password for the enable password (feel free to customize this however you want)
enable = login
###
### Cisco IOS Authentication
###
service = shell {
#Permit all commands
default command = permit
#Permit all command attributes
default attribute = permit
#Set privilege level to 15 on IOS/XE
set priv-lvl = 15
#Uncomment the line below for NX-OS support
#set shell:roles="\"network-admin vdc-admin\""
#Uncomment the line below for IOS XR support
#set task = "#root-system"
}
###
### Juniper JunOS Authentication
###
service = junos-exec {
set local-user-name = R_TECHS
}
}
### BEGIN USER ACCOUNT MAPS ###
# user = user@example.net {
# password = mavis
# member = R_ADMINS
# }
# user = DEFAULT {
# password = mavis
# member = R_TECHS
# }
### END USER ACCOUNT MAPS ###
}
#!/usr/local/sbin/tac_plus
id = spawnd {
listen = { address = 0.0.0.0 port = 49 }
#Uncomment the line below for IPv6 support
#listen = { address = :: port = 49 }
spawn = {
instances min = 1
instances max = 10
}
background = yes
}
id = tac_plus {
access log = /var/log/tac_plus/access/%Y/%m/access-%m-%d-%Y.txt
accounting log = /var/log/tac_plus/accounting/%Y/%m/accounting-%m-%d-%Y.txt
authentication log = /var/log/tac_plus/authentication/%Y/%m/authentication-%m-%d-%Y.txt
mavis module = external {
setenv LDAP_SERVER_TYPE = "microsoft"
#If you are using Microsoft Global Catalog with secure LDAP (SSL)
#setenv LDAP_HOSTS = "ldaps://172.16.10.10:3269"
#If you are using Microsoft Global Catalog with regular LDAP (non-SSL)
setenv LDAP_HOSTS = "ldap://172.16.10.10:3268"
setenv LDAP_BASE = "DC=tacacs-lab,DC=datai,DC=net"
setenv LDAP_SCOPE = sub
## Username ONLY Authentication
setenv LDAP_FILTER = "(&(objectClass=user)(objectClass=person)(sAMAccountName=%s))"
## Username + UPN Authentication [example: user@mydomain.lan]
# setenv LDAP_FILTER = "(&(objectClass=user)(objectClass=person)(userPrincipalName=%s))"
setenv LDAP_USER = "tacacs@tacacs-lab.datai.net"
setenv LDAP_PASSWD = "My3ncryptedP@55w0rd"
#Setting UNLIMIT_AD_GROUP_MEMBERSHIP to 0 will cause a NACK response if the AD account is a member of more than one security group
setenv UNLIMIT_AD_GROUP_MEMBERSHIP = 1
#I'm not 100% sure what EXPAND_AD_GROUP_MEMBERSHIP does
setenv EXPAND_AD_GROUP_MEMBERSHIP = 0
#Clear default setting of tacplus for AD_GROUP_PREFIX
setenv AD_GROUP_PREFIX = ""
#Setting REQUIRE_TACACS_GROUP_PREFIX to 1 will cause a NACK response if the AD account is not a member of a security group with the required prefix
setenv REQUIRE_TACACS_GROUP_PREFIX = 1
#DO NOT SET THE USE_TLS ENVIRONMENT VARIABLE
#TLS WILL AUTOMATICALLY BE ENABLED IF NEEDED
#FORCING THIS VARIABLE TO 1 WILL BREAK MAVIS IF TLS IS NEEDED
#setenv USE_TLS = 0
exec = /usr/local/lib/mavis/mavis_tacplus_ldap.pl
}
login backend = mavis
user backend = mavis
pap backend = mavis
skip missing groups = yes
host = mgmtnet {
#Allow any IPv4 device
address = 172.16.10.0/24
#Uncomment the line below for IPv6 support
#address = ::/0
#Uncomment the line below to inject a login prompt
#prompt = "Put your custom welcome message here.\n"
#Change this to your own secure TACACS+ key
key = "dXVHBUYX36nqd3hA"
}
group = R_ADMINS {
#Permit all services by default
default service = permit
#Users will need to re-enter their AD password for the enable password (feel free to customize this however you want)
enable = login
###
### Cisco IOS Authentication
###
service = shell {
#Permit all commands
default command = permit
#Permit all command attributes
default attribute = permit
#Set privilege level to 15 on IOS/XE
set priv-lvl = 15
#Uncomment the line below for NX-OS support
#set shell:roles="\"network-admin vdc-admin\""
#Uncomment the line below for IOS XR support
#set task = "#root-system"
}
###
### Juniper JunOS Authentication
###
service = junos-exec {
set local-user-name = R_ADMINS
}
}
group = R_TECHS {
#Permit all services by default
default service = permit
#Users will need to re-enter their AD password for the enable password (feel free to customize this however you want)
enable = login
###
### Cisco IOS Authentication
###
service = shell {
#Permit all commands
default command = permit
#Permit all command attributes
default attribute = permit
#Set privilege level to 15 on IOS/XE
set priv-lvl = 15
#Uncomment the line below for NX-OS support
#set shell:roles="\"network-admin vdc-admin\""
#Uncomment the line below for IOS XR support
#set task = "#root-system"
}
###
### Juniper JunOS Authentication
###
service = junos-exec {
set local-user-name = R_TECHS
}
}
### BEGIN USER ACCOUNT MAPS ###
# user = user@example.net {
# password = mavis
# member = R_ADMINS
# }
# user = DEFAULT {
# password = mavis
# member = R_TECHS
# }
### END USER ACCOUNT MAPS ###
}
Now we need to validate the configuration file. After you have saved and exited the tac_plus.cfg
file, run the following command to verify everything was setup correctly.
/usr/local/sbin/tac_plus -P /etc/tac_plus/tac_plus.cfg
/usr/local/sbin/tac_plus -P /etc/tac_plus/tac_plus.cfg
/usr/local/sbin/tac_plus -P /etc/tac_plus/tac_plus.cfg
If tac_plus reports any errors, you will need to edit the tac_plus.cfg
file again and correct the errors. Do not proceed further until you have corrected all the reported errors. See http://www.pro-bono-publico.de/projects/tac_plus.html for a complete configuration reference. You may also want to view the file /usr/local/lib/mavis/mavis_tacplus_ldap.pl
for a detailed explanation of the available LDAP variables.
Now we need to create a SystemD service startup script for our TACACS server. Copy/Paste the below command into your SSH session. It will automatically create the required service startup script.
sudo cat << EOF > /etc/systemd/system/tac_plus.service
# systemd configuration unit for tac_plus.
# $Id: tac_plus.service,v 1.1 2011/07/22 17:04:03 marc Exp $
# sudo cp tac_plus.service /etc/systemd/system/
# sudo systemctl enable tac_plus.service
# sudo systemctl start tac_plus.service
Description=TACACS+ Service
ExecStart=/usr/local/sbin/tac_plus -f /etc/tac_plus/tac_plus.cfg
ExecReload=/bin/kill -HUP $MAINPID
WantedBy=multi-user.target
sudo cat << EOF > /etc/systemd/system/tac_plus.service
# systemd configuration unit for tac_plus.
# $Id: tac_plus.service,v 1.1 2011/07/22 17:04:03 marc Exp $
#
# To enable the service:
# sudo cp tac_plus.service /etc/systemd/system/
# sudo systemctl enable tac_plus.service
# sudo systemctl start tac_plus.service
#
[Unit]
Description=TACACS+ Service
After=syslog.target
[Service]
ExecStart=/usr/local/sbin/tac_plus -f /etc/tac_plus/tac_plus.cfg
KillMode=process
Restart=always
ExecReload=/bin/kill -HUP $MAINPID
[Install]
WantedBy=multi-user.target
EOF
sudo cat << EOF > /etc/systemd/system/tac_plus.service
# systemd configuration unit for tac_plus.
# $Id: tac_plus.service,v 1.1 2011/07/22 17:04:03 marc Exp $
#
# To enable the service:
# sudo cp tac_plus.service /etc/systemd/system/
# sudo systemctl enable tac_plus.service
# sudo systemctl start tac_plus.service
#
[Unit]
Description=TACACS+ Service
After=syslog.target
[Service]
ExecStart=/usr/local/sbin/tac_plus -f /etc/tac_plus/tac_plus.cfg
KillMode=process
Restart=always
ExecReload=/bin/kill -HUP $MAINPID
[Install]
WantedBy=multi-user.target
EOF
Now you can enable the service for auto-startup and manually start the service.
sudo systemctl enable tac_plus.service
sudo systemctl start tac_plus.service
sudo systemctl enable tac_plus.service
sudo systemctl start tac_plus.service
sudo systemctl enable tac_plus.service
sudo systemctl start tac_plus.service
To verify that the service started, you can run the following two commands.
# sudo systemctl status tac_plus.service
● tac_plus.service - TACACS+ Service
Loaded: loaded (/etc/systemd/system/tac_plus.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2019-01-01 16:13:57 UTC; 1h 8min ago
Main PID: 21795 (tac_plus)
CGroup: /system.slice/tac_plus.service
├─21795 tac_plus: 0 connections, accepting up to 600 more
├─21796 tac_plus: 0 connections
└─21797 perl /usr/local/lib/mavis/mavis_tacplus_ldap.pl
Jan 01 16:13:57 tacacs01 tac_plus[21795]: startup (version 201811291931)
Jan 01 16:13:57 tacacs01 systemd[1]: Started TACACS+ Service.
Jan 01 16:13:57 tacacs01 tac_plus[21795]: epoll event notification mechanism is being used
Jan 01 16:13:57 tacacs01 tac_plus[21795]: bind to [0.0.0.0]:49 succeeded
Jan 01 16:13:57 tacacs01 tac_plus[21796]: - Version 201811291931 initialized
Jan 01 16:13:57 tacacs01 tac_plus[21796]: epoll event notification mechanism is being used
# netstat -antp | grep ":49"
tcp 0 0 0.0.0.0:49 0.0.0.0:* LISTEN 21673/tac_plus: 0 c
# sudo systemctl status tac_plus.service
>> OUTPUT <<
● tac_plus.service - TACACS+ Service
Loaded: loaded (/etc/systemd/system/tac_plus.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2019-01-01 16:13:57 UTC; 1h 8min ago
Main PID: 21795 (tac_plus)
Tasks: 3 (limit: 4662)
CGroup: /system.slice/tac_plus.service
├─21795 tac_plus: 0 connections, accepting up to 600 more
├─21796 tac_plus: 0 connections
└─21797 perl /usr/local/lib/mavis/mavis_tacplus_ldap.pl
Jan 01 16:13:57 tacacs01 tac_plus[21795]: startup (version 201811291931)
Jan 01 16:13:57 tacacs01 systemd[1]: Started TACACS+ Service.
Jan 01 16:13:57 tacacs01 tac_plus[21795]: epoll event notification mechanism is being used
Jan 01 16:13:57 tacacs01 tac_plus[21795]: bind to [0.0.0.0]:49 succeeded
Jan 01 16:13:57 tacacs01 tac_plus[21796]: - Version 201811291931 initialized
Jan 01 16:13:57 tacacs01 tac_plus[21796]: epoll event notification mechanism is being used
# netstat -antp | grep ":49"
>> OUTPUT <<
tcp 0 0 0.0.0.0:49 0.0.0.0:* LISTEN 21673/tac_plus: 0 c
# sudo systemctl status tac_plus.service
>> OUTPUT <<
● tac_plus.service - TACACS+ Service
Loaded: loaded (/etc/systemd/system/tac_plus.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2019-01-01 16:13:57 UTC; 1h 8min ago
Main PID: 21795 (tac_plus)
Tasks: 3 (limit: 4662)
CGroup: /system.slice/tac_plus.service
├─21795 tac_plus: 0 connections, accepting up to 600 more
├─21796 tac_plus: 0 connections
└─21797 perl /usr/local/lib/mavis/mavis_tacplus_ldap.pl
Jan 01 16:13:57 tacacs01 tac_plus[21795]: startup (version 201811291931)
Jan 01 16:13:57 tacacs01 systemd[1]: Started TACACS+ Service.
Jan 01 16:13:57 tacacs01 tac_plus[21795]: epoll event notification mechanism is being used
Jan 01 16:13:57 tacacs01 tac_plus[21795]: bind to [0.0.0.0]:49 succeeded
Jan 01 16:13:57 tacacs01 tac_plus[21796]: - Version 201811291931 initialized
Jan 01 16:13:57 tacacs01 tac_plus[21796]: epoll event notification mechanism is being used
# netstat -antp | grep ":49"
>> OUTPUT <<
tcp 0 0 0.0.0.0:49 0.0.0.0:* LISTEN 21673/tac_plus: 0 c
We are now ready to verify that the TACACS services are authentication against our Active Directory server. Run the below commands on your Ubuntu server. You should get output similar to our example.
### Test Admin Account Authentication
/usr/local/bin/mavistest -d -1 /etc/tac_plus/tac_plus.cfg tac_plus TACPLUS test.admin password123$
{{ bunch of debug output ...}}
Input attribute-value-pairs:
TIMESTAMP mavistest-21804-1546360707-0
Output attribute-value-pairs:
TIMESTAMP mavistest-21804-1546360707-0
SERIAL OwS74pPKAjcEH89PojinNQ=
### Test Technician Account Authentication
/usr/local/bin/mavistest -d -1 /etc/tac_plus/tac_plus.cfg tac_plus TACPLUS test.tech password123$
{{ bunch of debug output ...}}
Input attribute-value-pairs:
TIMESTAMP mavistest-21806-1546360743-0
Output attribute-value-pairs:
TIMESTAMP mavistest-21806-1546360743-0
SERIAL gydnsgXHXyjeQaR2JaBlhw=
### Test Admin Account Authentication
/usr/local/bin/mavistest -d -1 /etc/tac_plus/tac_plus.cfg tac_plus TACPLUS test.admin password123$
>> OUTPUT <<
{{ bunch of debug output ...}}
Input attribute-value-pairs:
TYPE TACPLUS
TIMESTAMP mavistest-21804-1546360707-0
USER test.admin
PASSWORD password123$
TACTYPE AUTH
Output attribute-value-pairs:
TYPE TACPLUS
TIMESTAMP mavistest-21804-1546360707-0
USER test.admin
RESULT ACK
PASSWORD password123$
SERIAL OwS74pPKAjcEH89PojinNQ=
DBPASSWORD password123$
TACMEMBER "R_ADMINS"
TACTYPE AUTH
### Test Technician Account Authentication
/usr/local/bin/mavistest -d -1 /etc/tac_plus/tac_plus.cfg tac_plus TACPLUS test.tech password123$
>> OUTPUT <<
{{ bunch of debug output ...}}
Input attribute-value-pairs:
TYPE TACPLUS
TIMESTAMP mavistest-21806-1546360743-0
USER test.tech
PASSWORD password123$
TACTYPE AUTH
Output attribute-value-pairs:
TYPE TACPLUS
TIMESTAMP mavistest-21806-1546360743-0
USER test.tech
RESULT ACK
PASSWORD password123$
SERIAL gydnsgXHXyjeQaR2JaBlhw=
DBPASSWORD password123$
TACMEMBER "R_TECHS"
TACTYPE AUTH
### Test Admin Account Authentication
/usr/local/bin/mavistest -d -1 /etc/tac_plus/tac_plus.cfg tac_plus TACPLUS test.admin password123$
>> OUTPUT <<
{{ bunch of debug output ...}}
Input attribute-value-pairs:
TYPE TACPLUS
TIMESTAMP mavistest-21804-1546360707-0
USER test.admin
PASSWORD password123$
TACTYPE AUTH
Output attribute-value-pairs:
TYPE TACPLUS
TIMESTAMP mavistest-21804-1546360707-0
USER test.admin
RESULT ACK
PASSWORD password123$
SERIAL OwS74pPKAjcEH89PojinNQ=
DBPASSWORD password123$
TACMEMBER "R_ADMINS"
TACTYPE AUTH
### Test Technician Account Authentication
/usr/local/bin/mavistest -d -1 /etc/tac_plus/tac_plus.cfg tac_plus TACPLUS test.tech password123$
>> OUTPUT <<
{{ bunch of debug output ...}}
Input attribute-value-pairs:
TYPE TACPLUS
TIMESTAMP mavistest-21806-1546360743-0
USER test.tech
PASSWORD password123$
TACTYPE AUTH
Output attribute-value-pairs:
TYPE TACPLUS
TIMESTAMP mavistest-21806-1546360743-0
USER test.tech
RESULT ACK
PASSWORD password123$
SERIAL gydnsgXHXyjeQaR2JaBlhw=
DBPASSWORD password123$
TACMEMBER "R_TECHS"
TACTYPE AUTH
From the output above, look specifically at the RESULT output and the TACMEMBER output. These should be “ACK” in the RESULT field, which means Active Directory responded and was successful, and the TACMEMBER value should match the security group associated with the user account. If you got NACK, BFD, or ERR in the RESULT field, that means something went wrong. You’ll want to double-check your Active Directory environment variables in the tac_plus.cfg
file.
For those that want to see what the traffic looks like, below is a PCAP (packet capture) of the LDAP communication between our TACACS Server and our Windows Active Directory Controller. The communication in this capture was done using none SSL based connections, which means everything is transmitted in CLEAR TEXT.
It is highly recommended that you enable SSL on the Active Directory Controller and the TACACS configuration
before you implement this into a production environment. Using LetsEncrypt, you can enable SSL certificates for free. We use the application
Certify the Web on Windows Servers to generate SSL certificates.
tacacs_ldap_connection.zip
A handy Windows tool that may help you correctly configure the environment variables in LDAP is the Softerra LDAP Browser.
Do not continue further until you can run the above tests and get a valid response from the user authentication.
Juniper (JunOS) Device Configuration
We are now ready to configure one of our Juniper devices for TACACS authentication. For a full en-depth understanding on setting up Juniper TACACS Authentication, we would recommend that you read the Juniper documentation for your specific device and version of software. To learn more about the different permissions flags and users classes, we would recommend reading the Junos OS Login Classes documentation. ~ In this example, we will be using a Juniper vMX Router running JunOS v14.1
First, we will configure our Juniper device to utilize the TACACS authentication server as the primary source for account authorizations, with the standard “password” (local user accounts) as a fall-back in the event the TACACS server is offline or networking is unavailable. You will need to replace the variables that are specific to your configuration. These are identified by {{VARIABLE-NAME}}
in the template configuration.
## Set the system authentication order
set system authentication-order tacplus
set system authentication-order password
## Set the TACACS server and encryption key
set system tacplus-server {{TACACS-SERVER-IP}} secret "{{TACACS-ENCRYPTION-KEY}}"
set system tacplus-server {{TACACS-SERVER-IP}} single-connection
set system tacplus-server {{TACACS-SERVER-IP}} source-address {{ROUTER-SOURCE-IP}}
## Set the accounting logging services
set system accounting events login
set system accounting events change-log
set system accounting events interactive-commands
set system accounting destination tacplus
## Set the system authentication order
##
set system authentication-order tacplus
set system authentication-order password
## Set the TACACS server and encryption key
##
set system tacplus-server {{TACACS-SERVER-IP}} secret "{{TACACS-ENCRYPTION-KEY}}"
set system tacplus-server {{TACACS-SERVER-IP}} single-connection
set system tacplus-server {{TACACS-SERVER-IP}} source-address {{ROUTER-SOURCE-IP}}
## Set the accounting logging services
##
set system accounting events login
set system accounting events change-log
set system accounting events interactive-commands
set system accounting destination tacplus
## Set the system authentication order
##
set system authentication-order tacplus
set system authentication-order password
## Set the TACACS server and encryption key
##
set system tacplus-server {{TACACS-SERVER-IP}} secret "{{TACACS-ENCRYPTION-KEY}}"
set system tacplus-server {{TACACS-SERVER-IP}} single-connection
set system tacplus-server {{TACACS-SERVER-IP}} source-address {{ROUTER-SOURCE-IP}}
## Set the accounting logging services
##
set system accounting events login
set system accounting events change-log
set system accounting events interactive-commands
set system accounting destination tacplus
Here is an example configuration from our lab equipment.
set system authentication-order tacplus
set system authentication-order password
set system tacplus-server 172.16.10.11 secret "dXVHBUYX36nqd3hA"
set system tacplus-server 172.16.10.11 single-connection
set system tacplus-server 172.16.10.11 source-address 172.16.10.15
set system accounting events login
set system accounting events change-log
set system accounting events interactive-commands
set system accounting destination tacplus
## SHOW SYSTEM >> OUTPUT << ##
authentication-order [ tacplus password ];
secret "$9$q.PQApOcrKNdw24aji1IEhKWxNdgaZLxUHk.zFSrleMX7NV"; ## SECRET-DATA
source-address 172.16.10.15;
events [ login change-log interactive-commands ];
set system authentication-order tacplus
set system authentication-order password
set system tacplus-server 172.16.10.11 secret "dXVHBUYX36nqd3hA"
set system tacplus-server 172.16.10.11 single-connection
set system tacplus-server 172.16.10.11 source-address 172.16.10.15
set system accounting events login
set system accounting events change-log
set system accounting events interactive-commands
set system accounting destination tacplus
## SHOW SYSTEM >> OUTPUT << ##
authentication-order [ tacplus password ];
tacplus-server {
172.16.10.11 {
secret "$9$q.PQApOcrKNdw24aji1IEhKWxNdgaZLxUHk.zFSrleMX7NV"; ## SECRET-DATA
single-connection;
source-address 172.16.10.15;
}
}
accounting {
events [ login change-log interactive-commands ];
destination {
tacplus;
}
}
set system authentication-order tacplus
set system authentication-order password
set system tacplus-server 172.16.10.11 secret "dXVHBUYX36nqd3hA"
set system tacplus-server 172.16.10.11 single-connection
set system tacplus-server 172.16.10.11 source-address 172.16.10.15
set system accounting events login
set system accounting events change-log
set system accounting events interactive-commands
set system accounting destination tacplus
## SHOW SYSTEM >> OUTPUT << ##
authentication-order [ tacplus password ];
tacplus-server {
172.16.10.11 {
secret "$9$q.PQApOcrKNdw24aji1IEhKWxNdgaZLxUHk.zFSrleMX7NV"; ## SECRET-DATA
single-connection;
source-address 172.16.10.15;
}
}
accounting {
events [ login change-log interactive-commands ];
destination {
tacplus;
}
}
Next, we need to add the configuration to the Juniper device that map the user account to the user class. This portion is very important and miss-understood very easily. The “user class” attributes can be built out however works best for your organization. However, you need to pay special attention to the “login user” accounts that are created.
The “login user” accounts that are created are NOT the “usernames” for every user that will be logging into the devices. These “names” are the direct mapping names that match what was created in the tac_plus.cfg
GROUP attributes. This is where the “magic” happens on the username > group mappings.
set local-user-name = R_TECHS
service = junos-exec {
set local-user-name = R_TECHS
}
service = junos-exec {
set local-user-name = R_TECHS
}
Add the following configuration to your Juniper device. If you named your security groups differently, then you will have to adjust the configuration to match your changes.
set system login class administrators permissions all
set system login class technicians permissions network
set system login class technicians permissions view
set system login class technicians permissions view-configuration
set system login user R_ADMINS full-name "TACACS Administrators"
set system login user R_ADMINS class administrators
set system login user R_TECHS full-name "TACACS Technicians"
set system login user R_TECHS class technicians
set system login class administrators permissions all
set system login class technicians permissions network
set system login class technicians permissions view
set system login class technicians permissions view-configuration
set system login user R_ADMINS full-name "TACACS Administrators"
set system login user R_ADMINS class administrators
set system login user R_TECHS full-name "TACACS Technicians"
set system login user R_TECHS class technicians
set system login class administrators permissions all
set system login class technicians permissions network
set system login class technicians permissions view
set system login class technicians permissions view-configuration
set system login user R_ADMINS full-name "TACACS Administrators"
set system login user R_ADMINS class administrators
set system login user R_TECHS full-name "TACACS Technicians"
set system login user R_TECHS class technicians
Once you have your configuration changes added to your device, commit them.
commit check
commit
You are now ready to test your TACACS authentication with the different user accounts. SSH into your Juniper device on the management address and enter the username / password that you setup. For this example, we will be using “test.admin” and “test.tech”.


Upon a successful login, your TACACS server should be recording the accounting packets sent from the Juniper device. These accounting logs are located in /var/log/tac_plus/*
cat /var/log/tac_plus/accounting/2019/01/accounting-01-01-2019.txt
cat /var/log/tac_plus/accounting/2019/01/accounting-01-01-2019.txt
cat /var/log/tac_plus/accounting/2019/01/accounting-01-01-2019.txt
2019-01-01 14:55:25 -0500 172.16.10.15 test.admin ttyp1 172.16.10.10 start task_id=1 service=shell process*mgd[5143] cmd=login
2019-01-01 14:55:48 -0500 172.16.10.15 test.tech ttyp2 172.16.10.10 start task_id=1 service=shell process*mgd[5152] cmd=login
>> OUTPUT <<
2019-01-01 14:55:25 -0500 172.16.10.15 test.admin ttyp1 172.16.10.10 start task_id=1 service=shell process*mgd[5143] cmd=login
2019-01-01 14:55:48 -0500 172.16.10.15 test.tech ttyp2 172.16.10.10 start task_id=1 service=shell process*mgd[5152] cmd=login
>> OUTPUT <<
2019-01-01 14:55:25 -0500 172.16.10.15 test.admin ttyp1 172.16.10.10 start task_id=1 service=shell process*mgd[5143] cmd=login
2019-01-01 14:55:48 -0500 172.16.10.15 test.tech ttyp2 172.16.10.10 start task_id=1 service=shell process*mgd[5152] cmd=login
I have also provided a PCAP of the TACACS authentication request between the Juniper device and the TACACS server. This PCAP also includes the SSH traffic from the client to the Juniper device.
tacacs_ssh_juniper-authentication.zip
Cisco Device Configuration
We are now ready to configure one of our Cisco devices for TACACS authentication. For a full en-depth understanding on setting up Cisco AAA / TACACS Authentication, we would recommend that you read the Cisco Documentation for your specific device and version of software. Unfortunately, Cisco has done a very poor job on standardizing the configuration of the AAA settings per version and again per device type. ~ In this example, we will be using a Cisco IOS Router running version 15.4(1)T
First, we will configure our Cisco device to utilize the TACACS authentication server as the primary source for account authorizations, with the “local” user account as a fall-back in the event the TACACS server is offline or networking is unavailable. You will need to replace the variables that are specific to your configuration. These are identified by {{VARIABLE-NAME}}
in the template configuration.
!-- SET THE TACACS AUTHENTICATION SERVER
tacacs-server host {{TACACS-SERVER-IP}}
tacacs-server directed-request
tacacs-server key 0 {{TACACS-ENCRYPTION-KEY}}
!-- ESTABLISH A SECRET PASSWORD FOR CONSOLE
service password-encryption
enable secret 0 {{SECURE-SECRET-PASSWORD}}
!-- SET THE AAA SECURITY ROLES
aaa authentication login default group tacacs+ local
aaa authentication login console local
aaa authorization config-commands
aaa authorization exec default group tacacs+ local if-authenticated
aaa authorization exec console if-authenticated
aaa authorization commands 1 default group tacacs+ local if-authenticated
aaa authorization commands 15 default group tacacs+ local if-authenticated
aaa accounting exec default start-stop group tacacs+
aaa accounting commands 1 default start-stop group tacacs+
aaa accounting commands 15 default start-stop group tacacs+
!-- CONFIGURE CONSOLE FOR LOCAL AUTHENTICATION ONLY
login authentication console
!-- CONFIGURE VTY FOR AAA AUTHENTICATION VIA SSH ONLY
!
!--
!-- SET THE TACACS AUTHENTICATION SERVER
!--
tacacs-server host {{TACACS-SERVER-IP}}
tacacs-server directed-request
tacacs-server key 0 {{TACACS-ENCRYPTION-KEY}}
!
!
!--
!-- ESTABLISH A SECRET PASSWORD FOR CONSOLE
!--
service password-encryption
enable secret 0 {{SECURE-SECRET-PASSWORD}}
!
!--
!-- SET THE AAA SECURITY ROLES
!--
!
aaa new-model
!
aaa authentication login default group tacacs+ local
aaa authentication login console local
!
aaa authorization config-commands
aaa authorization exec default group tacacs+ local if-authenticated
aaa authorization exec console if-authenticated
aaa authorization commands 1 default group tacacs+ local if-authenticated
aaa authorization commands 15 default group tacacs+ local if-authenticated
!
aaa accounting exec default start-stop group tacacs+
aaa accounting commands 1 default start-stop group tacacs+
aaa accounting commands 15 default start-stop group tacacs+
!
!
aaa session-id common
!
!
!--
!-- CONFIGURE CONSOLE FOR LOCAL AUTHENTICATION ONLY
!--
line con 0
logging synchronous
login authentication console
!
!--
!-- CONFIGURE VTY FOR AAA AUTHENTICATION VIA SSH ONLY
!--
line vty 0 4
logging synchronous
transport input ssh
!
!
!
!--
!-- SET THE TACACS AUTHENTICATION SERVER
!--
tacacs-server host {{TACACS-SERVER-IP}}
tacacs-server directed-request
tacacs-server key 0 {{TACACS-ENCRYPTION-KEY}}
!
!
!--
!-- ESTABLISH A SECRET PASSWORD FOR CONSOLE
!--
service password-encryption
enable secret 0 {{SECURE-SECRET-PASSWORD}}
!
!--
!-- SET THE AAA SECURITY ROLES
!--
!
aaa new-model
!
aaa authentication login default group tacacs+ local
aaa authentication login console local
!
aaa authorization config-commands
aaa authorization exec default group tacacs+ local if-authenticated
aaa authorization exec console if-authenticated
aaa authorization commands 1 default group tacacs+ local if-authenticated
aaa authorization commands 15 default group tacacs+ local if-authenticated
!
aaa accounting exec default start-stop group tacacs+
aaa accounting commands 1 default start-stop group tacacs+
aaa accounting commands 15 default start-stop group tacacs+
!
!
aaa session-id common
!
!
!--
!-- CONFIGURE CONSOLE FOR LOCAL AUTHENTICATION ONLY
!--
line con 0
logging synchronous
login authentication console
!
!--
!-- CONFIGURE VTY FOR AAA AUTHENTICATION VIA SSH ONLY
!--
line vty 0 4
logging synchronous
transport input ssh
!
!
Upon a successful login, your TACACS server should be recording the accounting packets sent from the Cisco device. These accounting logs are located in /var/log/tac_plus/*
cat /var/log/tac_plus/accounting/2019/01/accounting-01-01-2019.txt
cat /var/log/tac_plus/accounting/2019/01/accounting-01-01-2019.txt
cat /var/log/tac_plus/accounting/2019/01/accounting-01-01-2019.txt
2019-01-01 17:37:26 -0500 172.16.10.16 test.admin tty2 172.16.10.10 start task_id=35 timezone=EST service=shell
2019-01-01 17:37:29 -0500 172.16.10.16 test.admin tty2 172.16.10.10 stop task_id=35 timezone=EST service=shell priv-lvl=15 cmd=configure terminal <cr>
2019-01-01 17:37:32 -0500 172.16.10.16 test.admin tty2 172.16.10.10 stop task_id=35 timezone=EST service=shell disc-cause=1 disc-cause-ext=9 pre-session-time=3 elapsed_time=6 stop_time=1546382252
2019-01-01 17:37:26 -0500 172.16.10.16 test.admin tty2 172.16.10.10 start task_id=35 timezone=EST service=shell
2019-01-01 17:37:29 -0500 172.16.10.16 test.admin tty2 172.16.10.10 stop task_id=35 timezone=EST service=shell priv-lvl=15 cmd=configure terminal <cr>
2019-01-01 17:37:32 -0500 172.16.10.16 test.admin tty2 172.16.10.10 stop task_id=35 timezone=EST service=shell disc-cause=1 disc-cause-ext=9 pre-session-time=3 elapsed_time=6 stop_time=1546382252
2019-01-01 17:37:26 -0500 172.16.10.16 test.admin tty2 172.16.10.10 start task_id=35 timezone=EST service=shell
2019-01-01 17:37:29 -0500 172.16.10.16 test.admin tty2 172.16.10.10 stop task_id=35 timezone=EST service=shell priv-lvl=15 cmd=configure terminal <cr>
2019-01-01 17:37:32 -0500 172.16.10.16 test.admin tty2 172.16.10.10 stop task_id=35 timezone=EST service=shell disc-cause=1 disc-cause-ext=9 pre-session-time=3 elapsed_time=6 stop_time=1546382252
Cisco Command Access Control
Below is a tac_plus.cfg
configuration file that includes settings to allow restrictive ( permit | deny ) commands for the R_TECHS access group. This was put together to show how to restrict or permit access to specific commands to users.
#!/usr/local/sbin/tac_plus
listen = { address = 0.0.0.0 port = 49 }
#Uncomment the line below for IPv6 support
#listen = { address = :: port = 49 }
access log = /var/log/tac_plus/access/%Y/%m/access-%m-%d-%Y.txt
accounting log = /var/log/tac_plus/accounting/%Y/%m/accounting-%m-%d-%Y.txt
authentication log = /var/log/tac_plus/authentication/%Y/%m/authentication-%m-%d-%Y.txt
mavis module = external {
setenv LDAP_SERVER_TYPE = "microsoft"
#If you are using Microsoft Global Catalog with secure LDAP (SSL)
#setenv LDAP_HOSTS = "ldaps://172.16.10.10:3269"
#If you are using Microsoft Global Catalog with regular LDAP (non-SSL)
setenv LDAP_HOSTS = "ldap://172.16.10.10:3268"
setenv LDAP_BASE = "DC=tacacs-lab,DC=datai,DC=net"
## Username ONLY Authentication
setenv LDAP_FILTER = "(&(objectClass=user)(objectClass=person)(sAMAccountName=%s))"
## Username + UPN Authentication [example: user@mydomain.lan]
# setenv LDAP_FILTER = "(&(objectClass=user)(objectClass=person)(userPrincipalName=%s))"
setenv LDAP_USER = "tacacs@tacacs-lab.datai.net"
setenv LDAP_PASSWD = "My3ncryptedP@55w0rd"
#Setting UNLIMIT_AD_GROUP_MEMBERSHIP to 0 will cause a NACK response if the AD account is a member of more than one security group
setenv UNLIMIT_AD_GROUP_MEMBERSHIP = 1
#I'm not 100% sure what EXPAND_AD_GROUP_MEMBERSHIP does
setenv EXPAND_AD_GROUP_MEMBERSHIP = 0
#Clear default setting of tacplus for AD_GROUP_PREFIX
setenv AD_GROUP_PREFIX = ""
#Setting REQUIRE_TACACS_GROUP_PREFIX to 1 will cause a NACK response if the AD account is not a member of a security group with the required prefix
setenv REQUIRE_TACACS_GROUP_PREFIX = 1
#DO NOT SET THE USE_TLS ENVIRONMENT VARIABLE
#TLS WILL AUTOMATICALLY BE ENABLED IF NEEDED
#FORCING THIS VARIABLE TO 1 WILL BREAK MAVIS IF TLS IS NEEDED
exec = /usr/local/lib/mavis/mavis_tacplus_ldap.pl
skip missing groups = yes
#Uncomment the line below for IPv6 support
#Uncomment the line below to inject a login prompt
#prompt = "Put your custom welcome message here.\n"
#Change this to your own secure TACACS+ key
#Permit all services by default
#Users will need to re-enter their AD password for the enable password (feel free to customize this however you want)
### Cisco IOS Authentication
#Permit all command attributes
default attribute = permit
#Set privilege level to 15 on IOS/XE
#Uncomment the line below for NX-OS support
#set shell:roles="\"network-admin vdc-admin\""
#Uncomment the line below for IOS XR support
#set task = "#root-system"
### Juniper JunOS Authentication
set local-user-name = R_ADMINS
#Permit all services by default
#Users will need to re-enter their AD password for the enable password (feel free to customize this however you want)
### Cisco IOS Authentication
# default command = permit
#Permit all command attributes
default attribute = permit
#Set privilege level to 15 on IOS/XE
##========================================##
## COMMAND ACCESS CONTROL RULES ##
##========================================##
# Enter global configuration of terminal
# Exit any configuration mode
# Jump back to enable mode
# Show any configuration parameter
# Save running-configuration
permit "running-config startup-config <cr>"
# Write running-configuration to memory
permit "counters FastEthernet.*"
permit "counters GigabitEthernet.*"
permit "counters Port-channel.*"
# "Do" commands run from configuration mode. Since "do" commands
# don't autoexpand, the shortest forms possible have to be allowed.
# Allow shortened form of "ping"
# Allow shortened form of "traceroute"
# Allow shortened form of "show"
# Enter interface configuration mode
# Set interfaces to default
permit "verify unicast.*"
permit "verify unicast.*"
# Removing configuration parameters
permit "ip verify unicast.*"
permit "ipv6 verify unicast.*"
permit "switchport mode <cr>"
permit "switchport access vlan .*"
permit "switchport private-vlan host-association.*"
permit "spanning-tree portfast edge <cr>"
# Allow adding descriptions
permit "verify unicast.*"
permit "verify unicast.*"
# Allow switchport commands
# Allow the 'switchport' command without allowing all
# other switchport commands.
permit "mode private-vlan host"
permit "private-vlan host-association.*"
# Allow spanning-tree commands
permit "portfast disable"
# Allow mls qos for VLANs
permit "qos vlan-based <cr>"
# Allow service policy commands
#Uncomment the line below for NX-OS support
#set shell:roles="\"network-admin vdc-admin\""
#Uncomment the line below for IOS XR support
#set task = "#root-system"
### Juniper JunOS Authentication
set local-user-name = R_TECHS
### BEGIN USER ACCOUNT MAPS ###
# user = user@example.net {
### END USER ACCOUNT MAPS ###
#!/usr/local/sbin/tac_plus
id = spawnd {
listen = { address = 0.0.0.0 port = 49 }
#Uncomment the line below for IPv6 support
#listen = { address = :: port = 49 }
spawn = {
instances min = 1
instances max = 10
}
background = yes
}
id = tac_plus {
access log = /var/log/tac_plus/access/%Y/%m/access-%m-%d-%Y.txt
accounting log = /var/log/tac_plus/accounting/%Y/%m/accounting-%m-%d-%Y.txt
authentication log = /var/log/tac_plus/authentication/%Y/%m/authentication-%m-%d-%Y.txt
mavis module = external {
setenv LDAP_SERVER_TYPE = "microsoft"
#If you are using Microsoft Global Catalog with secure LDAP (SSL)
#setenv LDAP_HOSTS = "ldaps://172.16.10.10:3269"
#If you are using Microsoft Global Catalog with regular LDAP (non-SSL)
setenv LDAP_HOSTS = "ldap://172.16.10.10:3268"
setenv LDAP_BASE = "DC=tacacs-lab,DC=datai,DC=net"
setenv LDAP_SCOPE = sub
## Username ONLY Authentication
setenv LDAP_FILTER = "(&(objectClass=user)(objectClass=person)(sAMAccountName=%s))"
## Username + UPN Authentication [example: user@mydomain.lan]
# setenv LDAP_FILTER = "(&(objectClass=user)(objectClass=person)(userPrincipalName=%s))"
setenv LDAP_USER = "tacacs@tacacs-lab.datai.net"
setenv LDAP_PASSWD = "My3ncryptedP@55w0rd"
#Setting UNLIMIT_AD_GROUP_MEMBERSHIP to 0 will cause a NACK response if the AD account is a member of more than one security group
setenv UNLIMIT_AD_GROUP_MEMBERSHIP = 1
#I'm not 100% sure what EXPAND_AD_GROUP_MEMBERSHIP does
setenv EXPAND_AD_GROUP_MEMBERSHIP = 0
#Clear default setting of tacplus for AD_GROUP_PREFIX
setenv AD_GROUP_PREFIX = ""
#Setting REQUIRE_TACACS_GROUP_PREFIX to 1 will cause a NACK response if the AD account is not a member of a security group with the required prefix
setenv REQUIRE_TACACS_GROUP_PREFIX = 1
#DO NOT SET THE USE_TLS ENVIRONMENT VARIABLE
#TLS WILL AUTOMATICALLY BE ENABLED IF NEEDED
#FORCING THIS VARIABLE TO 1 WILL BREAK MAVIS IF TLS IS NEEDED
#setenv USE_TLS = 0
exec = /usr/local/lib/mavis/mavis_tacplus_ldap.pl
}
login backend = mavis
user backend = mavis
pap backend = mavis
skip missing groups = yes
host = world {
#Allow any IPv4 device
address = 0.0.0.0/0
#Uncomment the line below for IPv6 support
#address = ::/0
#Uncomment the line below to inject a login prompt
#prompt = "Put your custom welcome message here.\n"
#Change this to your own secure TACACS+ key
key = "dXVHBUYX36nqd3hA"
}
group = R_ADMINS {
#Permit all services by default
default service = permit
#Users will need to re-enter their AD password for the enable password (feel free to customize this however you want)
enable = login
###
### Cisco IOS Authentication
###
service = shell {
#Permit all commands
default command = permit
#Permit all command attributes
default attribute = permit
#Set privilege level to 15 on IOS/XE
set priv-lvl = 15
#Uncomment the line below for NX-OS support
#set shell:roles="\"network-admin vdc-admin\""
#Uncomment the line below for IOS XR support
#set task = "#root-system"
}
###
### Juniper JunOS Authentication
###
service = junos-exec {
set local-user-name = R_ADMINS
}
}
group = R_TECHS {
#Permit all services by default
default service = permit
#Users will need to re-enter their AD password for the enable password (feel free to customize this however you want)
enable = login
###
### Cisco IOS Authentication
###
service = shell {
#Permit all commands
# default command = permit
default command = deny
#Permit all command attributes
default attribute = permit
#Set privilege level to 15 on IOS/XE
set priv-lvl = 15
##========================================##
## COMMAND ACCESS CONTROL RULES ##
##========================================##
# Enter enable mode
cmd = enable {
permit .*
}
# Enter global configuration of terminal
cmd = configure {
permit terminal.*
}
# Exit disable mode
cmd = disable {
permit .*
}
# Exit any configuration mode
cmd = exit {
permit .*
}
# Jump back to enable mode
cmd = end {
permit \r
}
# Ping
cmd = ping {
permit .*
}
# Traceroute
cmd = traceroute {
permit .*
}
# Show any configuration parameter
cmd = show {
permit .*
}
# Save running-configuration
cmd = copy {
permit "running-config startup-config <cr>"
}
# Write running-configuration to memory
cmd = write {
permit "memory <cr>"
}
# Clear commands
cmd = clear {
permit "counters FastEthernet.*"
permit "counters GigabitEthernet.*"
permit "counters Vlan.*"
permit "counters Port-channel.*"
}
# "Do" commands run from configuration mode. Since "do" commands
# don't autoexpand, the shortest forms possible have to be allowed.
cmd = do {
# Allow shortened form of "ping"
permit pi.*
# Allow shortened form of "traceroute"
permit tr.*
# Allow shortened form of "show"
permit sh.*
}
# Enter interface configuration mode
cmd = interface {
permit FastEthernet.*
permit GigabitEthernet.*
}
# Set interfaces to default
cmd = default {
permit FastEthernet.*
permit GigabitEthernet.*
}
# IP commands
cmd = ip {
permit route.*
permit address.*
permit "verify unicast.*"
}
# IPv6 commands
cmd = ipv6 {
permit route.*
permit address.*
permit "verify unicast.*"
}
# Removing configuration parameters
cmd = no {
permit "ip route.*"
permit "ipv6 route.*"
permit description.*
permit "ip address.*"
permit "ipv6 address.*"
permit "ip verify unicast.*"
permit "ipv6 verify unicast.*"
permit "cdp enable <cr>"
permit "shutdown <cr>"
permit "switchport <cr>"
permit "switchport mode <cr>"
permit "switchport access vlan .*"
permit nonegotiate.*
permit "switchport private-vlan host-association.*"
permit "spanning-tree portfast edge <cr>"
permit service-policy.*
}
# Allow adding descriptions
cmd = description {
permit .*
}
# Allow IP commands
cmd = ip {
permit address.*
permit "verify unicast.*"
}
# Allow IPv6 commands
cmd = ipv6 {
permit address.*
permit "verify unicast.*"
}
# Allow switchport commands
cmd = switchport {
# Allow the 'switchport' command without allowing all
# other switchport commands.
permit ^<cr>
permit "mode access"
permit "access vlan.*"
permit "mode private-vlan host"
permit nonegotiate
permit "private-vlan host-association.*"
permit host
}
# Allow spanning-tree commands
cmd = spanning-tree {
permit "portfast edge"
permit "portfast disable"
}
# Allow CDP enable
cmd = cdp {
permit enable
}
# Allow mls qos for VLANs
cmd = mls {
permit "qos vlan-based <cr>"
}
# Allow service policy commands
cmd = service-policy {
permit .*
}
# Allow shutdown command
cmd = shutdown {
permit ^<cr>
}
#Uncomment the line below for NX-OS support
#set shell:roles="\"network-admin vdc-admin\""
#Uncomment the line below for IOS XR support
#set task = "#root-system"
}
###
### Juniper JunOS Authentication
###
service = junos-exec {
set local-user-name = R_TECHS
}
}
### BEGIN USER ACCOUNT MAPS ###
# user = user@example.net {
# password = mavis
# member = R_ADMINS
# }
# user = DEFAULT {
# password = mavis
# member = R_ADMINS
# }
### END USER ACCOUNT MAPS ###
}
#!/usr/local/sbin/tac_plus
id = spawnd {
listen = { address = 0.0.0.0 port = 49 }
#Uncomment the line below for IPv6 support
#listen = { address = :: port = 49 }
spawn = {
instances min = 1
instances max = 10
}
background = yes
}
id = tac_plus {
access log = /var/log/tac_plus/access/%Y/%m/access-%m-%d-%Y.txt
accounting log = /var/log/tac_plus/accounting/%Y/%m/accounting-%m-%d-%Y.txt
authentication log = /var/log/tac_plus/authentication/%Y/%m/authentication-%m-%d-%Y.txt
mavis module = external {
setenv LDAP_SERVER_TYPE = "microsoft"
#If you are using Microsoft Global Catalog with secure LDAP (SSL)
#setenv LDAP_HOSTS = "ldaps://172.16.10.10:3269"
#If you are using Microsoft Global Catalog with regular LDAP (non-SSL)
setenv LDAP_HOSTS = "ldap://172.16.10.10:3268"
setenv LDAP_BASE = "DC=tacacs-lab,DC=datai,DC=net"
setenv LDAP_SCOPE = sub
## Username ONLY Authentication
setenv LDAP_FILTER = "(&(objectClass=user)(objectClass=person)(sAMAccountName=%s))"
## Username + UPN Authentication [example: user@mydomain.lan]
# setenv LDAP_FILTER = "(&(objectClass=user)(objectClass=person)(userPrincipalName=%s))"
setenv LDAP_USER = "tacacs@tacacs-lab.datai.net"
setenv LDAP_PASSWD = "My3ncryptedP@55w0rd"
#Setting UNLIMIT_AD_GROUP_MEMBERSHIP to 0 will cause a NACK response if the AD account is a member of more than one security group
setenv UNLIMIT_AD_GROUP_MEMBERSHIP = 1
#I'm not 100% sure what EXPAND_AD_GROUP_MEMBERSHIP does
setenv EXPAND_AD_GROUP_MEMBERSHIP = 0
#Clear default setting of tacplus for AD_GROUP_PREFIX
setenv AD_GROUP_PREFIX = ""
#Setting REQUIRE_TACACS_GROUP_PREFIX to 1 will cause a NACK response if the AD account is not a member of a security group with the required prefix
setenv REQUIRE_TACACS_GROUP_PREFIX = 1
#DO NOT SET THE USE_TLS ENVIRONMENT VARIABLE
#TLS WILL AUTOMATICALLY BE ENABLED IF NEEDED
#FORCING THIS VARIABLE TO 1 WILL BREAK MAVIS IF TLS IS NEEDED
#setenv USE_TLS = 0
exec = /usr/local/lib/mavis/mavis_tacplus_ldap.pl
}
login backend = mavis
user backend = mavis
pap backend = mavis
skip missing groups = yes
host = world {
#Allow any IPv4 device
address = 0.0.0.0/0
#Uncomment the line below for IPv6 support
#address = ::/0
#Uncomment the line below to inject a login prompt
#prompt = "Put your custom welcome message here.\n"
#Change this to your own secure TACACS+ key
key = "dXVHBUYX36nqd3hA"
}
group = R_ADMINS {
#Permit all services by default
default service = permit
#Users will need to re-enter their AD password for the enable password (feel free to customize this however you want)
enable = login
###
### Cisco IOS Authentication
###
service = shell {
#Permit all commands
default command = permit
#Permit all command attributes
default attribute = permit
#Set privilege level to 15 on IOS/XE
set priv-lvl = 15
#Uncomment the line below for NX-OS support
#set shell:roles="\"network-admin vdc-admin\""
#Uncomment the line below for IOS XR support
#set task = "#root-system"
}
###
### Juniper JunOS Authentication
###
service = junos-exec {
set local-user-name = R_ADMINS
}
}
group = R_TECHS {
#Permit all services by default
default service = permit
#Users will need to re-enter their AD password for the enable password (feel free to customize this however you want)
enable = login
###
### Cisco IOS Authentication
###
service = shell {
#Permit all commands
# default command = permit
default command = deny
#Permit all command attributes
default attribute = permit
#Set privilege level to 15 on IOS/XE
set priv-lvl = 15
##========================================##
## COMMAND ACCESS CONTROL RULES ##
##========================================##
# Enter enable mode
cmd = enable {
permit .*
}
# Enter global configuration of terminal
cmd = configure {
permit terminal.*
}
# Exit disable mode
cmd = disable {
permit .*
}
# Exit any configuration mode
cmd = exit {
permit .*
}
# Jump back to enable mode
cmd = end {
permit \r
}
# Ping
cmd = ping {
permit .*
}
# Traceroute
cmd = traceroute {
permit .*
}
# Show any configuration parameter
cmd = show {
permit .*
}
# Save running-configuration
cmd = copy {
permit "running-config startup-config <cr>"
}
# Write running-configuration to memory
cmd = write {
permit "memory <cr>"
}
# Clear commands
cmd = clear {
permit "counters FastEthernet.*"
permit "counters GigabitEthernet.*"
permit "counters Vlan.*"
permit "counters Port-channel.*"
}
# "Do" commands run from configuration mode. Since "do" commands
# don't autoexpand, the shortest forms possible have to be allowed.
cmd = do {
# Allow shortened form of "ping"
permit pi.*
# Allow shortened form of "traceroute"
permit tr.*
# Allow shortened form of "show"
permit sh.*
}
# Enter interface configuration mode
cmd = interface {
permit FastEthernet.*
permit GigabitEthernet.*
}
# Set interfaces to default
cmd = default {
permit FastEthernet.*
permit GigabitEthernet.*
}
# IP commands
cmd = ip {
permit route.*
permit address.*
permit "verify unicast.*"
}
# IPv6 commands
cmd = ipv6 {
permit route.*
permit address.*
permit "verify unicast.*"
}
# Removing configuration parameters
cmd = no {
permit "ip route.*"
permit "ipv6 route.*"
permit description.*
permit "ip address.*"
permit "ipv6 address.*"
permit "ip verify unicast.*"
permit "ipv6 verify unicast.*"
permit "cdp enable <cr>"
permit "shutdown <cr>"
permit "switchport <cr>"
permit "switchport mode <cr>"
permit "switchport access vlan .*"
permit nonegotiate.*
permit "switchport private-vlan host-association.*"
permit "spanning-tree portfast edge <cr>"
permit service-policy.*
}
# Allow adding descriptions
cmd = description {
permit .*
}
# Allow IP commands
cmd = ip {
permit address.*
permit "verify unicast.*"
}
# Allow IPv6 commands
cmd = ipv6 {
permit address.*
permit "verify unicast.*"
}
# Allow switchport commands
cmd = switchport {
# Allow the 'switchport' command without allowing all
# other switchport commands.
permit ^<cr>
permit "mode access"
permit "access vlan.*"
permit "mode private-vlan host"
permit nonegotiate
permit "private-vlan host-association.*"
permit host
}
# Allow spanning-tree commands
cmd = spanning-tree {
permit "portfast edge"
permit "portfast disable"
}
# Allow CDP enable
cmd = cdp {
permit enable
}
# Allow mls qos for VLANs
cmd = mls {
permit "qos vlan-based <cr>"
}
# Allow service policy commands
cmd = service-policy {
permit .*
}
# Allow shutdown command
cmd = shutdown {
permit ^<cr>
}
#Uncomment the line below for NX-OS support
#set shell:roles="\"network-admin vdc-admin\""
#Uncomment the line below for IOS XR support
#set task = "#root-system"
}
###
### Juniper JunOS Authentication
###
service = junos-exec {
set local-user-name = R_TECHS
}
}
### BEGIN USER ACCOUNT MAPS ###
# user = user@example.net {
# password = mavis
# member = R_ADMINS
# }
# user = DEFAULT {
# password = mavis
# member = R_ADMINS
# }
### END USER ACCOUNT MAPS ###
}