From bacf8ef72f9b64c864fc553aeff628c98859a145 Mon Sep 17 00:00:00 2001 From: Matt Jia Date: Dec 01 2017 00:11:27 +0000 Subject: add ssl cert auth support https://pagure.io/waiverdb/issue/76 --- diff --git a/tests/conftest.py b/tests/conftest.py index 84c111c..8a04e6b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -53,3 +53,8 @@ def client(app): @pytest.fixture() def enable_kerberos(app, monkeypatch): monkeypatch.setitem(app.config, 'AUTH_METHOD', 'Kerberos') + + +@pytest.fixture() +def enable_ssl(app, monkeypatch): + monkeypatch.setitem(app.config, 'AUTH_METHOD', 'SSL') diff --git a/tests/test_auth.py b/tests/test_auth.py index a06ccce..71a896d 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -90,3 +90,30 @@ class TestOIDCAuthentication(object): request.headers.__contains__.side_effect = headers.__contains__ user, header = waiverdb.auth.get_user(request) assert user == name + + +@pytest.mark.usefixtures('enable_ssl') +class TestSSLAuthentication(object): + def test_SSL_CLIENT_VERIFY_is_not_set_should_raise_error(self): + with pytest.raises(Unauthorized) as excinfo: + request = mock.MagicMock() + waiverdb.auth.get_user(request) + assert 'Cannot verify client' in excinfo.value.get_description() + + def test_SSL_CLIENT_S_DN_is_not_set_should_raise_error(self): + with pytest.raises(Unauthorized) as excinfo: + request = mock.MagicMock(environ={'SSL_CLIENT_VERIFY': 'SUCCESS'}) + waiverdb.auth.get_user(request) + assert 'Unable to get user information (DN) from the client certificate' \ + in excinfo.value.get_description() + + def test_good_ssl_cert(self): + # http://vsbattles.wikia.com/wiki/Son_Goku + name = 'Son Goku' + ssl = { + 'SSL_CLIENT_VERIFY': 'SUCCESS', + 'SSL_CLIENT_S_DN': name + } + request = mock.MagicMock(environ=ssl) + user, header = waiverdb.auth.get_user(request) + assert user == name diff --git a/waiverdb/auth.py b/waiverdb/auth.py index 9da29b2..4e6bb01 100644 --- a/waiverdb/auth.py +++ b/waiverdb/auth.py @@ -112,6 +112,15 @@ def get_user(request): user = user.split("@")[0] if kerberos_token is not None: headers = {'WWW-Authenticate': ' '.join(['negotiate', kerberos_token])} + elif current_app.config['AUTH_METHOD'] == 'SSL': + # Nginx sets SSL_CLIENT_VERIFY and SSL_CLIENT_S_DN in request.environ + # when doing SSL authentication. + ssl_client_verify = request.environ.get('SSL_CLIENT_VERIFY') + if ssl_client_verify != 'SUCCESS': + raise Unauthorized('Cannot verify client: %s' % ssl_client_verify) + if not request.environ.get('SSL_CLIENT_S_DN'): + raise Unauthorized('Unable to get user information (DN) from the client certificate') + user = request.environ.get('SSL_CLIENT_S_DN') elif current_app.config['AUTH_METHOD'] == 'dummy': # Blindly accept any username. For testing purposes only of course! if not request.authorization: diff --git a/waiverdb/config.py b/waiverdb/config.py index 910f0e5..120672f 100644 --- a/waiverdb/config.py +++ b/waiverdb/config.py @@ -22,7 +22,7 @@ class Config(object): # need to explicitly turn this off # https://github.com/flask-restful/flask-restful/issues/449 ERROR_404_HELP = False - AUTH_METHOD = 'OIDC' # Specify OIDC or Kerberos for authentication + AUTH_METHOD = 'OIDC' # Specify OIDC, Kerberos or SSL for authentication # Change it if the Kerberos service is not running on which the waiverdb is run. KERBEROS_HTTP_HOST = None # Set this to True or False to enable publishing to a message bus