From 03128e172e0242eba396e8487bdd8d6b0da52db3 Mon Sep 17 00:00:00 2001 From: Chetan Risbud Date: Thu, 23 Jan 2014 12:42:53 +0530 Subject: [PATCH] Rebase swiftkerbauth imported code with upstream Few changes have been merged to upstream swiftkerbauth repo. This commit brings it down to gluster-swift repo. Bringing below changes to gluster-swift repo in one go. http://review.gluster.org/#/c/6296/ http://review.gluster.org/#/c/6370/ http://review.gluster.org/#/c/6595/ http://review.gluster.org/#/c/6713/ http://review.gluster.org/#/c/6732/ Change-Id: I10dc12d75ec63fca313339fbc71e4f18071af552 Signed-off-by: Chetan Risbud Reviewed-on: http://review.gluster.org/6764 Reviewed-by: Prashanth Pai --- doc/markdown/swiftkerbauth/AD_server.md | 12 ++ doc/markdown/swiftkerbauth/ipa_server.md | 12 ++ .../swiftkerbauth/swiftkerbauth_guide.md | 58 ++++++- .../apachekerbauth/var/www/cgi-bin/swift-auth | 4 +- .../middleware/swiftkerbauth/kerbauth.py | 157 ++++++++++++++++-- .../swiftkerbauth/kerbauth_utils.py | 36 +++- .../middleware/swiftkerbauth/test_kerbauth.py | 142 +++++++++++++++- .../swiftkerbauth/test_kerbauth_utils.py | 11 +- 8 files changed, 407 insertions(+), 25 deletions(-) diff --git a/doc/markdown/swiftkerbauth/AD_server.md b/doc/markdown/swiftkerbauth/AD_server.md index c34f0f1..66d90f2 100644 --- a/doc/markdown/swiftkerbauth/AD_server.md +++ b/doc/markdown/swiftkerbauth/AD_server.md @@ -98,6 +98,18 @@ On client: ###Adding users and groups +The following convention is to be followed in creating group names: + + \_ + + \_ + +As of now, account=volume=group + +For example: + + AUTH\_test + Adding groups and users to the Windows domain is easy task. - Start -> Administrative Tools -> Active Directory Users & Computers diff --git a/doc/markdown/swiftkerbauth/ipa_server.md b/doc/markdown/swiftkerbauth/ipa_server.md index ef12b53..55e654e 100644 --- a/doc/markdown/swiftkerbauth/ipa_server.md +++ b/doc/markdown/swiftkerbauth/ipa_server.md @@ -107,6 +107,18 @@ Check if reverse resolution works : ## Adding users and groups +The following convention is to be followed in creating group names: + + \_ + + \_ + +As of now, account=volume=group + +For example: + + AUTH\_test + Create *auth_reseller_admin* user group > ipa group-add auth_reseller_admin --desc="Full access to all Swift accounts" diff --git a/doc/markdown/swiftkerbauth/swiftkerbauth_guide.md b/doc/markdown/swiftkerbauth/swiftkerbauth_guide.md index ef76ad0..12845a6 100644 --- a/doc/markdown/swiftkerbauth/swiftkerbauth_guide.md +++ b/doc/markdown/swiftkerbauth/swiftkerbauth_guide.md @@ -4,6 +4,7 @@ * [Creating HTTP Service Principal on IPA server] (#http-principal) * [Installing and configuring swiftkerbauth on IPA client] (#install-swiftkerbauth) * [Using swiftkerbauth] (#use-swiftkerbauth) +* [Configurable Parameters] (#config-swiftkerbauth) ## Installing Kerberos module for Apache on IPA client @@ -47,7 +48,8 @@ Copy keytab file to client: Add a HTTP Kerberos service principal: > c:\>ktpass.exe -princ HTTP/fcclient.winad.com@WINAD.COM -mapuser -> auth_admin@WINAD.COM -pass Redhat*123 -out c:\HTTP.keytab +> auth_admin@WINAD.COM -pass Redhat*123 -out c:\HTTP.keytab -crypto DES-CBC-CRC +> -kvno 0 Use winscp to copy HTTP.ketab file to /etc/httpd/conf/http.keytab @@ -101,6 +103,7 @@ Edit */etc/swift/proxy-server.conf* and add a new filter section as follows: [filter:kerbauth] use = egg:swiftkerbauth#kerbauth ext_authentication_url = http://client.rhelbox.com/cgi-bin/swift-auth + auth_mode=passive Add kerbauth to pipeline @@ -433,3 +436,56 @@ The --negotiate option is for curl to perform Kerberos authentication and --location-trusted is for curl to follow the redirect. [auth_kerb_module Configuration]: http://modauthkerb.sourceforge.net/configure.html + + +#### Get an authentication token when auth_mode=passive: +> curl -v -H 'X-Auth-User: test:auth_admin' -H 'X-Auth-Key: Redhat*123' http://127.0.0.1:8080/auth/v1.0 + +**NOTE**: X-Storage-Url response header can be returned only in passive mode. + + +##Configurable Parameters + +The kerbauth filter section in **/etc/swift/proxy-server.conf** looks something +like this: + + [filter:kerbauth] + use = egg:swiftkerbauth#kerbauth + ext_authentication_url = http://client.rhelbox.com/cgi-bin/swift-auth + auth_method = active + token_life = 86400 + debug_headers = yes + realm_name = RHELBOX.COM + +Of all the options listed above, specifying **ext\_authentication\_url** is +mandatory. The rest of the options are optional and have default values. + +#### ext\_authentication\_url +A URL specifying location of the swift-auth CGI script. Avoid using IP address. +Default value: None + +#### token_life +After how many seconds the cached information about an authentication token is +discarded. +Default value: 86400 + +#### debug_headers +When turned on, the response headers sent to the user will contain additional +debug information apart from the auth token. +Default value: yes + +#### auth_method +Set this to **"active"** when you want to allow access **only to clients +residing inside the domain**. In this mode, authentication is performed by +mod\_auth\_kerb using the Kerberos ticket bundled with the client request. +No username and password have to be specified to get a token. +Set this to **"passive"** when you want to allow access to clients residing +outside the domain. In this mode, authentication is performed by gleaning +username and password from request headers (X-Auth-User and X-Auth-Key) and +running kinit command against it. +Default value: passive + +#### realm_name +This is applicable only when the auth_method=passive. This option specifies +realm name if RHS server belongs to more than one realm and realm name is not +part of the username specified in X-Auth-User header. diff --git a/gluster/swift/common/middleware/swiftkerbauth/apachekerbauth/var/www/cgi-bin/swift-auth b/gluster/swift/common/middleware/swiftkerbauth/apachekerbauth/var/www/cgi-bin/swift-auth index 45df45c..11fe0e2 100755 --- a/gluster/swift/common/middleware/swiftkerbauth/apachekerbauth/var/www/cgi-bin/swift-auth +++ b/gluster/swift/common/middleware/swiftkerbauth/apachekerbauth/var/www/cgi-bin/swift-auth @@ -24,7 +24,7 @@ from swift.common.memcached import MemcacheRing from time import time, ctime from swiftkerbauth import MEMCACHE_SERVERS, TOKEN_LIFE, DEBUG_HEADERS from swiftkerbauth.kerbauth_utils import get_remote_user, get_auth_data, \ - generate_token, set_auth_data, get_groups + generate_token, set_auth_data, get_groups_from_username def main(): @@ -48,7 +48,7 @@ def main(): if not token: token = generate_token() expires = time() + TOKEN_LIFE - groups = get_groups(username) + groups = get_groups_from_username(username) set_auth_data(mc, username, token, expires, groups) print "X-Auth-Token: %s" % token diff --git a/gluster/swift/common/middleware/swiftkerbauth/kerbauth.py b/gluster/swift/common/middleware/swiftkerbauth/kerbauth.py index a1ba091..1a63a40 100644 --- a/gluster/swift/common/middleware/swiftkerbauth/kerbauth.py +++ b/gluster/swift/common/middleware/swiftkerbauth/kerbauth.py @@ -12,17 +12,22 @@ # See the License for the specific language governing permissions and # limitations under the License. -from time import time +import errno +from time import time, ctime from traceback import format_exc from eventlet import Timeout +from urllib import unquote -from swift.common.swob import Request +from swift.common.swob import Request, Response from swift.common.swob import HTTPBadRequest, HTTPForbidden, HTTPNotFound, \ - HTTPSeeOther + HTTPSeeOther, HTTPUnauthorized, HTTPServerError from swift.common.middleware.acl import clean_acl, parse_acl, referrer_allowed from swift.common.utils import cache_from_env, get_logger, \ split_path, config_true_value +from gluster.swift.common.middleware.swiftkerbauth.kerbauth_utils import \ + get_auth_data, generate_token, \ + set_auth_data, run_kinit, get_groups_from_username class KerbAuth(object): @@ -71,6 +76,10 @@ class KerbAuth(object): if self.auth_prefix[-1] != '/': self.auth_prefix += '/' self.token_life = int(conf.get('token_life', 86400)) + self.auth_method = conf.get('auth_method', 'passive') + self.debug_headers = config_true_value( + conf.get('debug_headers', 'yes')) + self.realm_name = conf.get('realm_name', None) self.allow_overrides = config_true_value( conf.get('allow_overrides', 't')) self.storage_url_scheme = conf.get('storage_url_scheme', 'default') @@ -109,8 +118,13 @@ class KerbAuth(object): env['reseller_request'] = True else: # Invalid token (may be expired) - return HTTPSeeOther( - location=self.ext_authentication_url)(env, start_response) + if self.auth_method == "active": + return HTTPSeeOther( + location=self.ext_authentication_url)(env, + start_response) + elif self.auth_method == "passive": + self.logger.increment('unauthorized') + return HTTPUnauthorized()(env, start_response) else: # With a non-empty reseller_prefix, I would like to be called # back for anonymous access to accounts I know I'm the @@ -234,7 +248,11 @@ class KerbAuth(object): self.logger.increment('forbidden') return HTTPForbidden(request=req) else: - return HTTPSeeOther(location=self.ext_authentication_url) + if self.auth_method == "active": + return HTTPSeeOther(location=self.ext_authentication_url) + elif self.auth_method == "passive": + self.logger.increment('unauthorized') + return HTTPUnauthorized(request=req) def handle(self, env, start_response): """ @@ -290,16 +308,37 @@ class KerbAuth(object): """ Handles the various `request for token and service end point(s)` calls. There are various formats to support the various auth servers in the - past. Examples:: + past. + + "Active Mode" usage: + All formats require GSS (Kerberos) authentication. GET /v1//auth GET /auth GET /v1.0 - All formats require GSS (Kerberos) authentication. + On successful authentication, the response will have X-Auth-Token + and X-Storage-Token set to the token to use with Swift. - On successful authentication, the response will have X-Auth-Token - set to the token to use with Swift. + "Passive Mode" usage:: + + GET /v1//auth + X-Auth-User: : or X-Storage-User: + X-Auth-Key: or X-Storage-Pass: + GET /auth + X-Auth-User: : or X-Storage-User: : + X-Auth-Key: or X-Storage-Pass: + GET /v1.0 + X-Auth-User: : or X-Storage-User: : + X-Auth-Key: or X-Storage-Pass: + + Values should be url encoded, "act%3Ausr" instead of "act:usr" for + example; however, for backwards compatibility the colon may be + included unencoded. + + On successful authentication, the response will have X-Auth-Token + and X-Storage-Token set to the token to use with Swift and + X-Storage-URL set to the URL to the default Swift cluster to use. :param req: The swob.Request to process. :returns: swob.Response, 2xx on success with data set as explained @@ -315,7 +354,103 @@ class KerbAuth(object): or pathsegs[0] in ('auth', 'v1.0')): return HTTPBadRequest(request=req) - return HTTPSeeOther(location=self.ext_authentication_url) + # Client is inside the domain + if self.auth_method == "active": + return HTTPSeeOther(location=self.ext_authentication_url) + + # Client is outside the domain + elif self.auth_method == "passive": + account, user, key = None, None, None + # Extract user, account and key from request + if pathsegs[0] == 'v1' and pathsegs[2] == 'auth': + account = pathsegs[1] + user = req.headers.get('x-storage-user') + if not user: + user = unquote(req.headers.get('x-auth-user', '')) + if user: + if ':' not in user: + return HTTPUnauthorized(request=req) + else: + account2, user = user.split(':', 1) + if account != account2: + return HTTPUnauthorized(request=req) + key = req.headers.get('x-storage-pass') + if not key: + key = unquote(req.headers.get('x-auth-key', '')) + elif pathsegs[0] in ('auth', 'v1.0'): + user = unquote(req.headers.get('x-auth-user', '')) + if not user: + user = req.headers.get('x-storage-user') + if user: + if ':' not in user: + return HTTPUnauthorized(request=req) + else: + account, user = user.split(':', 1) + key = unquote(req.headers.get('x-auth-key', '')) + if not key: + key = req.headers.get('x-storage-pass') + + if not (account or user or key): + # If all are not given, client may be part of the domain + return HTTPSeeOther(location=self.ext_authentication_url) + elif None in (key, user, account): + # If only one or two of them is given, but not all + return HTTPUnauthorized(request=req) + + # Run kinit on the user + if self.realm_name and "@" not in user: + user = user + "@" + self.realm_name + try: + ret = run_kinit(user, key) + except OSError as e: + if e.errno == errno.ENOENT: + return HTTPServerError("kinit command not found\n") + if ret != 0: + self.logger.warning("Failed: kinit %s", user) + if ret == -1: + self.logger.warning("Failed: kinit: Password has probably " + "expired.") + return HTTPServerError("Kinit is taking too long.\n") + return HTTPUnauthorized(request=req) + self.logger.debug("kinit succeeded") + + if "@" in user: + user = user.split("@")[0] + + # Check if user really belongs to the account + groups_list = get_groups_from_username(user).strip().split(",") + user_group = ("%s%s" % (self.reseller_prefix, account)).lower() + reseller_admin_group = \ + ("%sreseller_admin" % self.reseller_prefix).lower() + if user_group not in groups_list: + # Check if user is reseller_admin. If not, return Unauthorized. + # On AD/IdM server, auth_reseller_admin is a separate group + if reseller_admin_group not in groups_list: + return HTTPUnauthorized(request=req) + + mc = cache_from_env(req.environ) + if not mc: + raise Exception('Memcache required') + token, expires, groups = get_auth_data(mc, user) + if not token: + token = generate_token() + expires = time() + self.token_life + groups = get_groups_from_username(user) + set_auth_data(mc, user, token, expires, groups) + + headers = {'X-Auth-Token': token, + 'X-Storage-Token': token} + + if self.debug_headers: + headers.update({'X-Debug-Remote-User': user, + 'X-Debug-Groups:': groups, + 'X-Debug-Token-Life': self.token_life, + 'X-Debug-Token-Expires': ctime(expires)}) + + resp = Response(request=req, headers=headers) + resp.headers['X-Storage-Url'] = \ + '%s/v1/%s%s' % (resp.host_url, self.reseller_prefix, account) + return resp def filter_factory(global_conf, **local_conf): diff --git a/gluster/swift/common/middleware/swiftkerbauth/kerbauth_utils.py b/gluster/swift/common/middleware/swiftkerbauth/kerbauth_utils.py index 2fecf4b..599ef99 100644 --- a/gluster/swift/common/middleware/swiftkerbauth/kerbauth_utils.py +++ b/gluster/swift/common/middleware/swiftkerbauth/kerbauth_utils.py @@ -16,7 +16,8 @@ import re import random import grp -import subprocess +import signal +from subprocess import Popen, PIPE from time import time from gluster.swift.common.middleware.swiftkerbauth \ import TOKEN_LIFE, RESELLER_PREFIX @@ -82,13 +83,13 @@ def generate_token(): return token -def get_groups(username): +def get_groups_from_username(username): """Return a set of groups to which the user belongs to.""" # Retrieve the numerical group IDs. We cannot list the group names # because group names from Active Directory may contain spaces, and # we wouldn't be able to split the list of group names into its # elements. - p = subprocess.Popen(['id', '-G', username], stdout=subprocess.PIPE) + p = Popen(['id', '-G', username], stdout=PIPE) if p.wait() != 0: raise RuntimeError("Failure running id -G for %s" % username) (p_stdout, p_stderr) = p.communicate() @@ -105,3 +106,32 @@ def get_groups(username): groups = [username] + groups groups = ','.join(groups) return groups + + +def run_kinit(username, password): + """Runs kinit command as a child process and returns the status code.""" + kinit = Popen(['kinit', username], + stdin=PIPE, stdout=PIPE, stderr=PIPE) + kinit.stdin.write('%s\n' % password) + + # The following code handles a corner case where the Kerberos password + # has expired and a prompt is displayed to enter new password. Ideally, + # we would want to read from stdout but these are blocked reads. This is + # a hack to kill the process if it's taking too long! + + class Alarm(Exception): + pass + + def signal_handler(signum, frame): + raise Alarm + # Set the signal handler and a 1-second alarm + signal.signal(signal.SIGALRM, signal_handler) + signal.alarm(1) + try: + kinit.wait() # Wait for the child to exit + signal.alarm(0) # Reset the alarm + return kinit.returncode # Exit status of child on graceful exit + except Alarm: + # Taking too long, kill and return error + kinit.kill() + return -1 diff --git a/test/unit/common/middleware/swiftkerbauth/test_kerbauth.py b/test/unit/common/middleware/swiftkerbauth/test_kerbauth.py index 642c4d6..537b8d3 100644 --- a/test/unit/common/middleware/swiftkerbauth/test_kerbauth.py +++ b/test/unit/common/middleware/swiftkerbauth/test_kerbauth.py @@ -18,9 +18,9 @@ import errno import unittest from time import time from mock import patch, Mock -from gluster.swift.common.middleware.swiftkerbauth import kerbauth as auth from test.unit import FakeMemcache from swift.common.swob import Request, Response +from gluster.swift.common.middleware.swiftkerbauth import kerbauth as auth EXT_AUTHENTICATION_URL = "127.0.0.1" REDIRECT_STATUS = 303 # HTTPSeeOther @@ -80,7 +80,8 @@ class TestKerbAuth(unittest.TestCase): patch_filter_factory() def setUp(self): - self.test_auth = auth.filter_factory({})(FakeApp()) + self.test_auth = \ + auth.filter_factory({'auth_method': 'active'})(FakeApp()) self.test_auth_passive = \ auth.filter_factory({'auth_method': 'passive'})(FakeApp()) @@ -105,6 +106,10 @@ class TestKerbAuth(unittest.TestCase): app = FakeApp() ath = auth.filter_factory({})(app) self.assertEquals(ath.reseller_prefix, 'AUTH_') + ath = auth.filter_factory({'reseller_prefix': 'TEST'})(app) + self.assertEquals(ath.reseller_prefix, 'TEST_') + ath = auth.filter_factory({'reseller_prefix': 'TEST_'})(app) + self.assertEquals(ath.reseller_prefix, 'TEST_') def test_auth_prefix_init(self): app = FakeApp() @@ -130,6 +135,19 @@ class TestKerbAuth(unittest.TestCase): self.assertEquals(req.environ['swift.authorize'], self.test_auth.denied_response) + def test_passive_top_level_deny(self): + req = self._make_request('/') + resp = req.get_response(self.test_auth_passive) + self.assertEquals(resp.status_int, 401) + self.assertEquals(req.environ['swift.authorize'], + self.test_auth_passive.denied_response) + + def test_passive_deny_invalid_token(self): + req = self._make_request('/v1/AUTH_account', + headers={'X-Auth-Token': 'AUTH_t'}) + resp = req.get_response(self.test_auth_passive) + self.assertEquals(resp.status_int, 401) + def test_override_asked_for_and_allowed(self): self.test_auth = \ auth.filter_factory({'allow_overrides': 'true'})(FakeApp()) @@ -249,6 +267,126 @@ class TestKerbAuth(unittest.TestCase): resp = self.test_auth.handle_get_token(req) self.assertEquals(resp.status_int, 404) + def test_passive_handle_get_token_no_user_or_key(self): + #No user and key + req = self._make_request('/auth/v1.0') + resp = self.test_auth_passive.handle_get_token(req) + self.assertEquals(resp.status_int, REDIRECT_STATUS) + #User given but no key + req = self._make_request('/auth/v1.0', + headers={'X-Auth-User': 'test:user'}) + resp = self.test_auth_passive.handle_get_token(req) + self.assertEquals(resp.status_int, 401) + + def test_passive_handle_get_token_account_in_req_path(self): + req = self._make_request('/v1/test/auth', + headers={'X-Auth-User': 'test:user', + 'X-Auth-Key': 'password'}) + _mock_run_kinit = Mock(return_value=0) + _mock_get_groups = Mock(return_value="user,auth_test") + with patch('gluster.swift.common.middleware.swiftkerbauth.kerbauth.run_kinit', _mock_run_kinit): + with patch('gluster.swift.common.middleware.swiftkerbauth.kerbauth.get_groups_from_username', + _mock_get_groups): + resp = self.test_auth_passive.handle_get_token(req) + _mock_run_kinit.assert_called_once_with('user', 'password') + self.assertEquals(_mock_get_groups.call_count, 2) + self.assertEquals(resp.status_int, 200) + self.assertTrue(resp.headers['X-Auth-Token'] is not None) + self.assertTrue(resp.headers['X-Storage-Token'] is not None) + self.assertTrue(resp.headers['X-Storage-Url'] is not None) + + def test_passive_handle_get_token_user_invalid_or_no__account(self): + #X-Auth-User not in acc:user format + req = self._make_request('/auth/v1.0', + headers={'X-Auth-User': 'user'}) + resp = self.test_auth_passive.handle_get_token(req) + self.assertEquals(resp.status_int, 401) + req = self._make_request('/v1/test/auth', + headers={'X-Auth-User': 'user'}) + resp = self.test_auth_passive.handle_get_token(req) + self.assertEquals(resp.status_int, 401) + # Account name mismatch + req = self._make_request('/v1/test/auth', + headers={'X-Auth-User': 'wrongacc:user'}) + resp = self.test_auth_passive.handle_get_token(req) + self.assertEquals(resp.status_int, 401) + + def test_passive_handle_get_token_no_kinit(self): + req = self._make_request('/auth/v1.0', + headers={'X-Auth-User': 'test:user', + 'X-Auth-Key': 'password'}) + _mock_run_kinit = Mock(side_effect=OSError(errno.ENOENT, + os.strerror(errno.ENOENT))) + with patch('gluster.swift.common.middleware.swiftkerbauth.kerbauth.run_kinit', _mock_run_kinit): + resp = self.test_auth_passive.handle_get_token(req) + self.assertEquals(resp.status_int, 500) + self.assertTrue("kinit command not found" in resp.body) + _mock_run_kinit.assert_called_once_with('user', 'password') + + def test_passive_handle_get_token_kinit_fail(self): + req = self._make_request('/auth/v1.0', + headers={'X-Auth-User': 'test:user', + 'X-Auth-Key': 'password'}) + _mock_run_kinit = Mock(return_value=1) + with patch('gluster.swift.common.middleware.swiftkerbauth.kerbauth.run_kinit', _mock_run_kinit): + resp = self.test_auth_passive.handle_get_token(req) + self.assertEquals(resp.status_int, 401) + _mock_run_kinit.assert_called_once_with('user', 'password') + + def test_passive_handle_get_token_kinit_success_token_not_present(self): + req = self._make_request('/auth/v1.0', + headers={'X-Auth-User': 'test:user', + 'X-Auth-Key': 'password'}) + _mock_run_kinit = Mock(return_value=0) + _mock_get_groups = Mock(return_value="user,auth_test") + with patch('gluster.swift.common.middleware.swiftkerbauth.kerbauth.run_kinit', _mock_run_kinit): + with patch('gluster.swift.common.middleware.swiftkerbauth.kerbauth.get_groups_from_username', + _mock_get_groups): + resp = self.test_auth_passive.handle_get_token(req) + _mock_run_kinit.assert_called_once_with('user', 'password') + self.assertEquals(_mock_get_groups.call_count, 2) + self.assertEquals(resp.status_int, 200) + self.assertTrue(resp.headers['X-Auth-Token'] is not None) + self.assertTrue(resp.headers['X-Storage-Token'] is not None) + self.assertTrue(resp.headers['X-Storage-Url'] is not None) + + def test_passive_handle_get_token_kinit_realm_and_memcache(self): + req = self._make_request('/auth/v1.0', + headers={'X-Auth-User': 'test:user', + 'X-Auth-Key': 'password'}) + req.environ['swift.cache'] = None + _auth_passive = \ + auth.filter_factory({'auth_method': 'passive', + 'realm_name': 'EXAMPLE.COM'})(FakeApp()) + _mock_run_kinit = Mock(return_value=0) + _mock_get_groups = Mock(return_value="user,auth_test") + with patch('gluster.swift.common.middleware.swiftkerbauth.kerbauth.run_kinit', _mock_run_kinit): + with patch('gluster.swift.common.middleware.swiftkerbauth.kerbauth.get_groups_from_username', + _mock_get_groups): + try: + _auth_passive.handle_get_token(req) + except Exception as e: + self.assertTrue(e.args[0].startswith("Memcache " + "required")) + else: + self.fail("Expected Exception - Memcache required") + _mock_run_kinit.assert_called_once_with('user@EXAMPLE.COM', 'password') + _mock_get_groups.assert_called_once_with('user') + + def test_passive_handle_get_token_user_in_any__account(self): + req = self._make_request('/auth/v1.0', + headers={'X-Auth-User': 'test:user', + 'X-Auth-Key': 'password'}) + _mock_run_kinit = Mock(return_value=0) + _mock_get_groups = Mock(return_value="user,auth_blah") + with patch('gluster.swift.common.middleware.swiftkerbauth.kerbauth.run_kinit', _mock_run_kinit): + with patch('gluster.swift.common.middleware.swiftkerbauth.kerbauth.get_groups_from_username', + _mock_get_groups): + resp = self.test_auth_passive.handle_get_token(req) + self.assertEquals(resp.status_int, 401) + _mock_run_kinit.assert_called_once_with('user', 'password') + _mock_get_groups.assert_called_once_with('user') + def test_handle(self): req = self._make_request('/auth/v1.0') resp = req.get_response(self.test_auth) diff --git a/test/unit/common/middleware/swiftkerbauth/test_kerbauth_utils.py b/test/unit/common/middleware/swiftkerbauth/test_kerbauth_utils.py index c5da168..2a4e90b 100644 --- a/test/unit/common/middleware/swiftkerbauth/test_kerbauth_utils.py +++ b/test/unit/common/middleware/swiftkerbauth/test_kerbauth_utils.py @@ -17,7 +17,6 @@ import unittest import re from time import time from test.unit import FakeMemcache -from gluster.swift.common.middleware.swiftkerbauth import kerbauth as auth from gluster.swift.common.middleware.swiftkerbauth import kerbauth_utils as ku @@ -63,15 +62,15 @@ class TestKerbUtils(unittest.TestCase): def test_generate_token(self): token = ku.generate_token() matches = re.match('AUTH_tk[a-f0-9]{32}', token) - self.assertNotEqual(matches, None) + self.assertTrue(matches is not None) - def test_get_groups(self): - groups = ku.get_groups("root") + def test_get_groups_from_username(self): + groups = ku.get_groups_from_username("root") self.assertTrue("root" in groups) - def test_get_groups_err(self): + def test_get_groups_from_username_err(self): try: - ku.get_groups("Zroot") + ku.get_groups_from_username("Zroot") except RuntimeError as err: self.assertTrue(err.args[0].startswith("Failure running id -G")) else: