Comments (10)
Hi,
the LDAP query Perl scripts don't come with a custom TLS implementation, so the default is whatever the underlying Perl module thinks it's best. Could you check whether
setenv TLS_OPTIONS = "sslversion => 'tlsv1_2'"
in module context makes a difference?
Thanks,
Marc
from event-driven-servers.
from event-driven-servers.
Hi,
I'm sorry, but I can't help you with that. That "openssl s_client" failure seems to imply a local issue.
Cheers,
Marc
from event-driven-servers.
from event-driven-servers.
Hi Marc,
The problem appears to be with openssl indeed openssl/openssl#19518. I tried to compile tac_plus-ng with openssl 1.1.1 but it requires 3.0. Is there a chance to use 1.1.1?
BR,
from event-driven-servers.
Hi,
TLS support for tac_plus-ng is experimental, and while standardization is in progress I'd expect it to take quite some time before actual network devices support it. tac_plus-ng can easily be built without TLS support (e.g. using "./configure --minimum tac_plus-ng").
Regarding a Python module implementation: Well, yes, that's certainly a possibility. I could commit a module for importing the constants (I've never bothered to release that -- I'm just not familiar enough with Python to support it).
The "protocol" between the "external" module and back-end scripts is pretty simple: script receives a series of
\n
lines, followed by a single
=\n
on stdin. It then does its task and returns the updated
\n
list, followed by a
=\n
to stdout. Typical values are 0 (final result available) and 16 (try next module). The perl back-ends should give some insights about the attribute-value pairs that may be used.
Just to make sure that your configuration is correct: Your LDAP_HOSTS variable looks like "ldaps://:636" and USE_TLS is not set? The latter would trigger START_TLS, and that's obviously not available for a native LDAPS server.
Cheers,
Marc
from event-driven-servers.
Hello,
Thank-you. I was able to make the python module work! Just managed the stdin and stdout as you commented. The perl script appears to translate AV constant strings into numbers before prompting, but using the numbers directly allows python to interact correctly.
I will clean the code a bit and will leave a sample here.
Regarding the configuration, that's correct. I use ldaps with port 636 and USE_TLS is not declared. That config on openssl 3.0 is not working; it does for openssl 1.1.1 and gnutls that python implements.
Best regards,
from event-driven-servers.
Hi,
ok, thanks. I'm curious when this will work again ...
I've just pushed some of the Python sample code I've played with a couple of weeks ago. Worked for me, but my Python background is quite limited.
Cheers,
Marc
from event-driven-servers.
Hello,
I had a look to the code you published. It was really helpful as I realised the tacacs may interact several times with the module rather than just pass all AVs at once.
I built this code that works for me against a microsoft ldaps. It's based on python-ldap. The logger can be used to log stuff to a file to help out the debugging when the tacacs is running.
This is subject to improvements such as object implementation, but it works for me anyway.
import ldap, os, sys, logging, re
from datetime import datetime
# Import AV constants
import mavis
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
formatLogger = logging.Formatter("{asctime} {message}", style = "{")
fileLogger = logging.FileHandler("ldappy.log", mode = "w", encoding='utf-8')
fileLogger.setFormatter(formatLogger)
logger.addHandler(fileLogger)
ldapHosts = os.environ.get('LDAP_HOSTS') or "ldaps://<server>"
ldapPass = os.environ.get('LDAP_PASSWD') or "<pass>"
ldapBase = os.environ.get('LDAP_BASE') or "<DN>"
ldapDomain = os.environ.get('LDAP_DOMAIN') or "<domain>"
ldapUser = "{}@{}".format(os.environ.get('LDAP_USER'), os.environ.get('LDAP_DOMAIN')) or "<user>"
ldapFilter = "(&(objectclass=user)(sAMAccountName={}))"
def parseStdin():
avPairs = dict()
for line in sys.stdin:
#logger.info(line.rstrip())
if line.rstrip() != "=":
avPairs[int(line.split()[0])] = line.split()[1]
else:
return avPairs
def writeStdout(avPairs, result):
for key in sorted(avPairs):
sys.stdout.write("%d %s\n" % (int(key), avPairs[key]))
sys.stdout.write("=%d\n" % result)
logger.info("start")
avDict = parseStdin()
result = mavis.MAVIS_DEFERRED
flagFinish = False
try:
# ldapConnection = ldap.initialize(ldapHosts, trace_level=0)
ldapConnection = ldap.ldapobject.ReconnectLDAPObject(ldapHosts, trace_level=0, retry_max=5, retry_delay=10.0)
ldapConnection.set_option(ldap.OPT_DEFBASE, ldapBase)
#ldapConnection.set_option(ldap.OPT_DEBUG_LEVEL,9)
except:
avDict[mavis.AV_A_USER_RESPONSE] = "Unable to connect to the server."
result = mavis.MAVIS_FINAL
flagFinish = True
if not flagFinish and (avDict[mavis.AV_A_TYPE] != mavis.AV_V_TYPE_TACPLUS):
result = mavis.MAVIS_DOWN
flagFinish = True
if not flagFinish and (not mavis.AV_A_USER in avDict):
avDict[mavis.AV_A_USER_RESPONSE] = "User not set."
avDict[mavis.AV_A_RESULT] = mavis.AV_V_RESULT_ERROR
result = mavis.MAVIS_FINAL
flagFinish = True
else:
ldapFilter = ldapFilter.format(avDict[mavis.AV_A_USER])
if not flagFinish and (re.match('\(|\)|,|\||&|\*', avDict[mavis.AV_A_USER])):
avDict[mavis.AV_A_USER_RESPONSE] = "Username not valid."
avDict[mavis.AV_A_RESULT] = mavis.AV_V_RESULT_ERROR;
result = mavis.MAVIS_FINAL
flagFinish = True
if not flagFinish and (avDict[mavis.AV_A_TACTYPE] == mavis.AV_V_TACTYPE_AUTH and not mavis.AV_A_PASSWORD in avDict):
avDict[mavis.AV_A_USER_RESPONSE] = "Password not set."
avDict[mavis.AV_A_RESULT] = mavis.AV_V_RESULT_ERROR;
result = mavis.MAVIS_FINAL
flagFinish = True
if not flagFinish and not mavis.AV_A_PASSWORD in avDict:
ldapConnection.simple_bind_s(ldapUser, ldapPass)
try:
userData = ldapConnection.search_ext_s(ldapBase, ldap.SCOPE_SUBTREE, filterstr = ldapFilter)
#logger.info("user data type {} with {}".format(type(userData), userData))
if userData is not None and len(userData) != 0:
avDict[mavis.AV_A_USER_RESPONSE] = "Authorization passed."
avDict[mavis.AV_A_RESULT] = mavis.AV_V_RESULT_OK
result = mavis.MAVIS_FINAL
else:
avDict[mavis.AV_A_USER_RESPONSE] = "User not found."
avDict[mavis.AV_A_RESULT] = mavis.AV_V_RESULT_NOTFOUND
result = mavis.MAVIS_DOWN
except ldap.TIMEOUT as lto:
#logger.info("timeout {}".format(lto))
avDict[mavis.AV_A_USER_RESPONSE] = "Time out looking up the user."
avDict[mavis.AV_A_RESULT] = mavis.AV_V_RESULT_ERROR
result = mavis.MAVIS_TIMEOUT
finally:
ldapConnection.unbind_s()
flagFinish = True
if not flagFinish and mavis.AV_A_PASSWORD in avDict:
ldapConnection = ldap.ldapobject.ReconnectLDAPObject(ldapHosts, trace_level=0, retry_max=5, retry_delay=10.0)
ldapConnection.set_option(ldap.OPT_DEFBASE, ldapBase)
try:
#logger.info("av received {}".format(avDict))
#logger.info("mypass {}".format(avDict[mavis.AV_A_PASSWORD]))
ldapConnection.simple_bind_s("{}@{}".format(avDict[mavis.AV_A_USER], ldapDomain), avDict[mavis.AV_A_PASSWORD])
#logger.info("ok")
userData = ldapConnection.search_ext_s(ldapBase, ldap.SCOPE_SUBTREE, filterstr = ldapFilter)
#logger.info("user data type {} with {}".format(type(userData), userData))
avDict[mavis.AV_A_DBPASSWORD] = avDict[mavis.AV_A_PASSWORD]
avDict[mavis.AV_A_DN] = userData[0][0]
avDict[mavis.AV_A_MEMBEROF] = '"{}"'.format(userData[0][1]['memberOf'][0].decode('UTF-8'))
avDict[mavis.AV_A_RESULT] = mavis.AV_V_RESULT_OK
result = mavis.MAVIS_FINAL
except ldap.INVALID_CREDENTIALS as lic:
#logger.info("invalid credentials {}".format(lic))
avDict[mavis.AV_A_RESULT] = mavis.AV_V_RESULT_FAIL
result = mavis.MAVIS_DOWN
finally:
flagFinish = True
ldapConnection.unbind_s()
writeStdout(avDict, result)
Again, many thanks for your help and your time.
BR,
from event-driven-servers.
Hi,
pretty nice, thanks for sharing this code!
I'll be closing this issue then.
Cheers,
Marc
from event-driven-servers.
Related Issues (20)
- tac_plus-ng: mavis_tacplus-ng_ldap.pl - @LDAP_HOSTS array does not work if >1 elements are inserted HOT 1
- Not using cached data for authorization with LDAP HOT 2
- tac_plus-ng as a service? HOT 3
- tac_plus: Return auth_error instead of auth_fail when LDAP backend is unreachable HOT 3
- autocmd closing immediately - Cisco IOS HOT 1
- An error message is displayed when you run the openssl passwd -crypt clear_text_password command to create a password HOT 2
- Arista + TACPLUS-NG HOT 1
- tac_plus-ng doesn't seem to start socket even though service reports up and operational. HOT 6
- tac-plus-ng support google authenticator? HOT 1
- Username+Password+OTP second login fails HOT 6
- tac_plus-ng - CLI context aware - unclear documentation HOT 3
- Migration from tac_plus version F4.0.4.27a HOT 2
- tac_plus-ng dns preload file HOT 6
- Trouble to use MEMBEROF value with my OpenLDAP HOT 6
- Tacacs behind AWS NLB HOT 6
- Sporadic TLS negotiation failures with Mavis LDAP backend HOT 6
- libfreeradius-client has been deprecated in favor of radcli HOT 5
- 编译中出现异常 HOT 2
- the error when i execute './configure tac_plus,'the following errors occurs HOT 1
- Connection refused HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from event-driven-servers.