mirror of
				https://github.com/laurivosandi/certidude
				synced 2025-10-31 09:29:13 +00:00 
			
		
		
		
	Migrate to python-gssapi
This commit is contained in:
		| @@ -197,8 +197,7 @@ Install dependencies: | |||||||
|  |  | ||||||
| .. code:: bash | .. code:: bash | ||||||
|  |  | ||||||
|     apt-get install samba-common-bin krb5-user ldap-utils |     apt-get install samba-common-bin krb5-user ldap-utils python-gssapi | ||||||
|     pip install pykerberos |  | ||||||
|  |  | ||||||
| Reset Samba client configuration in ``/etc/samba/smb.conf``, adjust | Reset Samba client configuration in ``/etc/samba/smb.conf``, adjust | ||||||
| workgroup and realm accordingly: | workgroup and realm accordingly: | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ import logging | |||||||
| import os | import os | ||||||
| import re | import re | ||||||
| import socket | import socket | ||||||
|  | from base64 import b64decode | ||||||
| from certidude.user import User | from certidude.user import User | ||||||
| from certidude.firewall import whitelist_subnets | from certidude.firewall import whitelist_subnets | ||||||
| from certidude import config, const | from certidude import config, const | ||||||
| @@ -12,25 +13,11 @@ from certidude import config, const | |||||||
| logger = logging.getLogger("api") | logger = logging.getLogger("api") | ||||||
|  |  | ||||||
| if "kerberos" in config.AUTHENTICATION_BACKENDS: | if "kerberos" in config.AUTHENTICATION_BACKENDS: | ||||||
|     import kerberos # If this fails pip install kerberos |     import gssapi | ||||||
|     ktname = os.getenv("KRB5_KTNAME") |     os.environ["KRB5_KTNAME"] = config.KERBEROS_KEYTAB | ||||||
|  |     server_creds = gssapi.creds.Credentials( | ||||||
|     if not ktname: |         usage='accept', | ||||||
|         click.echo("Kerberos keytab not specified, set environment variable 'KRB5_KTNAME'", err=True) |         name=gssapi.names.Name('HTTP/%s'% (socket.gethostname()))) | ||||||
|         exit(250) |  | ||||||
|     if not os.path.exists(ktname): |  | ||||||
|         click.echo("Kerberos keytab %s does not exist" % ktname, err=True) |  | ||||||
|         exit(248) |  | ||||||
|  |  | ||||||
|     try: |  | ||||||
|         principal = kerberos.getServerPrincipalDetails("HTTP", const.FQDN) |  | ||||||
|     except kerberos.KrbError as exc: |  | ||||||
|         click.echo("Failed to initialize Kerberos, service principal is HTTP/%s, reason: %s" % ( |  | ||||||
|             const.FQDN, exc), err=True) |  | ||||||
|         exit(249) |  | ||||||
|     else: |  | ||||||
|         click.echo("Kerberos enabled, service principal is HTTP/%s" % const.FQDN) |  | ||||||
|  |  | ||||||
|     click.echo("Accepting requests only for realm: %s" % const.DOMAIN) |     click.echo("Accepting requests only for realm: %s" % const.DOMAIN) | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -55,37 +42,12 @@ def authenticate(optional=False): | |||||||
|                     "No Kerberos ticket offered, are you sure you've logged in with domain user account?", |                     "No Kerberos ticket offered, are you sure you've logged in with domain user account?", | ||||||
|                     ["Negotiate"]) |                     ["Negotiate"]) | ||||||
|  |  | ||||||
|  |             context = gssapi.sec_contexts.SecurityContext(creds=server_creds) | ||||||
|             token = ''.join(req.auth.split()[1:]) |             token = ''.join(req.auth.split()[1:]) | ||||||
|  |             context.step(b64decode(token)) | ||||||
|  |             username, domain = str(context.initiator_name).split("@") | ||||||
|  |  | ||||||
|             try: |             if domain.lower() != const.DOMAIN.lower(): | ||||||
|                 result, context = kerberos.authGSSServerInit("HTTP@" + const.FQDN) |  | ||||||
|             except kerberos.GSSError as ex: |  | ||||||
|                 # TODO: logger.error |  | ||||||
|                 raise falcon.HTTPForbidden("Forbidden", |  | ||||||
|                     "Authentication System Failure: %s(%s)" % (ex.args[0][0], ex.args[1][0],)) |  | ||||||
|  |  | ||||||
|             try: |  | ||||||
|                 result = kerberos.authGSSServerStep(context, token) |  | ||||||
|             except kerberos.GSSError as ex: |  | ||||||
|                 kerberos.authGSSServerClean(context) |  | ||||||
|                 logger.error(u"Kerberos authentication failed from %s. " |  | ||||||
|                     "GSSAPI error: %s (%d), perhaps the clock skew it too large?", |  | ||||||
|                     req.context.get("remote_addr"), |  | ||||||
|                     ex.args[0][0], ex.args[0][1]) |  | ||||||
|                 raise falcon.HTTPForbidden("Forbidden", |  | ||||||
|                     "GSSAPI error: %s (%d), perhaps the clock skew it too large?" % (ex.args[0][0], ex.args[0][1])) |  | ||||||
|             except kerberos.KrbError as ex: |  | ||||||
|                 kerberos.authGSSServerClean(context) |  | ||||||
|                 logger.error(u"Kerberos authentication failed from  %s. " |  | ||||||
|                     "Kerberos error: %s (%d)", |  | ||||||
|                     req.context.get("remote_addr"), |  | ||||||
|                     ex.args[0][0], ex.args[0][1]) |  | ||||||
|                 raise falcon.HTTPForbidden("Forbidden", |  | ||||||
|                     "Kerberos error: %s" % (ex.args[0],)) |  | ||||||
|  |  | ||||||
|             user_principal = kerberos.authGSSServerUserName(context) |  | ||||||
|             username, domain = user_principal.split("@") |  | ||||||
|             if domain.lower() != const.DOMAIN: |  | ||||||
|                 raise falcon.HTTPForbidden("Forbidden", |                 raise falcon.HTTPForbidden("Forbidden", | ||||||
|                     "Invalid realm supplied") |                     "Invalid realm supplied") | ||||||
|  |  | ||||||
| @@ -98,29 +60,9 @@ def authenticate(optional=False): | |||||||
|                 # Attempt to look up real user |                 # Attempt to look up real user | ||||||
|                 req.context["user"] = User.objects.get(username) |                 req.context["user"] = User.objects.get(username) | ||||||
|  |  | ||||||
|             try: |  | ||||||
|                 kerberos.authGSSServerClean(context) |  | ||||||
|             except kerberos.GSSError as ex: |  | ||||||
|                 logger.error(u"Kerberos authentication failed for user %s from  %s. " |  | ||||||
|                     "Authentication system failure: %s (%d)", |  | ||||||
|                     user, req.context.get("remote_addr"), |  | ||||||
|                     ex.args[0][0], ex.args[0][1]) |  | ||||||
|                 raise falcon.HTTPUnauthorized("Authentication System Failure %s (%s)" % (ex.args[0][0], ex.args[1][0])) |  | ||||||
|  |  | ||||||
|             if result == kerberos.AUTH_GSS_COMPLETE: |  | ||||||
|             logger.debug(u"Succesfully authenticated user %s for %s from %s", |             logger.debug(u"Succesfully authenticated user %s for %s from %s", | ||||||
|                 req.context["user"], req.env["PATH_INFO"], req.context["remote_addr"]) |                 req.context["user"], req.env["PATH_INFO"], req.context["remote_addr"]) | ||||||
|             return func(resource, req, resp, *args, **kwargs) |             return func(resource, req, resp, *args, **kwargs) | ||||||
|             elif result == kerberos.AUTH_GSS_CONTINUE: |  | ||||||
|                 logger.error(u"Kerberos authentication failed for user %s from  %s. " |  | ||||||
|                     "Unauthorized, tried GSSAPI.", |  | ||||||
|                     user, req.context.get("remote_addr")) |  | ||||||
|                 raise falcon.HTTPUnauthorized("Unauthorized", "Tried GSSAPI") |  | ||||||
|             else: |  | ||||||
|                 logger.error(u"Kerberos authentication failed for user %s from  %s. " |  | ||||||
|                     "Forbidden, tried GSSAPI.", |  | ||||||
|                     user, req.context.get("remote_addr")) |  | ||||||
|                 raise falcon.HTTPForbidden("Forbidden", "Tried GSSAPI") |  | ||||||
|  |  | ||||||
|  |  | ||||||
|         def ldap_authenticate(resource, req, resp, *args, **kwargs): |         def ldap_authenticate(resource, req, resp, *args, **kwargs): | ||||||
| @@ -186,7 +128,6 @@ def authenticate(optional=False): | |||||||
|             if not req.auth.startswith("Basic "): |             if not req.auth.startswith("Basic "): | ||||||
|                 raise falcon.HTTPForbidden("Forbidden", "Bad header: %s" % req.auth) |                 raise falcon.HTTPForbidden("Forbidden", "Bad header: %s" % req.auth) | ||||||
|  |  | ||||||
|             from base64 import b64decode |  | ||||||
|             basic, token = req.auth.split(" ", 1) |             basic, token = req.auth.split(" ", 1) | ||||||
|             user, passwd = b64decode(token).split(":", 1) |             user, passwd = b64decode(token).split(":", 1) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -18,6 +18,7 @@ AUTHENTICATION_BACKENDS = set([j for j in | |||||||
| AUTHORIZATION_BACKEND = cp.get("authorization", "backend")  # whitelist, ldap, posix | AUTHORIZATION_BACKEND = cp.get("authorization", "backend")  # whitelist, ldap, posix | ||||||
| ACCOUNTS_BACKEND = cp.get("accounts", "backend")             # posix, ldap | ACCOUNTS_BACKEND = cp.get("accounts", "backend")             # posix, ldap | ||||||
|  |  | ||||||
|  | KERBEROS_KEYTAB = cp.get("authentication", "kerberos keytab") | ||||||
| LDAP_AUTHENTICATION_URI = cp.get("authentication", "ldap uri") | LDAP_AUTHENTICATION_URI = cp.get("authentication", "ldap uri") | ||||||
| LDAP_GSSAPI_CRED_CACHE = cp.get("accounts", "ldap gssapi credential cache") | LDAP_GSSAPI_CRED_CACHE = cp.get("accounts", "ldap gssapi credential cache") | ||||||
| LDAP_ACCOUNTS_URI = cp.get("accounts", "ldap uri") | LDAP_ACCOUNTS_URI = cp.get("accounts", "ldap uri") | ||||||
|   | |||||||
| @@ -10,6 +10,7 @@ backends = pam | |||||||
| ;backends = kerberos ldap | ;backends = kerberos ldap | ||||||
| ;backends = kerberos pam | ;backends = kerberos pam | ||||||
| ldap uri = ldaps://dc1.example.com | ldap uri = ldaps://dc1.example.com | ||||||
|  | kerberos keytab = FILE:{{ kerberos_keytab }} | ||||||
|  |  | ||||||
| [accounts] | [accounts] | ||||||
| # The accounts backend specifies how the user's given name, surname and e-mail | # The accounts backend specifies how the user's given name, surname and e-mail | ||||||
|   | |||||||
| @@ -4,7 +4,6 @@ After=network.target | |||||||
|  |  | ||||||
| [Service] | [Service] | ||||||
| Environment=PYTHON_EGG_CACHE=/tmp/.cache | Environment=PYTHON_EGG_CACHE=/tmp/.cache | ||||||
| Environment=KRB5_KTNAME={{kerberos_keytab}} |  | ||||||
| PIDFile=/run/certidude/server.pid | PIDFile=/run/certidude/server.pid | ||||||
| ExecReload=/bin/kill -s HUP $MAINPID | ExecReload=/bin/kill -s HUP $MAINPID | ||||||
| ExecStop=/bin/kill -s TERM $MAINPID | ExecStop=/bin/kill -s TERM $MAINPID | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user