TACACS+ External Monitor (Python)

Problem this snippet solves:

This script is an external monitor for TACACS+ that simulates a TACACS+ client authenticating a test user, and marks the status of a pool member as up if the authentication is successful. If the connection is down/times out, or the authentication fails due to invalid account settings, the script marks the pool member status as down.


This is heavily inspired by the Radius External Monitor (Python) by AlanTen.

How to use this snippet:

Prerequisite

  1. Create the directory /config/eav/tacacs_plus on BIG-IP
  2. Copy all contents from tacacs_plus package into /config/eav/tacacs_plus.
  • You may also need to download six.py from https://raw.githubusercontent.com/benjaminp/six/master/six.py and place it in /config/eav/tacacs_plus.
  • You will need to have a test account provisioned on the TACACS+ server for the script to perform authentication.


Installation

On BIG-IP, import the code snippet below as an External Monitor Program File.


Monitor Configuration

Set up an External monitor with the imported file, and configure it with the following environment variables:


KEY: TACACS+ server secret

USER: Username for test account

PASSWORD: Password for test account

MOD_PATH: Path to location of Python package tacacs_plus, default: /config/eav

TIMEOUT: Duration to wait for connectivity to TACACS server to be established, default: 3


Troubleshooting

SSH to BIG-IP and run the script locally

$ cd /config/filestore/files_d/Common_d/external_monitor_d/

# Get name of uploaded file, e.g.:
$ ls -la
...
-rwxr-xr-x. 1 tomcat tomcat 1883 2021-09-17 04:05 :Common:tacacs-monitor_39568_7

# Run the script with the corresponding variables
$ KEY=<my_tacacs_key> USER=<testuser> PASSWORD=<supersecure> python <external program file, e.g.:Common:tacacs-monitor_39568_7> <TACACS+ server IP> <TACACS+ server port>


Code :

#!/usr/bin/env python
#
# Filename  : tacacs_plus_mon.py
# Author    : Leon Seng
# Version   : 1.2
# Date      : 2021/09/21
# Python ver: 2.6+
# F5 version: 12.1+
# 
# ========== Installation
# Import this script via GUI:
# System > File Management > External Monitor Program File List > Import...
# Name it however you want.
# Get, modify and copy the following modules:

# ========== Required modules
# -- six --
# https://pypi.org/project/six/
# Copy six.py into /config/eav
#
# -- tacacs_plus --
# https://pypi.org/project/tacacs_plus/ | https://github.com/ansible/tacacs_plus
# Copy tacacs_plus directory into /config/eav

# ========== Environment Variables
# NODE_IP   -   Supplied by F5 monitor as first argument
# NODE_PORT -   Supplied by F5 monitor as second argument
# KEY       -   TACACS+ server secret
# USER      -   Username for test account
# PASSWORD  -   Password for test account
# MOD_PATH  -   Path to location of Python package tacacs_plus, default: /config/eav
# TIMEOUT   -   Duration to wait for connectivity to TACACS server to be established, default: 3

import os
import socket
import sys

if os.environ.get('MOD_PATH'):
    sys.path.append(os.environ.get('MOD_PATH'))
else:
    sys.path.append('/config/eav')

# https://github.com/ansible/tacacs_plus
from tacacs_plus.client import TACACSClient

node_ip = sys.argv[1]
node_port = int(sys.argv[2])
key = os.environ.get("KEY")
user = os.environ.get("USER")
password = os.environ.get("PASSWORD")
timeout = int(os.environ.get("TIMEOUT", 3))

# Determine if node IP is IPv4 or IPv6
family = None
try:
    socket.inet_pton(socket.AF_INET, node_ip)
    family = socket.AF_INET
except socket.error:  # not a valid address
    try:
      socket.inet_pton(socket.AF_INET6, node_ip)
      family = socket.AF_INET6
    except socket.error:
      sys.exit(1)

# Authenticate against TACACS server
client = TACACSClient(node_ip, node_port, key, timeout=timeout, family=family)
try:
  auth = client.authenticate(user, password)
  if auth.valid:
    print "up"
except socket.error:
  # EAV script marks node as DOWN when no output is present
  pass

Tested this on version:

12.1
Published Sep 15, 2021
Version 1.0
No CommentsBe the first to comment