diff --git a/README.md b/README.md index 197a8bb..29a8a34 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,27 @@ the client does not support Kerberos. To use this, configure: There should be one `%s` symbol in this string, which will be replaced by the username. +### TLS Client Certificate + +It's also possible to use client certificates on machines that have them for +authentication purposes instead of using LDAP or Kerberos. To do this, set +the environment variable `KRBAUTH_TLS_CERT_AUTH` to `1` or `yes`. + +Then, pass the WSGI environment variable `NGINX_SSL_CLIENT_VERIFY` from `nginx`, +setting it to the value of `$ssl_client_verify`, like this: + +```nginx +uwsgi_param NGINX_SSL_CLIENT_VERIFY "$ssl_client_verify"; +``` + +You most likely want to make client certificate verification optional if you +are using it with `nginx-krbauth`: + +```nginx +ssl_client_certificate /path/to/ca.crt; +ssl_verify_client optional; +``` + ## Example `nginx.conf` ```nginx diff --git a/nginx_krbauth.py b/nginx_krbauth.py index 232e18f..c536d9b 100644 --- a/nginx_krbauth.py +++ b/nginx_krbauth.py @@ -41,6 +41,7 @@ else: gssapi_creds = None COOKIE_SECURE = os.environ.get('KRBAUTH_SECURE_COOKIE', '1').lower() not in ('0', 'no') +TLS_CERT_AUTH = os.environ.get('KRBAUTH_TLS_CERT_AUTH', '0').lower() in ('1', 'yes') class Context: @@ -170,12 +171,21 @@ def auth_basic(context: Context, next_url: str) -> Response: return auth_success(context, next_url) +def check_tls() -> bool: + if not TLS_CERT_AUTH: + return False + + return request.environ.get('NGINX_SSL_CLIENT_VERIFY') == 'SUCCESS' + + @app.endpoint('krbauth.auth') def auth() -> Response: next_url = request.args.get('next', '/') context = Context.from_request() authorization = request.headers.get('Authorization', '') + if check_tls(): + return auth_success(context, next_url) if authorization.startswith('Negotiate '): return auth_spnego(context, next_url) if LDAP_USER_DN and authorization.startswith('Basic '): @@ -186,6 +196,6 @@ def auth() -> Response: @app.endpoint('krbauth.check') def check() -> Response: - if verify_cookie(request.cookies.get('krbauth'), Context.from_request()): + if check_tls() or verify_cookie(request.cookies.get('krbauth'), Context.from_request()): return Response(status=200) return Response(status=401)