mirror of
https://github.com/laurivosandi/certidude
synced 2025-09-08 22:41:04 +00:00
Added preliminary Kerberos authentication support
This commit is contained in:
60
certidude/auth.py
Normal file
60
certidude/auth.py
Normal file
@@ -0,0 +1,60 @@
|
||||
|
||||
import click
|
||||
import falcon
|
||||
import kerberos
|
||||
import os
|
||||
import re
|
||||
import socket
|
||||
|
||||
# Vanilla Kerberos provides only username.
|
||||
# AD also embeds PAC (Privilege Attribute Certificate), which
|
||||
# is supposed to be sent via HTTP headers and it contains
|
||||
# the groups user is part of.
|
||||
# Even then we would have to manually look up the e-mail
|
||||
# address eg via LDAP, hence to keep things simple
|
||||
# we simply use Kerberos to authenticate.
|
||||
|
||||
FQDN = socket.getaddrinfo(socket.gethostname(), 0, flags=socket.AI_CANONNAME)[0][3]
|
||||
|
||||
if not os.getenv("KRB5_KTNAME"):
|
||||
click.echo("Kerberos keytab not specified, set environment variable 'KRB5_KTNAME'", err=True)
|
||||
exit(250)
|
||||
|
||||
try:
|
||||
principal = kerberos.getServerPrincipalDetails("HTTP", FQDN)
|
||||
except kerberos.KrbError as exc:
|
||||
click.echo("Failed to initialize Kerberos, reason: %s" % exc, err=True)
|
||||
exit(249)
|
||||
else:
|
||||
click.echo("Kerberos enabled, service principal is HTTP/%s" % FQDN)
|
||||
|
||||
def login_required(func):
|
||||
def wrapped(resource, req, resp, *args, **kwargs):
|
||||
authorization = req.get_header("Authorization")
|
||||
|
||||
if not authorization:
|
||||
resp.append_header("WWW-Authenticate", "Negotiate")
|
||||
raise falcon.HTTPUnauthorized("Unauthorized", "No Kerberos ticket offered?")
|
||||
|
||||
token = ''.join(authorization.split()[1:])
|
||||
|
||||
rc, context = kerberos.authGSSServerInit("HTTP@" + FQDN)
|
||||
if rc != kerberos.AUTH_GSS_COMPLETE:
|
||||
raise falcon.HTTPForbidden("Forbidden", "Kerberos ticket expired?")
|
||||
|
||||
rc = kerberos.authGSSServerStep(context, token)
|
||||
kerberos_user = kerberos.authGSSServerUserName(context).split("@")
|
||||
|
||||
# References lost beyond this point! Results in
|
||||
# ValueError: PyCapsule_SetPointer called with null pointer
|
||||
kerberos.authGSSServerClean(context)
|
||||
|
||||
if rc == kerberos.AUTH_GSS_COMPLETE:
|
||||
kwargs["user"] = kerberos_user
|
||||
return func(resource, req, resp, *args, **kwargs)
|
||||
elif rc == kerberos.AUTH_GSS_CONTINUE:
|
||||
raise falcon.HTTPUnauthorized("Unauthorized", "Tried GSSAPI")
|
||||
else:
|
||||
raise falcon.HTTPForbidden("Forbidden", "Tried GSSAPI")
|
||||
|
||||
return wrapped
|
Reference in New Issue
Block a user