Merge lp:~khussein/swift/authn into lp:~hudson-openstack/swift/trunk

Proposed by Khaled Hussein
Status: Superseded
Proposed branch: lp:~khussein/swift/authn
Merge into: lp:~hudson-openstack/swift/trunk
Diff against target: 1008 lines (+442/-250)
7 files modified
.unittests (+1/-1)
doc/source/development_saio.rst (+9/-3)
setup.py (+4/-2)
swift/common/middleware/devauthn.py (+145/-0)
swift/common/middleware/devauthz.py (+48/-109)
swift/common/middleware/papiauth.py (+62/-0)
test/unit/common/middleware/test_auth.py (+173/-135)
To merge this branch: bzr merge lp:~khussein/swift/authn
Reviewer Review Type Date Requested Status
Chuck Thier (community) Needs Fixing
gholt Pending
Review via email: mp+45532@code.launchpad.net

This proposal supersedes a proposal from 2010-12-08.

This proposal has been superseded by a proposal from 2011-01-11.

Description of the change

Implemented the proposed protocol to handle authentication in OpenStack services.

To post a comment you must log in.
Revision history for this message
Mike Barton (redbo) wrote : Posted in a previous version of this proposal

> self.response_status = status

self.response_status is storing per-request info in a shared object. That could be wrong under concurrency.

> ''.join(response_itr)
> return [resp.read()]
> response.content_length = sum(map(len, response.app_iter))

Storing many GB of data in RAM is a bad idea.

> usersConfig.readfp(open('/etc/openstack/users.ini'))

You shouldn't re-read and parse the basic auth credentials file on every request. The local imports there are kind of ugly too.

> def validateCreds(self, username, password):

only major pep8 violation I see is those camel caps.

> - 'auth=swift.auth.server:app_factory',
> + #'auth=swift.auth.server:app_factory',
> + 'auth=swift.auth.basicauth:app_factory',

Was leaving it this way a mistake? The basic auth isn't super useful right now, and removing the devauth filter completely breaks our dev and testing environments.

review: Needs Fixing
Revision history for this message
gholt (gholt) wrote : Posted in a previous version of this proposal

We meant for this to be a work-in-progress; sorry.

Revision history for this message
gholt (gholt) wrote : Posted in a previous version of this proposal

Oh, and these weren't the droids you were looking for anyhow. Move along; move along.

Revision history for this message
Khaled Hussein (khussein) wrote : Posted in a previous version of this proposal

The proxy-server config now would be [auth1 devauth papiauth]

Revision history for this message
Chuck Thier (cthier) wrote :

Initial comments:

1. There is one unit test failure
2. There are 9 functional test failures
3. There are no unit tests for the new pieces of middleware
4. There are no docs that explain how/when to use the different pieces of middleware
5. Do the saio or multiserver install docs need to change?
6. auth1 is a poor choice for the module name and class name
7. Is anything going to need to change when we move to swauth?
8. PEP8:

cthier@storage1:~/swift/authn$ pep8 -r swift/common/middleware/auth1.py
swift/common/middleware/auth1.py:24:1: E302 expected 2 blank lines, found 1
swift/common/middleware/auth1.py:97:1: W293 blank line contains whitespace
swift/common/middleware/auth1.py:112:75: W291 trailing whitespace
swift/common/middleware/auth1.py:113:76: W291 trailing whitespace
swift/common/middleware/auth1.py:140:1: E302 expected 2 blank lines, found 1

cthier@storage1:~/swift/authn$ pep8 -r swift/common/middleware/papiauth.py
swift/common/middleware/papiauth.py:43:50: W291 trailing whitespace
swift/common/middleware/papiauth.py:63:1: W391 blank line at end of file
cthier@storage1:~/swift/authn$ pep8 -r swift/common/middleware/auth.py

cthier@storage1:~/swift/authn$ pep8 -r swift/common/middleware/devauth.py
swift/common/middleware/devauth.py:40:20: W291 trailing whitespace

review: Needs Fixing
Revision history for this message
gholt (gholt) wrote :

As I understood things, the DevAuth that we have always used was not going to change except that it was going to set an additional header instead of just setting REMOTE_USER. All the new auth stuff was going to be new files. What happened with that plan?

Revision history for this message
Khaled Hussein (khussein) wrote :

Following the 'public or anonymous access' use case that you've mentioned, we've discussed adding the delegated mode, which is documented in our blueprint. So, this added a couple of new changes to the source code. It also lead us to refactor the code base a little bit so that we separate the two concerns: authentication and authorization into two separate modules.

lp:~khussein/swift/authn updated
160. By Khaled Hussein

documentation change

161. By Khaled Hussein

merge trunk

Unmerged revisions

161. By Khaled Hussein

merge trunk

160. By Khaled Hussein

documentation change

159. By Khaled Hussein

saio documentation changes

158. By Khaled Hussein

PEP8 Stuff :)

157. By Khaled Hussein

Refactored and Added unit tests

156. By Khaled Hussein

fixing conflicts

155. By Khaled Hussein

fixed functional tests

154. By Khaled Hussein

setup.py config changes

153. By Khaled Hussein

Merged trunk

152. By Khaled Hussein

Fixed unit tests

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.unittests'
2--- .unittests 2010-07-13 03:34:34 +0000
3+++ .unittests 2011-01-11 20:54:28 +0000
4@@ -1,4 +1,4 @@
5 #!/bin/bash
6
7-nosetests test/unit --exe --with-coverage --cover-package swift --cover-erase
8+nosetests test/unit/ --exe --with-coverage --cover-package swift --cover-erase
9 rm -f .coverage
10
11=== modified file 'doc/source/development_saio.rst'
12--- doc/source/development_saio.rst 2010-12-02 01:08:49 +0000
13+++ doc/source/development_saio.rst 2011-01-11 20:54:28 +0000
14@@ -240,7 +240,7 @@
15
16 [pipeline:main]
17 # For DevAuth:
18- pipeline = healthcheck cache auth proxy-server
19+ pipeline = healthcheck cache devauthn devauthz papiauth proxy-server
20 # For Swauth:
21 # pipeline = healthcheck cache swauth proxy-server
22
23@@ -249,8 +249,14 @@
24 allow_account_management = true
25
26 # Only needed for DevAuth
27- [filter:auth]
28- use = egg:swift#auth
29+ [filter:devauthn]
30+ use = egg:swift#devauthn
31+
32+ [filter:devauthz]
33+ use = egg:swift#devauthz
34+
35+ [filter:papiauth]
36+ use = egg:swift#papiauth
37
38 # Only needed for Swauth
39 [filter:swauth]
40
41=== modified file 'setup.py'
42--- setup.py 2011-01-05 15:17:36 +0000
43+++ setup.py 2011-01-11 20:54:28 +0000
44@@ -1,5 +1,5 @@
45 #!/usr/bin/python
46-# Copyright (c) 2010-2011 OpenStack, LLC.
47+# Copyright (c) 2010 OpenStack, LLC.
48 #
49 # Licensed under the Apache License, Version 2.0 (the "License");
50 # you may not use this file except in compliance with the License.
51@@ -94,7 +94,9 @@
52 'auth=swift.auth.server:app_factory',
53 ],
54 'paste.filter_factory': [
55- 'auth=swift.common.middleware.auth:filter_factory',
56+ 'devauthn=swift.common.middleware.devauthn:filter_factory',
57+ 'devauthz=swift.common.middleware.devauthz:filter_factory',
58+ 'papiauth=swift.common.middleware.papiauth:filter_factory',
59 'swauth=swift.common.middleware.swauth:filter_factory',
60 'healthcheck=swift.common.middleware.healthcheck:filter_factory',
61 'memcache=swift.common.middleware.memcache:filter_factory',
62
63=== added file 'swift/common/middleware/devauthn.py'
64--- swift/common/middleware/devauthn.py 1970-01-01 00:00:00 +0000
65+++ swift/common/middleware/devauthn.py 2011-01-11 20:54:28 +0000
66@@ -0,0 +1,145 @@
67+# Copyright (c) 2010 OpenStack, LLC.
68+#
69+# Licensed under the Apache License, Version 2.0 (the "License");
70+# you may not use this file except in compliance with the License.
71+# You may obtain a copy of the License at
72+#
73+# http://www.apache.org/licenses/LICENSE-2.0
74+#
75+# Unless required by applicable law or agreed to in writing, software
76+# distributed under the License is distributed on an "AS IS" BASIS,
77+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
78+# implied.
79+# See the License for the specific language governing permissions and
80+# limitations under the License.
81+
82+from time import time
83+
84+from eventlet.timeout import Timeout
85+from webob.exc import HTTPUnauthorized
86+
87+from swift.common.bufferedhttp import http_connect_raw as http_connect
88+from swift.common.utils import cache_from_env, TRUE_VALUES
89+
90+
91+class DevAuthN(object):
92+ """Auth Middleware that uses the dev auth server."""
93+
94+ def __init__(self, app, conf):
95+ self.app = app
96+ self.conf = conf
97+ self.reseller_prefix = conf.get('reseller_prefix', 'AUTH').strip()
98+ if self.reseller_prefix and self.reseller_prefix[-1] != '_':
99+ self.reseller_prefix += '_'
100+ self.auth_host = conf.get('ip', '127.0.0.1')
101+ self.auth_prefix = conf.get('prefix', '/')
102+ self.auth_port = int(conf.get('port', 11000))
103+ self.ssl = conf.get('ssl', 'false').lower() in TRUE_VALUES
104+ self.timeout = int(conf.get('node_timeout', 10))
105+ self.delegated = int(conf.get('delegated', 0))
106+
107+ def __call__(self, env, start_response):
108+ """
109+ Accepts a standard WSGI application call and authenticates the request.
110+ For an authenticated request, SWIFT_GROUPS will be set to a comma
111+ separated list of the user's groups. It'll also set X-Authorization
112+ header to 'Proxy [Username]'. If it is running in a delegated mode, it
113+ sets the X-Identity-Status header to 'Confirmed' if the token is valid,
114+ or 'Indeterminate' if the token doesn't exist.
115+
116+ With a non-empty reseller prefix, acts as the definitive auth service
117+ for just tokens and accounts that begin with that prefix, but will deny
118+ requests outside this prefix if no other auth middleware overrides it.
119+
120+ With an empty reseller prefix, acts as the definitive auth service only
121+ for tokens that validate to a non-empty set of groups. For all other
122+ requests, acts as the fallback auth service when no other auth
123+ middleware overrides it.
124+ """
125+
126+ def custom_start_response(status, headers):
127+ if self.delegated:
128+ headers.append(('WWW-Authenticate', "Basic realm='API Realm'"))
129+ return start_response(status, headers)
130+
131+ token = env.get('HTTP_X_AUTH_TOKEN', env.get('HTTP_X_STORAGE_TOKEN'))
132+ if token and token.startswith(self.reseller_prefix):
133+ # Note: Empty reseller_prefix will match all tokens.
134+ # Attempt to auth my token with my auth server
135+ groups = \
136+ self.get_groups(token, memcache_client=cache_from_env(env))
137+ if groups:
138+ user = groups and groups.split(',', 1)[0] or ''
139+ env['SWIFT_GROUPS'] = groups
140+ env['HTTP_X_AUTHORIZATION'] = "Proxy " + user
141+ if self.delegated:
142+ env['HTTP_X_IDENTITY_STATUS'] = "Confirmed"
143+ # We know the proxy logs the token, so we augment it just
144+ # a bit to also log the authenticated user.
145+ env['HTTP_X_AUTH_TOKEN'] = '%s,%s' % (user, token)
146+ else:
147+ if self.delegated and not self.reseller_prefix:
148+ env['HTTP_X_IDENTITY_STATUS'] = "Invalid"
149+ else:
150+ # Unauthorized token
151+ return HTTPUnauthorized()(env, custom_start_response)
152+ else:
153+ env['HTTP_X_AUTHORIZATION'] = "Proxy"
154+ if self.delegated:
155+ env['HTTP_X_IDENTITY_STATUS'] = "Indeterminate"
156+ else:
157+ return HTTPUnauthorized()(env, custom_start_response)
158+
159+ env['HTTP_AUTHORIZATION'] = "Basic dTpw"
160+ return self.app(env, custom_start_response)
161+
162+ def get_groups(self, token, memcache_client=None):
163+ """
164+ Get groups for the given token.
165+
166+ If memcache_client is set, token credentials will be cached
167+ appropriately.
168+
169+ With a cache miss, or no memcache_client, the configurated external
170+ authentication server will be queried for the group information.
171+
172+ :param token: Token to validate and return a group string for.
173+ :param memcache_client: Memcached client to use for caching token
174+ credentials; None if no caching is desired.
175+ :returns: None if the token is invalid or a string containing a comma
176+ separated list of groups the authenticated user is a member
177+ of. The first group in the list is also considered a unique
178+ identifier for that user.
179+ """
180+ groups = None
181+ key = '%s/token/%s' % (self.reseller_prefix, token)
182+ cached_auth_data = memcache_client and memcache_client.get(key)
183+ if cached_auth_data:
184+ start, expiration, groups = cached_auth_data
185+ if time() - start > expiration:
186+ groups = None
187+ if not groups:
188+ with Timeout(self.timeout):
189+ conn = http_connect(self.auth_host, self.auth_port, 'GET',
190+ '%stoken/%s' % (self.auth_prefix, token), ssl=self.ssl)
191+ resp = conn.getresponse()
192+ resp.read()
193+ conn.close()
194+ if resp.status // 100 != 2:
195+ return None
196+ expiration = float(resp.getheader('x-auth-ttl'))
197+ groups = resp.getheader('x-auth-groups')
198+ if memcache_client:
199+ memcache_client.set(key, (time(), expiration, groups),
200+ timeout=expiration)
201+ return groups
202+
203+
204+def filter_factory(global_conf, **local_conf):
205+ """Returns a WSGI filter app for use with paste.deploy."""
206+ conf = global_conf.copy()
207+ conf.update(local_conf)
208+
209+ def auth_filter(app):
210+ return DevAuthN(app, conf)
211+ return auth_filter
212
213=== renamed file 'swift/common/middleware/auth.py' => 'swift/common/middleware/devauthz.py'
214--- swift/common/middleware/auth.py 2011-01-05 16:14:31 +0000
215+++ swift/common/middleware/devauthz.py 2011-01-11 20:54:28 +0000
216@@ -13,17 +13,13 @@
217 # See the License for the specific language governing permissions and
218 # limitations under the License.
219
220-from time import time
221-
222-from eventlet.timeout import Timeout
223 from webob.exc import HTTPForbidden, HTTPUnauthorized, HTTPNotFound
224
225-from swift.common.bufferedhttp import http_connect_raw as http_connect
226 from swift.common.middleware.acl import clean_acl, parse_acl, referrer_allowed
227-from swift.common.utils import cache_from_env, split_path, TRUE_VALUES
228-
229-
230-class DevAuth(object):
231+from swift.common.utils import split_path, TRUE_VALUES
232+
233+
234+class DevAuthZ(object):
235 """Auth Middleware that uses the dev auth server."""
236
237 def __init__(self, app, conf):
238@@ -42,110 +38,50 @@
239 """
240 Accepts a standard WSGI application call, authenticating the request
241 and installing callback hooks for authorization and ACL header
242- validation. For an authenticated request, REMOTE_USER will be set to a
243- comma separated list of the user's groups.
244-
245- With a non-empty reseller prefix, acts as the definitive auth service
246- for just tokens and accounts that begin with that prefix, but will deny
247- requests outside this prefix if no other auth middleware overrides it.
248-
249- With an empty reseller prefix, acts as the definitive auth service only
250- for tokens that validate to a non-empty set of groups. For all other
251- requests, acts as the fallback auth service when no other auth
252- middleware overrides it.
253+ validation.
254 """
255- token = env.get('HTTP_X_AUTH_TOKEN', env.get('HTTP_X_STORAGE_TOKEN'))
256- if token and token.startswith(self.reseller_prefix):
257- # Note: Empty reseller_prefix will match all tokens.
258- # Attempt to auth my token with my auth server
259- groups = \
260- self.get_groups(token, memcache_client=cache_from_env(env))
261- if groups:
262- env['REMOTE_USER'] = groups
263- user = groups and groups.split(',', 1)[0] or ''
264- # We know the proxy logs the token, so we augment it just a bit
265- # to also log the authenticated user.
266- env['HTTP_X_AUTH_TOKEN'] = '%s,%s' % (user, token)
267+ groups = None
268+ if 'SWIFT_GROUPS' in env:
269+ groups = env['SWIFT_GROUPS']
270+ env['REMOTE_USER'] = groups
271+ self.authorize = self.dev_authorize
272+ env['swift.clean_acl'] = clean_acl
273+ elif 'swift.authorize' not in env:
274+ self.authorize = self.empty_authorize
275+
276+ if self.reseller_prefix:
277+ # With a non-empty reseller_prefix, I would like to be called
278+ # back for anonymous access to accounts I know I'm the
279+ # definitive auth for.
280+ try:
281+ version, rest = split_path(env.get('PATH_INFO', ''),
282+ 1, 2, True)
283+ except ValueError:
284+ return HTTPNotFound()(env, start_response)
285+ if rest and rest.startswith(self.reseller_prefix):
286+ # Handle anonymous access to accounts I'm the definitive
287+ # auth for.
288 env['swift.authorize'] = self.authorize
289 env['swift.clean_acl'] = clean_acl
290- else:
291- # Unauthorized token
292- if self.reseller_prefix:
293- # Because I know I'm the definitive auth for this token, I
294- # can deny it outright.
295- return HTTPUnauthorized()(env, start_response)
296- # Because I'm not certain if I'm the definitive auth for empty
297- # reseller_prefixed tokens, I won't overwrite swift.authorize.
298- elif 'swift.authorize' not in env:
299- env['swift.authorize'] = self.denied_response
300- else:
301- if self.reseller_prefix:
302- # With a non-empty reseller_prefix, I would like to be called
303- # back for anonymous access to accounts I know I'm the
304- # definitive auth for.
305- try:
306- version, rest = split_path(env.get('PATH_INFO', ''),
307- 1, 2, True)
308- except ValueError:
309- return HTTPNotFound()(env, start_response)
310- if rest and rest.startswith(self.reseller_prefix):
311- # Handle anonymous access to accounts I'm the definitive
312- # auth for.
313- env['swift.authorize'] = self.authorize
314- env['swift.clean_acl'] = clean_acl
315- # Not my token, not my account, I can't authorize this request,
316- # deny all is a good idea if not already set...
317- elif 'swift.authorize' not in env:
318- env['swift.authorize'] = self.denied_response
319- # Because I'm not certain if I'm the definitive auth for empty
320- # reseller_prefixed accounts, I won't overwrite swift.authorize.
321+ # Not my token, not my account, I can't authorize this request,
322+ # deny all is a good idea if not already set...
323 elif 'swift.authorize' not in env:
324- env['swift.authorize'] = self.authorize
325- env['swift.clean_acl'] = clean_acl
326+ env['swift.authorize'] = self.denied_response
327+ # Because I'm not certain if I'm the definitive auth for empty
328+ # reseller_prefixed accounts, I won't overwrite swift.authorize.
329+ elif 'swift.authorize' not in env:
330+ env['swift.authorize'] = self.empty_authorize
331 return self.app(env, start_response)
332
333- def get_groups(self, token, memcache_client=None):
334- """
335- Get groups for the given token.
336-
337- If memcache_client is set, token credentials will be cached
338- appropriately.
339-
340- With a cache miss, or no memcache_client, the configurated external
341- authentication server will be queried for the group information.
342-
343- :param token: Token to validate and return a group string for.
344- :param memcache_client: Memcached client to use for caching token
345- credentials; None if no caching is desired.
346- :returns: None if the token is invalid or a string containing a comma
347- separated list of groups the authenticated user is a member
348- of. The first group in the list is also considered a unique
349- identifier for that user.
350- """
351- groups = None
352- key = '%s/token/%s' % (self.reseller_prefix, token)
353- cached_auth_data = memcache_client and memcache_client.get(key)
354- if cached_auth_data:
355- start, expiration, groups = cached_auth_data
356- if time() - start > expiration:
357- groups = None
358- if not groups:
359- with Timeout(self.timeout):
360- conn = http_connect(self.auth_host, self.auth_port, 'GET',
361- '%stoken/%s' % (self.auth_prefix, token), ssl=self.ssl)
362- resp = conn.getresponse()
363- resp.read()
364- conn.close()
365- if resp.status // 100 != 2:
366- return None
367- expiration = float(resp.getheader('x-auth-ttl'))
368- groups = resp.getheader('x-auth-groups')
369- if memcache_client:
370- memcache_client.set(key, (time(), expiration, groups),
371- timeout=expiration)
372- return groups
373-
374- def authorize(self, req):
375+ def empty_authorize(self, req):
376+ if 'x_identity_status' in req.headers:
377+ if req.headers['x_identity_status'] == 'Invalid':
378+ return self.denied_response(req)
379+ elif req.headers['x_identity_status'] == 'Indeterminate':
380+ return self.dev_authorize(req)
381+ return None
382+
383+ def dev_authorize(self, req):
384 """
385 Returns None if the request is authorized to continue or a standard
386 WSGI response callable if not.
387@@ -179,10 +115,13 @@
388 Returns a standard WSGI response callable with the status of 403 or 401
389 depending on whether the REMOTE_USER is set or not.
390 """
391+ headers = [('www-authenticate', 'delegated')]
392 if req.remote_user:
393- return HTTPForbidden(request=req)
394+ resp = HTTPForbidden(headers=headers, request=req)
395 else:
396- return HTTPUnauthorized(request=req)
397+ resp = HTTPUnauthorized(headers=headers, request=req)
398+
399+ return resp
400
401
402 def filter_factory(global_conf, **local_conf):
403@@ -191,5 +130,5 @@
404 conf.update(local_conf)
405
406 def auth_filter(app):
407- return DevAuth(app, conf)
408+ return DevAuthZ(app, conf)
409 return auth_filter
410
411=== added file 'swift/common/middleware/papiauth.py'
412--- swift/common/middleware/papiauth.py 1970-01-01 00:00:00 +0000
413+++ swift/common/middleware/papiauth.py 2011-01-11 20:54:28 +0000
414@@ -0,0 +1,62 @@
415+# Copyright (c) 2010 OpenStack, LLC.
416+#
417+# Licensed under the Apache License, Version 2.0 (the "License");
418+# you may not use this file except in compliance with the License.
419+# You may obtain a copy of the License at
420+#
421+# http://www.apache.org/licenses/LICENSE-2.0
422+#
423+# Unless required by applicable law or agreed to in writing, software
424+# distributed under the License is distributed on an "AS IS" BASIS,
425+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
426+# implied.
427+# See the License for the specific language governing permissions and
428+# limitations under the License.
429+
430+from webob.exc import HTTPUseProxy, HTTPUnauthorized
431+
432+from swift.common.utils import TRUE_VALUES
433+
434+
435+class PAPIAuth(object):
436+ """Auth Middleware that uses the dev auth server."""
437+
438+ def __init__(self, app, conf):
439+ self.app = app
440+ self.conf = conf
441+ self.reseller_prefix = conf.get('reseller_prefix', 'AUTH').strip()
442+ if self.reseller_prefix and self.reseller_prefix[-1] != '_':
443+ self.reseller_prefix += '_'
444+ self.auth_host = conf.get('ip', '127.0.0.1')
445+ self.auth_port = int(conf.get('port', 11000))
446+ self.auth_pass = conf.get('pass', 'dTpw')
447+ self.ssl = conf.get('ssl', 'false').lower() in TRUE_VALUES
448+ self.timeout = int(conf.get('node_timeout', 10))
449+
450+ def __call__(self, env, start_response):
451+ # Make sure that the user has been authenticated by the Auth Service
452+ if 'HTTP_X_AUTHORIZATION' not in env:
453+ proxy_location = 'http://' + self.auth_host + ':' + \
454+ str(self.auth_port) + '/'
455+ return HTTPUseProxy(location=proxy_location)(env, start_response)
456+
457+ # Authenticate the Auth component itself.
458+ headers = [('www-authenticate', 'Basic realm="swift"')]
459+ if 'HTTP_AUTHORIZATION' not in env:
460+ return HTTPUnauthorized(headers=headers)(env, start_response)
461+ else:
462+ auth_type, encoded_creds = env['HTTP_AUTHORIZATION'].split(None, 1)
463+ if encoded_creds != self.auth_pass:
464+ return HTTPUnauthorized(headers=headers)(env, start_response)
465+
466+ return self.app(env, start_response)
467+
468+
469+def filter_factory(global_conf, **local_conf):
470+ """Returns a WSGI filter app for use with paste.deploy."""
471+ conf = global_conf.copy()
472+ conf.update(local_conf)
473+
474+ def auth_filter(app):
475+ return PAPIAuth(app, conf)
476+ return auth_filter
477
478=== modified file 'test/unit/common/middleware/test_auth.py'
479--- test/unit/common/middleware/test_auth.py 2011-01-05 16:14:31 +0000
480+++ test/unit/common/middleware/test_auth.py 2011-01-11 20:54:28 +0000
481@@ -23,7 +23,7 @@
482 import eventlet
483 from webob import Request
484
485-from swift.common.middleware import auth
486+from swift.common.middleware import devauthn, devauthz, papiauth
487
488 # mocks
489 logging.getLogger().addHandler(logging.StreamHandler(sys.stdout))
490@@ -122,243 +122,281 @@
491 class TestAuth(unittest.TestCase):
492
493 def setUp(self):
494- self.test_auth = auth.filter_factory({})(FakeApp())
495+ self.test_authn = devauthn.filter_factory({})(FakeApp())
496+ self.test_authz = devauthz.filter_factory({})(FakeApp())
497+ self.test_papiauth = papiauth.filter_factory({})(FakeApp())
498
499 def test_auth_deny_non_reseller_prefix(self):
500- old_http_connect = auth.http_connect
501- try:
502- auth.http_connect = mock_http_connect(204,
503- {'x-auth-ttl': '1234', 'x-auth-groups': 'act:usr,act,AUTH_cfa'})
504- reqenv = {'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v1/BLAH_account',
505- 'HTTP_X_AUTH_TOKEN': 'BLAH_t', 'swift.cache': FakeMemcache()}
506- result = ''.join(self.test_auth(reqenv, lambda x, y: None))
507- self.assert_(result.startswith('401'), result)
508- self.assertEquals(reqenv['swift.authorize'],
509- self.test_auth.denied_response)
510- finally:
511- auth.http_connect = old_http_connect
512+ reqenv = {'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v1/BLAH_account',
513+ 'HTTP_X_AUTH_TOKEN': 'BLAH_t', 'swift.cache': FakeMemcache()}
514+ result = ''.join(self.test_authz(reqenv, lambda x, y: None))
515+ self.assert_(result.startswith('401'), result)
516+ self.assertEquals(reqenv['swift.authorize'],
517+ self.test_authz.denied_response)
518
519 def test_auth_deny_non_reseller_prefix_no_override(self):
520- old_http_connect = auth.http_connect
521+ old_http_connect = devauthn.http_connect
522 try:
523- auth.http_connect = mock_http_connect(204,
524+ local_app = FakeApp()
525+ local_authz = \
526+ devauthz.filter_factory({'reseller_prefix': ''})(local_app)
527+ local_authn = \
528+ devauthn.filter_factory({'delegated': 1})(local_authz)
529+ devauthn.http_connect = mock_http_connect(204,
530 {'x-auth-ttl': '1234', 'x-auth-groups': 'act:usr,act,AUTH_cfa'})
531 fake_authorize = lambda x: lambda x, y: ['500 Fake']
532 reqenv = {'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v1/BLAH_account',
533 'HTTP_X_AUTH_TOKEN': 'BLAH_t', 'swift.cache': FakeMemcache(),
534 'swift.authorize': fake_authorize}
535- result = ''.join(self.test_auth(reqenv, lambda x, y: None))
536+ result = ''.join(local_authn(reqenv, lambda x, y: None))
537 self.assert_(result.startswith('500 Fake'), result)
538 self.assertEquals(reqenv['swift.authorize'], fake_authorize)
539 finally:
540- auth.http_connect = old_http_connect
541+ devauthn.http_connect = old_http_connect
542
543- def test_auth_no_reseller_prefix_deny(self):
544+ def test_auth_no_reseller_prefix_deny_delegated(self):
545 # Ensures that when we have no reseller prefix, we don't deny a request
546 # outright but set up a denial swift.authorize and pass the request on
547 # down the chain.
548- old_http_connect = auth.http_connect
549+ old_http_connect = devauthn.http_connect
550 try:
551 local_app = FakeApp()
552- local_auth = \
553- auth.filter_factory({'reseller_prefix': ''})(local_app)
554- auth.http_connect = mock_http_connect(404)
555+ local_authz = \
556+ devauthz.filter_factory({'reseller_prefix': ''})(local_app)
557+ local_authn = \
558+ devauthn.filter_factory(\
559+ {'reseller_prefix': '', 'delegated': 1})(local_authz)
560+ devauthn.http_connect = mock_http_connect(404)
561 reqenv = {'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v1/account',
562 'HTTP_X_AUTH_TOKEN': 't', 'swift.cache': FakeMemcache()}
563- result = ''.join(local_auth(reqenv, lambda x, y: None))
564+ result = ''.join(local_authn(reqenv, lambda x, y: None))
565 self.assert_(result.startswith('401'), result)
566 self.assert_(local_app.i_was_called)
567 self.assertEquals(reqenv['swift.authorize'],
568- local_auth.denied_response)
569- finally:
570- auth.http_connect = old_http_connect
571+ local_authz.empty_authorize)
572+ finally:
573+ devauthn.http_connect = old_http_connect
574+
575+ def test_auth_no_reseller_prefix_deny_non_delegated(self):
576+ # Ensures that when we have no reseller prefix, we don't deny a request
577+ # outright but set up a denial swift.authorize and pass the request on
578+ # down the chain.
579+ old_http_connect = devauthn.http_connect
580+ try:
581+ local_app = FakeApp()
582+ local_authn = \
583+ devauthn.filter_factory(\
584+ {'reseller_prefix': ''})(local_app)
585+ devauthn.http_connect = mock_http_connect(404)
586+ reqenv = {'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v1/account',
587+ 'HTTP_X_AUTH_TOKEN': 't', 'swift.cache': FakeMemcache()}
588+ result = ''.join(local_authn(reqenv, lambda x, y: None))
589+ self.assert_(result.startswith('401'), result)
590+ self.assert_(not local_app.i_was_called)
591+ finally:
592+ devauthn.http_connect = old_http_connect
593+
594
595 def test_auth_no_reseller_prefix_allow(self):
596 # Ensures that when we have no reseller prefix, we can still allow
597 # access if our auth server accepts requests
598- old_http_connect = auth.http_connect
599- try:
600- local_app = FakeApp()
601- local_auth = \
602- auth.filter_factory({'reseller_prefix': ''})(local_app)
603- auth.http_connect = mock_http_connect(204,
604- {'x-auth-ttl': '1234', 'x-auth-groups': 'act:usr,act,AUTH_cfa'})
605- reqenv = {'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v1/act',
606- 'HTTP_X_AUTH_TOKEN': 't', 'swift.cache': None}
607- result = ''.join(local_auth(reqenv, lambda x, y: None))
608- self.assert_(result.startswith('204'), result)
609- self.assert_(local_app.i_was_called)
610- self.assertEquals(reqenv['swift.authorize'],
611- local_auth.authorize)
612- finally:
613- auth.http_connect = old_http_connect
614+ local_app = FakeApp()
615+ local_auth = \
616+ devauthz.filter_factory({'reseller_prefix': ''})(local_app)
617+ reqenv = {'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v1/act',
618+ 'HTTP_X_AUTH_TOKEN': 't', 'swift.cache': None,
619+ 'SWIFT_GROUPS': 'act:usr,act,AUTH_cfa'}
620+ result = ''.join(local_auth(reqenv, lambda x, y: None))
621+ self.assert_(result.startswith('204'), result)
622+ self.assert_(local_app.i_was_called)
623+ self.assertEquals(reqenv['swift.authorize'],
624+ local_auth.empty_authorize)
625
626- def test_auth_no_reseller_prefix_no_token(self):
627+ def test_auth_no_reseller_prefix_no_token_delegated(self):
628 # Check that normally we set up a call back to our authorize.
629- local_auth = \
630- auth.filter_factory({'reseller_prefix': ''})(FakeApp())
631+ local_authz = \
632+ devauthz.filter_factory({'reseller_prefix': ''})(FakeApp())
633+ local_authn = \
634+ devauthn.filter_factory(\
635+ {'reseller_prefix': '', 'delegated':1})(local_authz)
636 reqenv = {'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v1/account',
637 'swift.cache': FakeMemcache()}
638- result = ''.join(local_auth(reqenv, lambda x, y: None))
639+ result = ''.join(local_authn(reqenv, lambda x, y: None))
640 self.assert_(result.startswith('401'), result)
641- self.assertEquals(reqenv['swift.authorize'], local_auth.authorize)
642+ self.assertEquals(\
643+ reqenv['swift.authorize'], local_authz.empty_authorize)
644 # Now make sure we don't override an existing swift.authorize when we
645 # have no reseller prefix.
646 local_authorize = lambda req: None
647 reqenv['swift.authorize'] = local_authorize
648- result = ''.join(local_auth(reqenv, lambda x, y: None))
649+ result = ''.join(local_authz(reqenv, lambda x, y: None))
650 self.assert_(result.startswith('204'), result)
651 self.assertEquals(reqenv['swift.authorize'], local_authorize)
652
653+ def test_auth_no_reseller_prefix_no_token_non_delegated(self):
654+ # Ensure that in a non_delegated mode, no token gets denied
655+ # right away.
656+ local_app = FakeApp()
657+ local_authn = \
658+ devauthn.filter_factory(\
659+ {'reseller_prefix': ''})(local_app)
660+ reqenv = {'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v1/account',
661+ 'swift.cache': FakeMemcache()}
662+ result = ''.join(local_authn(reqenv, lambda x, y: None))
663+ self.assert_(result.startswith('401'), result)
664+ self.assert_(not local_app.i_was_called)
665+
666 def test_auth_fail(self):
667- old_http_connect = auth.http_connect
668+ old_http_connect = devauthn.http_connect
669 try:
670- auth.http_connect = mock_http_connect(404)
671- result = ''.join(self.test_auth({'REQUEST_METHOD': 'GET',
672+ devauthn.http_connect = mock_http_connect(404)
673+ result = ''.join(self.test_authn({'REQUEST_METHOD': 'GET',
674 'HTTP_X_AUTH_TOKEN': 'AUTH_t', 'swift.cache': FakeMemcache()},
675 lambda x, y: None))
676 self.assert_(result.startswith('401'), result)
677 finally:
678- auth.http_connect = old_http_connect
679+ devauthn.http_connect = old_http_connect
680
681 def test_auth_success(self):
682- old_http_connect = auth.http_connect
683+ old_http_connect = devauthn.http_connect
684 try:
685- auth.http_connect = mock_http_connect(204,
686+ devauthn.http_connect = mock_http_connect(204,
687 {'x-auth-ttl': '1234', 'x-auth-groups': 'act:usr,act,AUTH_cfa'})
688- result = ''.join(self.test_auth({'REQUEST_METHOD': 'GET',
689+ result = ''.join(self.test_authn({'REQUEST_METHOD': 'GET',
690 'PATH_INFO': '/v/AUTH_cfa', 'HTTP_X_AUTH_TOKEN': 'AUTH_t',
691 'swift.cache': FakeMemcache()}, lambda x, y: None))
692 self.assert_(result.startswith('204'), result)
693 finally:
694- auth.http_connect = old_http_connect
695+ devauthn.http_connect = old_http_connect
696
697 def test_auth_memcache(self):
698- old_http_connect = auth.http_connect
699+ old_http_connect = devauthn.http_connect
700 try:
701 fake_memcache = FakeMemcache()
702- auth.http_connect = mock_http_connect(204,
703+ devauthn.http_connect = mock_http_connect(204,
704 {'x-auth-ttl': '1234', 'x-auth-groups': 'act:usr,act,AUTH_cfa'})
705- result = ''.join(self.test_auth({'REQUEST_METHOD': 'GET',
706+ result = ''.join(self.test_authn({'REQUEST_METHOD': 'GET',
707 'PATH_INFO': '/v/AUTH_cfa', 'HTTP_X_AUTH_TOKEN': 'AUTH_t',
708 'swift.cache': fake_memcache}, lambda x, y: None))
709 self.assert_(result.startswith('204'), result)
710- auth.http_connect = mock_http_connect(404)
711+ devauthn.http_connect = mock_http_connect(404)
712 # Should still be in memcache
713- result = ''.join(self.test_auth({'REQUEST_METHOD': 'GET',
714+ result = ''.join(self.test_authn({'REQUEST_METHOD': 'GET',
715 'PATH_INFO': '/v/AUTH_cfa', 'HTTP_X_AUTH_TOKEN': 'AUTH_t',
716 'swift.cache': fake_memcache}, lambda x, y: None))
717 self.assert_(result.startswith('204'), result)
718 finally:
719- auth.http_connect = old_http_connect
720+ devauthn.http_connect = old_http_connect
721
722 def test_auth_just_expired(self):
723- old_http_connect = auth.http_connect
724+ old_http_connect = devauthn.http_connect
725 try:
726 fake_memcache = FakeMemcache()
727- auth.http_connect = mock_http_connect(204,
728+ devauthn.http_connect = mock_http_connect(204,
729 {'x-auth-ttl': '0', 'x-auth-groups': 'act:usr,act,AUTH_cfa'})
730- result = ''.join(self.test_auth({'REQUEST_METHOD': 'GET',
731+ result = ''.join(self.test_authn({'REQUEST_METHOD': 'GET',
732 'PATH_INFO': '/v/AUTH_cfa', 'HTTP_X_AUTH_TOKEN': 'AUTH_t',
733 'swift.cache': fake_memcache}, lambda x, y: None))
734 self.assert_(result.startswith('204'), result)
735- auth.http_connect = mock_http_connect(404)
736+ devauthn.http_connect = mock_http_connect(404)
737 # Should still be in memcache, but expired
738- result = ''.join(self.test_auth({'REQUEST_METHOD': 'GET',
739+ result = ''.join(self.test_authn({'REQUEST_METHOD': 'GET',
740 'HTTP_X_AUTH_TOKEN': 'AUTH_t', 'swift.cache': fake_memcache},
741 lambda x, y: None))
742 self.assert_(result.startswith('401'), result)
743 finally:
744- auth.http_connect = old_http_connect
745+ devauthn.http_connect = old_http_connect
746
747 def test_middleware_success(self):
748- old_http_connect = auth.http_connect
749+ old_http_connect = devauthn.http_connect
750 try:
751- auth.http_connect = mock_http_connect(204,
752+ devauthn.http_connect = mock_http_connect(204,
753 {'x-auth-ttl': '1234', 'x-auth-groups': 'act:usr,act,AUTH_cfa'})
754 req = Request.blank('/v/AUTH_cfa/c/o',
755 headers={'x-auth-token': 'AUTH_t'})
756 req.environ['swift.cache'] = FakeMemcache()
757- result = ''.join(self.test_auth(req.environ, start_response))
758+ result = ''.join(self.test_authn(req.environ, start_response))
759 self.assert_(result.startswith('204'), result)
760- self.assertEquals(req.remote_user, 'act:usr,act,AUTH_cfa')
761+ self.assertEquals(\
762+ req.environ['SWIFT_GROUPS'], 'act:usr,act,AUTH_cfa')
763 finally:
764- auth.http_connect = old_http_connect
765+ devauthn.http_connect = old_http_connect
766
767 def test_middleware_no_header(self):
768- old_http_connect = auth.http_connect
769+ old_http_connect = devauthn.http_connect
770 try:
771- auth.http_connect = mock_http_connect(204,
772+ devauthn.http_connect = mock_http_connect(204,
773 {'x-auth-ttl': '1234', 'x-auth-groups': 'act:usr,act,AUTH_cfa'})
774 req = Request.blank('/v/AUTH_cfa/c/o')
775 req.environ['swift.cache'] = FakeMemcache()
776- result = ''.join(self.test_auth(req.environ, start_response))
777+ result = ''.join(self.test_authn(req.environ, start_response))
778 self.assert_(result.startswith('401'), result)
779 self.assert_(not req.remote_user, req.remote_user)
780 finally:
781- auth.http_connect = old_http_connect
782+ devauthn.http_connect = old_http_connect
783
784 def test_middleware_storage_token(self):
785- old_http_connect = auth.http_connect
786+ old_http_connect = devauthn.http_connect
787 try:
788- auth.http_connect = mock_http_connect(204,
789+ devauthn.http_connect = mock_http_connect(204,
790 {'x-auth-ttl': '1234', 'x-auth-groups': 'act:usr,act,AUTH_cfa'})
791 req = Request.blank('/v/AUTH_cfa/c/o',
792 headers={'x-storage-token': 'AUTH_t'})
793 req.environ['swift.cache'] = FakeMemcache()
794- result = ''.join(self.test_auth(req.environ, start_response))
795+ result = ''.join(self.test_authn(req.environ, start_response))
796 self.assert_(result.startswith('204'), result)
797- self.assertEquals(req.remote_user, 'act:usr,act,AUTH_cfa')
798+ self.assertEquals(\
799+ req.environ['SWIFT_GROUPS'], 'act:usr,act,AUTH_cfa')
800 finally:
801- auth.http_connect = old_http_connect
802+ devauthn.http_connect = old_http_connect
803
804 def test_authorize_bad_path(self):
805 req = Request.blank('/badpath')
806- resp = self.test_auth.authorize(req)
807+ resp = self.test_authz.dev_authorize(req)
808 self.assertEquals(resp and resp.status_int, 401)
809 req = Request.blank('/badpath')
810 req.remote_user = 'act:usr,act,AUTH_cfa'
811- resp = self.test_auth.authorize(req)
812+ resp = self.test_authz.dev_authorize(req)
813 self.assertEquals(resp and resp.status_int, 403)
814 req = Request.blank('')
815- resp = self.test_auth.authorize(req)
816+ resp = self.test_authz.dev_authorize(req)
817 self.assertEquals(resp and resp.status_int, 404)
818 req = Request.blank('')
819 req.environ['swift.cache'] = FakeMemcache()
820- result = ''.join(self.test_auth(req.environ, lambda x, y: None))
821+ result = ''.join(self.test_authz(req.environ, lambda x, y: None))
822 self.assert_(result.startswith('404'), result)
823
824 def test_authorize_account_access(self):
825 req = Request.blank('/v1/AUTH_cfa')
826 req.remote_user = 'act:usr,act,AUTH_cfa'
827- self.assertEquals(self.test_auth.authorize(req), None)
828+ self.assertEquals(self.test_authz.dev_authorize(req), None)
829 req = Request.blank('/v1/AUTH_cfa')
830 req.remote_user = 'act:usr,act'
831- resp = self.test_auth.authorize(req)
832+ resp = self.test_authz.dev_authorize(req)
833 self.assertEquals(resp and resp.status_int, 403)
834
835 def test_authorize_acl_group_access(self):
836 req = Request.blank('/v1/AUTH_cfa')
837 req.remote_user = 'act:usr,act'
838- resp = self.test_auth.authorize(req)
839+ resp = self.test_authz.dev_authorize(req)
840 self.assertEquals(resp and resp.status_int, 403)
841 req = Request.blank('/v1/AUTH_cfa')
842 req.remote_user = 'act:usr,act'
843 req.acl = 'act'
844- self.assertEquals(self.test_auth.authorize(req), None)
845+ self.assertEquals(self.test_authz.dev_authorize(req), None)
846 req = Request.blank('/v1/AUTH_cfa')
847 req.remote_user = 'act:usr,act'
848 req.acl = 'act:usr'
849- self.assertEquals(self.test_auth.authorize(req), None)
850+ self.assertEquals(self.test_authz.dev_authorize(req), None)
851 req = Request.blank('/v1/AUTH_cfa')
852 req.remote_user = 'act:usr,act'
853 req.acl = 'act2'
854- resp = self.test_auth.authorize(req)
855+ resp = self.test_authz.dev_authorize(req)
856 self.assertEquals(resp and resp.status_int, 403)
857 req = Request.blank('/v1/AUTH_cfa')
858 req.remote_user = 'act:usr,act'
859 req.acl = 'act:usr2'
860- resp = self.test_auth.authorize(req)
861+ resp = self.test_authz.dev_authorize(req)
862 self.assertEquals(resp and resp.status_int, 403)
863
864 def test_deny_cross_reseller(self):
865@@ -366,96 +404,96 @@
866 req = Request.blank('/v1/OTHER_cfa')
867 req.remote_user = 'act:usr,act,AUTH_cfa'
868 req.acl = 'act'
869- resp = self.test_auth.authorize(req)
870+ resp = self.test_authz.dev_authorize(req)
871 self.assertEquals(resp and resp.status_int, 403)
872
873 def test_authorize_acl_referrer_access(self):
874 req = Request.blank('/v1/AUTH_cfa')
875 req.remote_user = 'act:usr,act'
876- resp = self.test_auth.authorize(req)
877- self.assertEquals(resp and resp.status_int, 403)
878- req = Request.blank('/v1/AUTH_cfa')
879- req.remote_user = 'act:usr,act'
880- req.acl = '.r:*'
881- self.assertEquals(self.test_auth.authorize(req), None)
882- req = Request.blank('/v1/AUTH_cfa')
883- req.remote_user = 'act:usr,act'
884- req.acl = '.r:.example.com'
885- resp = self.test_auth.authorize(req)
886- self.assertEquals(resp and resp.status_int, 403)
887- req = Request.blank('/v1/AUTH_cfa')
888- req.remote_user = 'act:usr,act'
889- req.referer = 'http://www.example.com/index.html'
890- req.acl = '.r:.example.com'
891- self.assertEquals(self.test_auth.authorize(req), None)
892- req = Request.blank('/v1/AUTH_cfa')
893- resp = self.test_auth.authorize(req)
894- self.assertEquals(resp and resp.status_int, 401)
895- req = Request.blank('/v1/AUTH_cfa')
896- req.acl = '.r:*'
897- self.assertEquals(self.test_auth.authorize(req), None)
898- req = Request.blank('/v1/AUTH_cfa')
899- req.acl = '.r:.example.com'
900- resp = self.test_auth.authorize(req)
901- self.assertEquals(resp and resp.status_int, 401)
902- req = Request.blank('/v1/AUTH_cfa')
903- req.referer = 'http://www.example.com/index.html'
904- req.acl = '.r:.example.com'
905- self.assertEquals(self.test_auth.authorize(req), None)
906+ resp = self.test_authz.dev_authorize(req)
907+ self.assertEquals(resp and resp.status_int, 403)
908+ req = Request.blank('/v1/AUTH_cfa')
909+ req.remote_user = 'act:usr,act'
910+ req.acl = '.r:*'
911+ self.assertEquals(self.test_authz.dev_authorize(req), None)
912+ req = Request.blank('/v1/AUTH_cfa')
913+ req.remote_user = 'act:usr,act'
914+ req.acl = '.r:.example.com'
915+ resp = self.test_authz.dev_authorize(req)
916+ self.assertEquals(resp and resp.status_int, 403)
917+ req = Request.blank('/v1/AUTH_cfa')
918+ req.remote_user = 'act:usr,act'
919+ req.referer = 'http://www.example.com/index.html'
920+ req.acl = '.r:.example.com'
921+ self.assertEquals(self.test_authz.dev_authorize(req), None)
922+ req = Request.blank('/v1/AUTH_cfa')
923+ resp = self.test_authz.dev_authorize(req)
924+ self.assertEquals(resp and resp.status_int, 401)
925+ req = Request.blank('/v1/AUTH_cfa')
926+ req.acl = '.r:*'
927+ self.assertEquals(self.test_authz.dev_authorize(req), None)
928+ req = Request.blank('/v1/AUTH_cfa')
929+ req.acl = '.r:.example.com'
930+ resp = self.test_authz.dev_authorize(req)
931+ self.assertEquals(resp and resp.status_int, 401)
932+ req = Request.blank('/v1/AUTH_cfa')
933+ req.referer = 'http://www.example.com/index.html'
934+ req.acl = '.r:.example.com'
935+ self.assertEquals(self.test_authz.dev_authorize(req), None)
936
937 def test_account_put_permissions(self):
938 req = Request.blank('/v1/AUTH_new', environ={'REQUEST_METHOD': 'PUT'})
939 req.remote_user = 'act:usr,act'
940- resp = self.test_auth.authorize(req)
941+ resp = self.test_authz.dev_authorize(req)
942 self.assertEquals(resp and resp.status_int, 403)
943
944 req = Request.blank('/v1/AUTH_new', environ={'REQUEST_METHOD': 'PUT'})
945 req.remote_user = 'act:usr,act,AUTH_other'
946- resp = self.test_auth.authorize(req)
947+ resp = self.test_authz.dev_authorize(req)
948 self.assertEquals(resp and resp.status_int, 403)
949
950 # Even PUTs to your own account as account admin should fail
951 req = Request.blank('/v1/AUTH_old', environ={'REQUEST_METHOD': 'PUT'})
952 req.remote_user = 'act:usr,act,AUTH_old'
953- resp = self.test_auth.authorize(req)
954+ resp = self.test_authz.dev_authorize(req)
955 self.assertEquals(resp and resp.status_int, 403)
956
957 req = Request.blank('/v1/AUTH_new', environ={'REQUEST_METHOD': 'PUT'})
958 req.remote_user = 'act:usr,act,.reseller_admin'
959- resp = self.test_auth.authorize(req)
960+ resp = self.test_authz.dev_authorize(req)
961 self.assertEquals(resp, None)
962
963 # .super_admin is not something the middleware should ever see or care
964 # about
965 req = Request.blank('/v1/AUTH_new', environ={'REQUEST_METHOD': 'PUT'})
966 req.remote_user = 'act:usr,act,.super_admin'
967- resp = self.test_auth.authorize(req)
968+ resp = self.test_authz.dev_authorize(req)
969 self.assertEquals(resp and resp.status_int, 403)
970
971 def test_account_delete_permissions(self):
972 req = Request.blank('/v1/AUTH_new',
973 environ={'REQUEST_METHOD': 'DELETE'})
974 req.remote_user = 'act:usr,act'
975- resp = self.test_auth.authorize(req)
976+ resp = self.test_authz.dev_authorize(req)
977 self.assertEquals(resp and resp.status_int, 403)
978
979 req = Request.blank('/v1/AUTH_new',
980 environ={'REQUEST_METHOD': 'DELETE'})
981 req.remote_user = 'act:usr,act,AUTH_other'
982- resp = self.test_auth.authorize(req)
983+ resp = self.test_authz.dev_authorize(req)
984 self.assertEquals(resp and resp.status_int, 403)
985
986 # Even DELETEs to your own account as account admin should fail
987 req = Request.blank('/v1/AUTH_old',
988 environ={'REQUEST_METHOD': 'DELETE'})
989 req.remote_user = 'act:usr,act,AUTH_old'
990- resp = self.test_auth.authorize(req)
991+ resp = self.test_authz.dev_authorize(req)
992 self.assertEquals(resp and resp.status_int, 403)
993
994 req = Request.blank('/v1/AUTH_new',
995 environ={'REQUEST_METHOD': 'DELETE'})
996 req.remote_user = 'act:usr,act,.reseller_admin'
997- resp = self.test_auth.authorize(req)
998+ resp = self.test_authz.dev_authorize(req)
999 self.assertEquals(resp, None)
1000
1001 # .super_admin is not something the middleware should ever see or care
1002@@ -463,7 +501,7 @@
1003 req = Request.blank('/v1/AUTH_new',
1004 environ={'REQUEST_METHOD': 'DELETE'})
1005 req.remote_user = 'act:usr,act,.super_admin'
1006- resp = self.test_auth.authorize(req)
1007+ resp = self.test_authz.dev_authorize(req)
1008 self.assertEquals(resp and resp.status_int, 403)
1009
1010