mirror of
https://github.com/laurivosandi/certidude
synced 2024-12-23 00:25:18 +00:00
Migrate to python-gssapi
This commit is contained in:
parent
51d7dffa9b
commit
02482e8d79
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user