diff --git a/LICENSE b/LICENSE index 64855a6..a419e46 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2020 D. E. Shaw & Co., L.P. +Copyright 2013-2020 D. E. Shaw & Co., L.P. All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/README.rst b/README.rst index 8831ec2..e783726 100644 --- a/README.rst +++ b/README.rst @@ -4,8 +4,7 @@ WSGI-Kerberos WSGI-Kerberos is `WSGI`_ Middleware which implements `Kerberos`_ authentication. It makes it easy to add Kerberos authentication to any WSGI application. -Its only dependency is `python-kerberos`_ and it's been tested against version -1.1.1. +Its only dependency is `python-kerberos`_ and it's been tested up to version 1.3.0 You can install the requirements from PyPI with ``easy_install`` or ``pip`` or download them by hand. @@ -19,11 +18,7 @@ The official copy of this documentation is available at `Read the Docs`_. Installation ------------ -Install the extension with one of the following commands:: - - $ easy_install WSGI-Kerberos - -or alternatively if you have ``pip`` installed:: +Install the extension with pip: $ pip install WSGI-Kerberos @@ -31,8 +26,8 @@ How to Use ---------- To integrate ``WSGI-Kerberos`` into your application you'll need to generate -your keytab set the environment variable ``KRB5_KTNAME`` in your shell to the -location of the keytab file. +your keytab and set the environment variable ``KRB5_KTNAME`` in your shell to +the location of the keytab file. After that, it should be as easy as passing your application to the ``KerberosAuthMiddleware`` constructor. All requests destined for the @@ -47,31 +42,14 @@ For example:: def example(environ, start_response): start_response('200 OK', [('Content-Type', 'text/plain')]) - return ['Hello, %s' % environ['REMOTE_USER']] + return ['Hello, {}'.format(environ['REMOTE_USER']).encode()] if __name__ == '__main__': app = KerberosAuthMiddleware(example) - http = make_server('', 80, app) + http = make_server('', 8080, app) http.serve_forever() -``WSGI-Kerberos`` assumes that the service will be running using the hostname of -the host on which the application is run. If this is not the case, you can -override it by passing in a hostname to the ``KerberosAuthMiddleware`` -constructor:: - - from wsgiref.simple_server import make_server - from wsgi_kerberos import KerberosAuthMiddleware - - def example(environ, start_response): - start_response('200 OK', [('Content-Type', 'text/plain')]) - return ['Hello, %s' % environ['REMOTE_USER']] - - if __name__ == '__main__': - app = KerberosAuthMiddleware(example, hostname='example.com') - http = make_server('', 80, app) - http.serve_forever() - ``WSGI-Kerberos`` assumes that every request should be authenticated. If this is not the case, you can override it by passing in a callback named ``auth_required_callback`` to the @@ -83,7 +61,7 @@ request and passed the wsgi environment object:: def example(environ, start_response): start_response('200 OK', [('Content-Type', 'text/plain')]) - return ['Hello, %s' % environ.get('REMOTE_USER', 'ANONYMOUS')] + return ['Hello, {}'.format(environ.get('REMOTE_USER', 'ANONYMOUS').encode()] def authenticate(environ): return environ['PATH_INFO'].startswith('/protected'): @@ -91,7 +69,7 @@ request and passed the wsgi environment object:: if __name__ == '__main__': app = KerberosAuthMiddleware(example, auth_required_callback=authenticate) - http = make_server('', 80, app) + http = make_server('', 8080, app) http.serve_forever() @@ -110,13 +88,13 @@ These can be customized:: def example(environ, start_response): start_response('200 OK', [('Content-Type', 'text/plain')]) - return ['Hello, %s' % environ['REMOTE_USER']] + return ['Hello, {}'.format(environ['REMOTE_USER']).encode()] if __name__ == '__main__': app = KerberosAuthMiddleware(example, unauthorized='Authentication Required', forbidden='Authentication Failed') - http = make_server('', 80, app) + http = make_server('', 8080, app) http.serve_forever() You can also change the ``Content-Types`` by passing in string/content-type @@ -127,7 +105,7 @@ tuples:: def example(environ, start_response): start_response('200 OK', [('Content-Type', 'text/plain')]) - return ['Hello, %s' % environ['REMOTE_USER']] + return ['Hello, {}'.format(environ['REMOTE_USER']).encode()] if __name__ == '__main__': forbidden=''' @@ -149,7 +127,25 @@ tuples:: app = KerberosAuthMiddleware(example, unauthorized=(unauthorized, 'text/html'), forbidden=(forbidden, 'text/plain')) - http = make_server('', 80, app) + http = make_server('', 8080, app) + http.serve_forever() + + + +``WSGI-Kerberos`` will authenticate the request using any hostname in the +keytab file. You can restrict requests to one specific hostname by passing it +to the ``KerberosAuthMiddleware`` constructor:: + + from wsgiref.simple_server import make_server + from wsgi_kerberos import KerberosAuthMiddleware + + def example(environ, start_response): + start_response('200 OK', [('Content-Type', 'text/plain')]) + return ['Hello, {}'.format(environ['REMOTE_USER']).encode()] + + if __name__ == '__main__': + app = KerberosAuthMiddleware(example, hostname='example.com') + http = make_server('', 8080, app) http.serve_forever() @@ -177,14 +173,26 @@ Full Example ------------ To see a simple example, you can download the code `from github -`_. It is in the example directory. +`_. It is in the example directory. Changes ------- -1.0.0 -````` +1.0.0 (2020-12-28) +`````````````````` +- `hostname` no longer needs to be specified in KerberosAuthMiddleware + constructor - any hostname in the keytab will be accepted +- Set REMOTE_USER when valid auth is provided, even if not required +- Limit the number of bytes read in request bodies on auth failure to + mitigate a possible DoS attack. New parameter `read_max_on_auth_fail` + can be set to customize or remove the limit +- Support clients which don't request mutual authentication +- Log Kerberos errors +- Validate first word in Authorization header +- Python 3 compatibility fixes +- Various bug fixes - Update license from BSD-2-Clause to BSD-3-Clause +- Project was moved to the D. E. Shaw Org 0.2.0 ````` diff --git a/docs/conf.py b/docs/conf.py index 1936789..326177b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -17,7 +17,7 @@ # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, os.path.abspath('..')) - +import wsgi_kerberos # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. @@ -41,16 +41,16 @@ # General information about the project. project = u'WSGI-Kerberos' -copyright = u'2013, Michael Komitee' +copyright = u'2013-2020, D. E. Shaw & Co., L.P. and contributors' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '0.2.0' +version = wsgi_kerberos.__version__ # The full version, including alpha/beta/rc tags. -release = '0.2.0' +release = wsgi_kerberos.__version__ # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/example/example_application.py b/example/example_application.py index 22346c1..6ed86c8 100755 --- a/example/example_application.py +++ b/example/example_application.py @@ -1,5 +1,8 @@ #!/usr/bin/env python -import sys +import logging +from wsgi_kerberos import KerberosAuthMiddleware +from wsgiref.simple_server import make_server + def example(environ, start_response): user = environ.get('REMOTE_USER', 'ANONYMOUS') @@ -7,12 +10,11 @@ def example(environ, start_response): data = "Hello {}".format(user) return [data.encode()] + +application = KerberosAuthMiddleware(example) + + if __name__ == '__main__': - from wsgiref.simple_server import make_server - from wsgi_kerberos import KerberosAuthMiddleware - from socket import gethostname - import logging logging.basicConfig(level=logging.DEBUG) - application = KerberosAuthMiddleware(example) - server = make_server(gethostname(), 8080, application) + server = make_server('', 8080, application) server.serve_forever() diff --git a/setup.py b/setup.py index 0d7327f..4c3c6b1 100644 --- a/setup.py +++ b/setup.py @@ -9,18 +9,26 @@ * `documentation `_ * `development version - `_ + `_ """ +import os +import re from setuptools import setup +lib = os.path.join(os.path.dirname(__file__), "wsgi_kerberos.py") +with open(lib) as fh: + version = re.search(r"""__version__ = ["'](.*?)["']""", fh.read()).group(1) + setup(name='WSGI-Kerberos', - version='1.0.0', - url='http://github.com/mkomitee/wsgi-kerberos', + version=version, + url='https://github.com/deshaw/wsgi-kerberos', license='BSD-3-Clause', author='Michael Komitee', author_email='mkomitee@gmail.com', + maintainer='Vitaly Shupak', + maintainer_email='vitaly.shupak@deshaw.com', description='Kerberos authentication support in WSGI Middleware', long_description=__doc__, py_modules=['wsgi_kerberos'], diff --git a/wsgi_kerberos.py b/wsgi_kerberos.py index 0286721..d45501e 100755 --- a/wsgi_kerberos.py +++ b/wsgi_kerberos.py @@ -9,6 +9,8 @@ import socket import sys +__version__ = '1.0.0' + LOG = logging.getLogger(__name__) LOG.addHandler(logging.NullHandler())