For ACL strings: Shortened .ref to just .r, though .ref, .referer, and .referrer are all accepted. Updated 'Creating Your Own Auth Middleware' to describe how the DevAuth server works and suggestions for creating one's own. Added reseller_prefix (optional) implementation. Used urlparse in referrer_allowed. Fixed bug where group names would get lowercased by clean_acl. Changed .r:any to .r:*. Allowed .r:*.example.com to mean .r:.example.com. Made proxy log just the first authenticated group (the user) alongside the token. Moved proxy callback to clean_acl before the length check of the metadata. Cleaned up redundant logic in first proxy swift.authorize callback. Bit better docs. More and updated tests.
This commit is contained in:
5
bin/st
5
bin/st
@@ -1417,9 +1417,8 @@ Example:
|
|||||||
'general documentation for what this means).')
|
'general documentation for what this means).')
|
||||||
parser.add_option('-r', '--read-acl', dest='read_acl',
|
parser.add_option('-r', '--read-acl', dest='read_acl',
|
||||||
help='Sets the Read ACL with post container commands. '
|
help='Sets the Read ACL with post container commands. '
|
||||||
'Quick summary of ACL syntax: .ref:any, '
|
'Quick summary of ACL syntax: .r:*, .r:-.example.com, '
|
||||||
'.ref:-.example.com, .ref:www.example.com, account1, '
|
'.r:www.example.com, account1, account2:user2')
|
||||||
'account2:user2')
|
|
||||||
parser.add_option('-w', '--write-acl', dest='write_acl',
|
parser.add_option('-w', '--write-acl', dest='write_acl',
|
||||||
help='Sets the Write ACL with post container commands. '
|
help='Sets the Write ACL with post container commands. '
|
||||||
'Quick summary of ACL syntax: account1, account2:user2')
|
'Quick summary of ACL syntax: account1, account2:user2')
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
===============
|
==========================
|
||||||
Auth Middleware
|
Auth Server and Middleware
|
||||||
===============
|
==========================
|
||||||
|
|
||||||
---------------------------------
|
--------------------------------------------
|
||||||
Creating Your Own Auth Middleware
|
Creating Your Own Auth Server and Middleware
|
||||||
---------------------------------
|
--------------------------------------------
|
||||||
|
|
||||||
The included swift/common/middleware/auth.py is a good minimal example of how
|
The included swift/common/middleware/auth.py is a good minimal example of how
|
||||||
to create auth middleware. The main points are that the auth middleware can
|
to create auth middleware. The main points are that the auth middleware can
|
||||||
@@ -26,6 +26,39 @@ specific information, it just passes it along. Convention has
|
|||||||
environ['REMOTE_USER'] set to the authenticated user string but often more
|
environ['REMOTE_USER'] set to the authenticated user string but often more
|
||||||
information is needed than just that.
|
information is needed than just that.
|
||||||
|
|
||||||
|
The included DevAuth will set the REMOTE_USER to a comma separated list of
|
||||||
|
groups the user belongs to. The first group will be the "user's group", a group
|
||||||
|
that only the user belongs to. The second group will be the "account's group",
|
||||||
|
a group that includes all users for that auth account (different than the
|
||||||
|
storage account). The third group is optional and is the storage account
|
||||||
|
string. If the user does not have admin access to the account, the third group
|
||||||
|
will be omitted.
|
||||||
|
|
||||||
|
It is highly recommended that authentication server implementers prefix their
|
||||||
|
group names and tokens with a configurable reseller prefix (`AUTH_` by default
|
||||||
|
with the included DevAuth). This prefix will allow deconflicting with other
|
||||||
|
authentication servers that might be using the same Swift cluster.
|
||||||
|
|
||||||
|
The only other restriction is that no group name should begin with a period '.'
|
||||||
|
as that is reserved for internal Swift use (such as the .r for referrer
|
||||||
|
designations as you'll see later). This shouldn't be an issue if a reseller
|
||||||
|
prefix is in use and does not begin with a period.
|
||||||
|
|
||||||
|
Example Authentication with DevAuth:
|
||||||
|
|
||||||
|
* Token AUTH_tkabcd is given to the DevAuth middleware in a request's
|
||||||
|
X-Auth-Token header.
|
||||||
|
* The DevAuth middleware makes a validate token AUTH_tkabcd call to the
|
||||||
|
external DevAuth server.
|
||||||
|
* The external DevAuth server validates the token AUTH_tkabcd and discovers
|
||||||
|
it matches the "tester" user within the "test" account for the storage
|
||||||
|
account "AUTH_storage_xyz".
|
||||||
|
* The external DevAuth server responds with "X-Auth-Groups:
|
||||||
|
AUTH_test:tester,AUTH_test,AUTH_storage_xyz"
|
||||||
|
* Now this user will have full access (via authorization procedures later)
|
||||||
|
to the AUTH_storage_xyz Swift storage account and access to anything with
|
||||||
|
ACLs specifying at least one of those three groups returned.
|
||||||
|
|
||||||
Authorization is performed through callbacks by the Swift Proxy server to the
|
Authorization is performed through callbacks by the Swift Proxy server to the
|
||||||
WSGI environment's swift.authorize value, if one is set. The swift.authorize
|
WSGI environment's swift.authorize value, if one is set. The swift.authorize
|
||||||
value should simply be a function that takes a webob.Request as an argument and
|
value should simply be a function that takes a webob.Request as an argument and
|
||||||
|
@@ -37,6 +37,10 @@ use = egg:swift#proxy
|
|||||||
|
|
||||||
[filter:auth]
|
[filter:auth]
|
||||||
use = egg:swift#auth
|
use = egg:swift#auth
|
||||||
|
# The reseller prefix, if set, will verify a token begins with this prefix
|
||||||
|
# before even attempting to validate it with the external reseller. Usefull if
|
||||||
|
# multiple auth systems are in use for one Swift cluster.
|
||||||
|
# reseller_prefix =
|
||||||
# ip = 127.0.0.1
|
# ip = 127.0.0.1
|
||||||
# port = 11000
|
# port = 11000
|
||||||
# ssl = false
|
# ssl = false
|
||||||
|
@@ -94,6 +94,9 @@ class AuthController(object):
|
|||||||
def __init__(self, conf, ring=None):
|
def __init__(self, conf, ring=None):
|
||||||
self.logger = get_logger(conf)
|
self.logger = get_logger(conf)
|
||||||
self.swift_dir = conf.get('swift_dir', '/etc/swift')
|
self.swift_dir = conf.get('swift_dir', '/etc/swift')
|
||||||
|
self.reseller_prefix = conf.get('reseller_prefix', 'AUTH').strip()
|
||||||
|
if self.reseller_prefix and self.reseller_prefix[-1] != '_':
|
||||||
|
self.reseller_prefix += '_'
|
||||||
self.default_cluster_url = \
|
self.default_cluster_url = \
|
||||||
conf.get('default_cluster_url', 'http://127.0.0.1:8080/v1')
|
conf.get('default_cluster_url', 'http://127.0.0.1:8080/v1')
|
||||||
self.token_life = int(conf.get('token_life', 86400))
|
self.token_life = int(conf.get('token_life', 86400))
|
||||||
@@ -147,7 +150,7 @@ class AuthController(object):
|
|||||||
begin = time()
|
begin = time()
|
||||||
orig_account_name = account_name
|
orig_account_name = account_name
|
||||||
if not account_name:
|
if not account_name:
|
||||||
account_name = str(uuid4())
|
account_name = '%s%s' % (self.reseller_prefix, uuid4().hex)
|
||||||
partition, nodes = self.account_ring.get_nodes(account_name)
|
partition, nodes = self.account_ring.get_nodes(account_name)
|
||||||
headers = {'X-Timestamp': normalize_timestamp(time()),
|
headers = {'X-Timestamp': normalize_timestamp(time()),
|
||||||
'x-cf-trans-id': 'tx' + str(uuid4())}
|
'x-cf-trans-id': 'tx' + str(uuid4())}
|
||||||
@@ -358,7 +361,9 @@ class AuthController(object):
|
|||||||
validation = self.validate_token(token)
|
validation = self.validate_token(token)
|
||||||
if not validation:
|
if not validation:
|
||||||
return HTTPNotFound()
|
return HTTPNotFound()
|
||||||
groups = ['%s:%s' % (validation[1], validation[2]), validation[1]]
|
groups = [
|
||||||
|
'%s%s:%s' % (self.reseller_prefix, validation[1], validation[2]),
|
||||||
|
'%s%s' % (self.reseller_prefix, validation[1])]
|
||||||
if validation[3]: # admin access to a cfaccount
|
if validation[3]: # admin access to a cfaccount
|
||||||
groups.append(validation[3])
|
groups.append(validation[3])
|
||||||
return HTTPNoContent(headers={'X-Auth-TTL': validation[0],
|
return HTTPNoContent(headers={'X-Auth-TTL': validation[0],
|
||||||
@@ -482,7 +487,7 @@ class AuthController(object):
|
|||||||
if row:
|
if row:
|
||||||
token = row[0]
|
token = row[0]
|
||||||
else:
|
else:
|
||||||
token = 'tk' + str(uuid4())
|
token = '%stk%s' % (self.reseller_prefix, uuid4().hex)
|
||||||
conn.execute('''
|
conn.execute('''
|
||||||
INSERT INTO token
|
INSERT INTO token
|
||||||
(token, created, account, user, cfaccount)
|
(token, created, account, user, cfaccount)
|
||||||
|
@@ -13,6 +13,9 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
from urlparse import urlparse
|
||||||
|
|
||||||
|
|
||||||
def clean_acl(name, value):
|
def clean_acl(name, value):
|
||||||
"""
|
"""
|
||||||
Returns a cleaned ACL header value, validating that it meets the formatting
|
Returns a cleaned ACL header value, validating that it meets the formatting
|
||||||
@@ -27,30 +30,35 @@ def clean_acl(name, value):
|
|||||||
|
|
||||||
The referrer designation format is::
|
The referrer designation format is::
|
||||||
|
|
||||||
.ref:[-]value
|
.r:[-]value
|
||||||
|
|
||||||
The value can be "any" to specify any referrer host is allowed access, a
|
The ``.r`` can also be ``.ref``, ``.referer``, or ``.referrer``; though it
|
||||||
specific host name like "www.example.com", or if it has a leading period
|
will be shortened to just ``.r`` for decreased character count usage.
|
||||||
"." it is a domain name specification, like ".example.com". The leading
|
|
||||||
minus sign "-" indicates referrer hosts that should be denied access.
|
The value can be ``*`` to specify any referrer host is allowed access, a
|
||||||
|
specific host name like ``www.example.com``, or if it has a leading period
|
||||||
|
``.`` or leading ``*.`` it is a domain name specification, like
|
||||||
|
``.example.com`` or ``*.example.com``. The leading minus sign ``-``
|
||||||
|
indicates referrer hosts that should be denied access.
|
||||||
|
|
||||||
Referrer access is applied in the order they are specified. For example,
|
Referrer access is applied in the order they are specified. For example,
|
||||||
.ref:.example.com,.ref:-thief.example.com would allow all hosts ending with
|
.r:.example.com,.r:-thief.example.com would allow all hosts ending with
|
||||||
.example.com except for the specific host thief.example.com.
|
.example.com except for the specific host thief.example.com.
|
||||||
|
|
||||||
Example valid ACLs::
|
Example valid ACLs::
|
||||||
|
|
||||||
.ref:any
|
.r:*
|
||||||
.ref:any,.ref:-.thief.com
|
.r:*,.r:-.thief.com
|
||||||
.ref:any,.ref:-.thief.com,bobs_account,sues_account:sue
|
.r:*,.r:.example.com,.r:-thief.example.com
|
||||||
|
.r:*,.r:-.thief.com,bobs_account,sues_account:sue
|
||||||
bobs_account,sues_account:sue
|
bobs_account,sues_account:sue
|
||||||
|
|
||||||
Example invalid ACLs::
|
Example invalid ACLs::
|
||||||
|
|
||||||
.ref:
|
.r:
|
||||||
.ref:-
|
.r:-
|
||||||
|
|
||||||
Also, .ref designations aren't allowed in headers whose names include the
|
Also, .r designations aren't allowed in headers whose names include the
|
||||||
word 'write'.
|
word 'write'.
|
||||||
|
|
||||||
ACLs that are "messy" will be cleaned up. Examples:
|
ACLs that are "messy" will be cleaned up. Examples:
|
||||||
@@ -58,10 +66,11 @@ def clean_acl(name, value):
|
|||||||
====================== ======================
|
====================== ======================
|
||||||
Original Cleaned
|
Original Cleaned
|
||||||
---------------------- ----------------------
|
---------------------- ----------------------
|
||||||
bob, sue bob,sue
|
``bob, sue`` ``bob,sue``
|
||||||
bob , sue bob,sue
|
``bob , sue`` ``bob,sue``
|
||||||
bob,,,sue bob,sue
|
``bob,,,sue`` ``bob,sue``
|
||||||
.ref : any .ref:any
|
``.referrer : *`` ``.r:*``
|
||||||
|
``.ref:*.example.com`` ``.r:.example.com``
|
||||||
====================== ======================
|
====================== ======================
|
||||||
|
|
||||||
:param name: The name of the header being cleaned, such as X-Container-Read
|
:param name: The name of the header being cleaned, such as X-Container-Read
|
||||||
@@ -71,30 +80,34 @@ def clean_acl(name, value):
|
|||||||
:raises ValueError: If the value does not meet the ACL formatting
|
:raises ValueError: If the value does not meet the ACL formatting
|
||||||
requirements; the error message will indicate why.
|
requirements; the error message will indicate why.
|
||||||
"""
|
"""
|
||||||
|
name = name.lower()
|
||||||
values = []
|
values = []
|
||||||
for raw_value in value.lower().split(','):
|
for raw_value in value.split(','):
|
||||||
raw_value = raw_value.strip()
|
raw_value = raw_value.strip()
|
||||||
if raw_value:
|
if raw_value:
|
||||||
if ':' not in raw_value:
|
if ':' not in raw_value:
|
||||||
values.append(raw_value)
|
values.append(raw_value)
|
||||||
else:
|
else:
|
||||||
first, second = (v.strip() for v in raw_value.split(':', 1))
|
first, second = (v.strip() for v in raw_value.split(':', 1))
|
||||||
if first != '.ref':
|
if not first or first[0] != '.':
|
||||||
values.append(raw_value)
|
values.append(raw_value)
|
||||||
elif 'write' in name:
|
elif first in ('.r', '.ref', '.referer', '.referrer'):
|
||||||
raise ValueError('Referrers not allowed in write ACLs: %s'
|
if 'write' in name:
|
||||||
% repr(raw_value))
|
raise ValueError('Referrers not allowed in write ACL: '
|
||||||
elif not second:
|
'%s' % repr(raw_value))
|
||||||
raise ValueError('No value after referrer designation in '
|
negate = False
|
||||||
'%s' % repr(raw_value))
|
if second and second[0] == '-':
|
||||||
else:
|
negate = True
|
||||||
if second[0] == '-':
|
|
||||||
second = second[1:].strip()
|
second = second[1:].strip()
|
||||||
if not second:
|
if second and second != '*' and second[0] == '*':
|
||||||
raise ValueError('No value after referrer deny '
|
second = second[1:].strip()
|
||||||
'designation in %s' % repr(raw_value))
|
if not second or second == '.':
|
||||||
second = '-' + second
|
raise ValueError('No host/domain value after referrer '
|
||||||
values.append('%s:%s' % (first, second))
|
'designation in ACL: %s' % repr(raw_value))
|
||||||
|
values.append('.r:%s%s' % (negate and '-' or '', second))
|
||||||
|
else:
|
||||||
|
raise ValueError('Unknown designator %s in ACL: %s' %
|
||||||
|
(repr(first), repr(raw_value)))
|
||||||
return ','.join(values)
|
return ','.join(values)
|
||||||
|
|
||||||
|
|
||||||
@@ -106,15 +119,15 @@ def parse_acl(acl_string):
|
|||||||
|
|
||||||
:param acl_string: The standard Swift ACL string to parse.
|
:param acl_string: The standard Swift ACL string to parse.
|
||||||
:returns: A tuple of (referrers, groups) where referrers is a list of
|
:returns: A tuple of (referrers, groups) where referrers is a list of
|
||||||
referrer designations (without the leading .ref:) and groups is a
|
referrer designations (without the leading .r:) and groups is a
|
||||||
list of groups to allow access.
|
list of groups to allow access.
|
||||||
"""
|
"""
|
||||||
referrers = []
|
referrers = []
|
||||||
groups = []
|
groups = []
|
||||||
if acl_string:
|
if acl_string:
|
||||||
for value in acl_string.split(','):
|
for value in acl_string.split(','):
|
||||||
if value.startswith('.ref:'):
|
if value.startswith('.r:'):
|
||||||
referrers.append(value[len('.ref:'):])
|
referrers.append(value[len('.r:'):])
|
||||||
else:
|
else:
|
||||||
groups.append(value)
|
groups.append(value)
|
||||||
return referrers, groups
|
return referrers, groups
|
||||||
@@ -134,24 +147,14 @@ def referrer_allowed(referrer, referrer_acl):
|
|||||||
"""
|
"""
|
||||||
allow = False
|
allow = False
|
||||||
if referrer_acl:
|
if referrer_acl:
|
||||||
if not referrer:
|
rhost = urlparse(referrer or '').hostname or 'unknown'
|
||||||
rhost = 'unknown'
|
|
||||||
else:
|
|
||||||
parts = referrer.split('//', 1)
|
|
||||||
if len(parts) == 2:
|
|
||||||
rhost = parts[1].split('/', 1)[0]
|
|
||||||
if '@' in rhost:
|
|
||||||
rhost = rhost.rsplit('@', 1)[1]
|
|
||||||
rhost = rhost.split(':', 1)[0].lower()
|
|
||||||
else:
|
|
||||||
rhost = 'unknown'
|
|
||||||
for mhost in referrer_acl:
|
for mhost in referrer_acl:
|
||||||
if mhost[0] == '-':
|
if mhost[0] == '-':
|
||||||
mhost = mhost[1:]
|
mhost = mhost[1:]
|
||||||
if mhost == rhost or \
|
if mhost == rhost or \
|
||||||
(mhost[0] == '.' and rhost.endswith(mhost)):
|
(mhost[0] == '.' and rhost.endswith(mhost)):
|
||||||
allow = False
|
allow = False
|
||||||
elif mhost == 'any' or mhost == rhost or \
|
elif mhost == '*' or mhost == rhost or \
|
||||||
(mhost[0] == '.' and rhost.endswith(mhost)):
|
(mhost[0] == '.' and rhost.endswith(mhost)):
|
||||||
allow = True
|
allow = True
|
||||||
return allow
|
return allow
|
||||||
|
@@ -29,6 +29,9 @@ class DevAuth(object):
|
|||||||
def __init__(self, app, conf):
|
def __init__(self, app, conf):
|
||||||
self.app = app
|
self.app = app
|
||||||
self.conf = conf
|
self.conf = conf
|
||||||
|
self.reseller_prefix = conf.get('reseller_prefix', '').strip()
|
||||||
|
if self.reseller_prefix and self.reseller_prefix[-1] != '_':
|
||||||
|
self.reseller_prefix += '_'
|
||||||
self.auth_host = conf.get('ip', '127.0.0.1')
|
self.auth_host = conf.get('ip', '127.0.0.1')
|
||||||
self.auth_port = int(conf.get('port', 11000))
|
self.auth_port = int(conf.get('port', 11000))
|
||||||
self.ssl = \
|
self.ssl = \
|
||||||
@@ -44,7 +47,7 @@ class DevAuth(object):
|
|||||||
"""
|
"""
|
||||||
groups = None
|
groups = None
|
||||||
token = env.get('HTTP_X_AUTH_TOKEN', env.get('HTTP_X_STORAGE_TOKEN'))
|
token = env.get('HTTP_X_AUTH_TOKEN', env.get('HTTP_X_STORAGE_TOKEN'))
|
||||||
if token:
|
if token and token.startswith(self.reseller_prefix):
|
||||||
memcache_client = cache_from_env(env)
|
memcache_client = cache_from_env(env)
|
||||||
key = 'devauth/%s' % token
|
key = 'devauth/%s' % token
|
||||||
cached_auth_data = memcache_client.get(key)
|
cached_auth_data = memcache_client.get(key)
|
||||||
@@ -68,6 +71,10 @@ class DevAuth(object):
|
|||||||
env['REMOTE_USER'] = groups
|
env['REMOTE_USER'] = groups
|
||||||
env['swift.authorize'] = self.authorize
|
env['swift.authorize'] = self.authorize
|
||||||
env['swift.clean_acl'] = clean_acl
|
env['swift.clean_acl'] = clean_acl
|
||||||
|
# We know the proxy logs the token, so we augment it just a bit to also
|
||||||
|
# log the authenticated user.
|
||||||
|
user = groups and groups.split(',', 1)[0] or ''
|
||||||
|
env['HTTP_X_AUTH_TOKEN'] = '%s,%s' % (user, token)
|
||||||
return self.app(env, start_response)
|
return self.app(env, start_response)
|
||||||
|
|
||||||
def authorize(self, req):
|
def authorize(self, req):
|
||||||
|
@@ -882,6 +882,7 @@ class ContainerController(Controller):
|
|||||||
@public
|
@public
|
||||||
def PUT(self, req):
|
def PUT(self, req):
|
||||||
"""HTTP PUT request handler."""
|
"""HTTP PUT request handler."""
|
||||||
|
self.clean_acls(req)
|
||||||
error_response = check_metadata(req, 'container')
|
error_response = check_metadata(req, 'container')
|
||||||
if error_response:
|
if error_response:
|
||||||
return error_response
|
return error_response
|
||||||
@@ -899,7 +900,6 @@ class ContainerController(Controller):
|
|||||||
self.account_name, self.container_name)
|
self.account_name, self.container_name)
|
||||||
headers = {'X-Timestamp': normalize_timestamp(time.time()),
|
headers = {'X-Timestamp': normalize_timestamp(time.time()),
|
||||||
'x-cf-trans-id': self.trans_id}
|
'x-cf-trans-id': self.trans_id}
|
||||||
self.clean_acls(req)
|
|
||||||
headers.update(value for value in req.headers.iteritems()
|
headers.update(value for value in req.headers.iteritems()
|
||||||
if value[0].lower() in self.pass_through_headers or
|
if value[0].lower() in self.pass_through_headers or
|
||||||
value[0].lower().startswith('x-container-meta-'))
|
value[0].lower().startswith('x-container-meta-'))
|
||||||
@@ -948,6 +948,7 @@ class ContainerController(Controller):
|
|||||||
@public
|
@public
|
||||||
def POST(self, req):
|
def POST(self, req):
|
||||||
"""HTTP POST request handler."""
|
"""HTTP POST request handler."""
|
||||||
|
self.clean_acls(req)
|
||||||
error_response = check_metadata(req, 'container')
|
error_response = check_metadata(req, 'container')
|
||||||
if error_response:
|
if error_response:
|
||||||
return error_response
|
return error_response
|
||||||
@@ -958,7 +959,6 @@ class ContainerController(Controller):
|
|||||||
self.account_name, self.container_name)
|
self.account_name, self.container_name)
|
||||||
headers = {'X-Timestamp': normalize_timestamp(time.time()),
|
headers = {'X-Timestamp': normalize_timestamp(time.time()),
|
||||||
'x-cf-trans-id': self.trans_id}
|
'x-cf-trans-id': self.trans_id}
|
||||||
self.clean_acls(req)
|
|
||||||
headers.update(value for value in req.headers.iteritems()
|
headers.update(value for value in req.headers.iteritems()
|
||||||
if value[0].lower() in self.pass_through_headers or
|
if value[0].lower() in self.pass_through_headers or
|
||||||
value[0].lower().startswith('x-container-meta-'))
|
value[0].lower().startswith('x-container-meta-'))
|
||||||
@@ -1273,12 +1273,14 @@ class BaseApplication(object):
|
|||||||
# controller's method indicates it'd like to gather more
|
# controller's method indicates it'd like to gather more
|
||||||
# information and try again later.
|
# information and try again later.
|
||||||
resp = req.environ['swift.authorize'](req)
|
resp = req.environ['swift.authorize'](req)
|
||||||
if resp:
|
if not resp:
|
||||||
if not getattr(handler, 'delay_denial', None) and \
|
# No resp means authorized, no delayed recheck required.
|
||||||
'swift.authorize' in req.environ:
|
|
||||||
return resp
|
|
||||||
else:
|
|
||||||
del req.environ['swift.authorize']
|
del req.environ['swift.authorize']
|
||||||
|
else:
|
||||||
|
# Response indicates denial, but we might delay the denial
|
||||||
|
# and recheck later. If not delayed, return the error now.
|
||||||
|
if not getattr(handler, 'delay_denial', None):
|
||||||
|
return resp
|
||||||
return handler(req)
|
return handler(req)
|
||||||
except Exception:
|
except Exception:
|
||||||
self.logger.exception('ERROR Unhandled exception in request')
|
self.logger.exception('ERROR Unhandled exception in request')
|
||||||
@@ -1331,8 +1333,7 @@ class Application(BaseApplication):
|
|||||||
status_int,
|
status_int,
|
||||||
req.referer or '-',
|
req.referer or '-',
|
||||||
req.user_agent or '-',
|
req.user_agent or '-',
|
||||||
'%s:%s' % (req.remote_user or '',
|
req.headers.get('x-auth-token', '-'),
|
||||||
req.headers.get('x-auth-token', '-')),
|
|
||||||
getattr(req, 'bytes_transferred', 0) or '-',
|
getattr(req, 'bytes_transferred', 0) or '-',
|
||||||
getattr(response, 'bytes_transferred', 0) or '-',
|
getattr(response, 'bytes_transferred', 0) or '-',
|
||||||
req.headers.get('etag', '-'),
|
req.headers.get('etag', '-'),
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
auth_host = 127.0.0.1
|
auth_host = 127.0.0.1
|
||||||
auth_port = 11000
|
auth_port = 11000
|
||||||
auth_ssl = no
|
auth_ssl = no
|
||||||
|
auth_prefix = AUTH
|
||||||
|
|
||||||
# Primary functional test account (needs admin access to the account)
|
# Primary functional test account (needs admin access to the account)
|
||||||
account = test
|
account = test
|
||||||
|
@@ -10,6 +10,9 @@ from swift.common.client import get_auth, http_connection
|
|||||||
|
|
||||||
|
|
||||||
swift_test_auth = os.environ.get('SWIFT_TEST_AUTH')
|
swift_test_auth = os.environ.get('SWIFT_TEST_AUTH')
|
||||||
|
swift_test_auth_prefix = os.environ.get('SWIFT_TEST_AUTH_PREFIX')
|
||||||
|
if swift_test_auth_prefix and swift_test_auth_prefix[-1] != '_':
|
||||||
|
swift_test_auth_prefix += '_'
|
||||||
swift_test_user = [os.environ.get('SWIFT_TEST_USER'), None, None]
|
swift_test_user = [os.environ.get('SWIFT_TEST_USER'), None, None]
|
||||||
swift_test_key = [os.environ.get('SWIFT_TEST_KEY'), None, None]
|
swift_test_key = [os.environ.get('SWIFT_TEST_KEY'), None, None]
|
||||||
|
|
||||||
@@ -32,6 +35,9 @@ if not all([swift_test_auth, swift_test_user[0], swift_test_key[0]]):
|
|||||||
if conf.get('auth_ssl', 'no').lower() in ('yes', 'true', 'on', '1'):
|
if conf.get('auth_ssl', 'no').lower() in ('yes', 'true', 'on', '1'):
|
||||||
swift_test_auth = 'https'
|
swift_test_auth = 'https'
|
||||||
swift_test_auth += '://%(auth_host)s:%(auth_port)s/v1.0' % conf
|
swift_test_auth += '://%(auth_host)s:%(auth_port)s/v1.0' % conf
|
||||||
|
swift_test_auth_prefix = conf.get('auth_prefix', 'AUTH')
|
||||||
|
if swift_test_auth_prefix and swift_test_auth_prefix[-1] != '_':
|
||||||
|
swift_test_auth_prefix += '_'
|
||||||
swift_test_user[0] = '%(account)s:%(username)s' % conf
|
swift_test_user[0] = '%(account)s:%(username)s' % conf
|
||||||
swift_test_key[0] = conf['password']
|
swift_test_key[0] = conf['password']
|
||||||
try:
|
try:
|
||||||
|
@@ -9,7 +9,7 @@ from swift.common.constraints import MAX_META_COUNT, MAX_META_NAME_LENGTH, \
|
|||||||
MAX_META_OVERALL_SIZE, MAX_META_VALUE_LENGTH
|
MAX_META_OVERALL_SIZE, MAX_META_VALUE_LENGTH
|
||||||
|
|
||||||
from swift_testing import check_response, retry, skip, skip2, skip3, \
|
from swift_testing import check_response, retry, skip, skip2, skip3, \
|
||||||
swift_test_user
|
swift_test_auth_prefix, swift_test_user
|
||||||
|
|
||||||
|
|
||||||
class TestContainer(unittest.TestCase):
|
class TestContainer(unittest.TestCase):
|
||||||
@@ -334,7 +334,7 @@ class TestContainer(unittest.TestCase):
|
|||||||
def post(url, token, parsed, conn):
|
def post(url, token, parsed, conn):
|
||||||
conn.request('POST', parsed.path + '/' + self.name, '',
|
conn.request('POST', parsed.path + '/' + self.name, '',
|
||||||
{'X-Auth-Token': token,
|
{'X-Auth-Token': token,
|
||||||
'X-Container-Read': '.ref:any'})
|
'X-Container-Read': '.r:*'})
|
||||||
return check_response(conn)
|
return check_response(conn)
|
||||||
resp = retry(post)
|
resp = retry(post)
|
||||||
resp.read()
|
resp.read()
|
||||||
@@ -377,10 +377,10 @@ class TestContainer(unittest.TestCase):
|
|||||||
self.assertEquals(resp.status, 403)
|
self.assertEquals(resp.status, 403)
|
||||||
# Make the container accessible by the second account
|
# Make the container accessible by the second account
|
||||||
def post(url, token, parsed, conn):
|
def post(url, token, parsed, conn):
|
||||||
conn.request('POST', parsed.path + '/' + self.name, '',
|
conn.request('POST', parsed.path + '/' + self.name, '', {
|
||||||
{'X-Auth-Token': token,
|
'X-Auth-Token': token,
|
||||||
'X-Container-Read': 'test2',
|
'X-Container-Read': '%stest2' % swift_test_auth_prefix,
|
||||||
'X-Container-Write': 'test2'})
|
'X-Container-Write': '%stest2' % swift_test_auth_prefix})
|
||||||
return check_response(conn)
|
return check_response(conn)
|
||||||
resp = retry(post)
|
resp = retry(post)
|
||||||
resp.read()
|
resp.read()
|
||||||
@@ -427,7 +427,7 @@ class TestContainer(unittest.TestCase):
|
|||||||
def post(url, token, parsed, conn):
|
def post(url, token, parsed, conn):
|
||||||
conn.request('POST', parsed.path + '/' + self.name, '',
|
conn.request('POST', parsed.path + '/' + self.name, '',
|
||||||
{'X-Auth-Token': token,
|
{'X-Auth-Token': token,
|
||||||
'X-Container-Read': '.ref:any'})
|
'X-Container-Read': '.r:*'})
|
||||||
return check_response(conn)
|
return check_response(conn)
|
||||||
resp = retry(post)
|
resp = retry(post)
|
||||||
resp.read()
|
resp.read()
|
||||||
@@ -446,9 +446,9 @@ class TestContainer(unittest.TestCase):
|
|||||||
self.assertEquals(resp.status, 403)
|
self.assertEquals(resp.status, 403)
|
||||||
# Now make the container also writeable by the second account
|
# Now make the container also writeable by the second account
|
||||||
def post(url, token, parsed, conn):
|
def post(url, token, parsed, conn):
|
||||||
conn.request('POST', parsed.path + '/' + self.name, '',
|
conn.request('POST', parsed.path + '/' + self.name, '', {
|
||||||
{'X-Auth-Token': token,
|
'X-Auth-Token': token,
|
||||||
'X-Container-Write': 'test2'})
|
'X-Container-Write': '%stest2' % swift_test_auth_prefix})
|
||||||
return check_response(conn)
|
return check_response(conn)
|
||||||
resp = retry(post)
|
resp = retry(post)
|
||||||
resp.read()
|
resp.read()
|
||||||
@@ -485,7 +485,9 @@ class TestContainer(unittest.TestCase):
|
|||||||
# Make the container accessible by the third account
|
# Make the container accessible by the third account
|
||||||
def post(url, token, parsed, conn):
|
def post(url, token, parsed, conn):
|
||||||
conn.request('POST', parsed.path + '/' + self.name, '',
|
conn.request('POST', parsed.path + '/' + self.name, '',
|
||||||
{'X-Auth-Token': token, 'X-Container-Read': swift_test_user[2]})
|
{'X-Auth-Token': token,
|
||||||
|
'X-Container-Read': '%s%s' %
|
||||||
|
(swift_test_auth_prefix, swift_test_user[2])})
|
||||||
return check_response(conn)
|
return check_response(conn)
|
||||||
resp = retry(post)
|
resp = retry(post)
|
||||||
resp.read()
|
resp.read()
|
||||||
@@ -506,7 +508,8 @@ class TestContainer(unittest.TestCase):
|
|||||||
def post(url, token, parsed, conn):
|
def post(url, token, parsed, conn):
|
||||||
conn.request('POST', parsed.path + '/' + self.name, '',
|
conn.request('POST', parsed.path + '/' + self.name, '',
|
||||||
{'X-Auth-Token': token,
|
{'X-Auth-Token': token,
|
||||||
'X-Container-Write': swift_test_user[2]})
|
'X-Container-Write': '%s%s' %
|
||||||
|
(swift_test_auth_prefix, swift_test_user[2])})
|
||||||
return check_response(conn)
|
return check_response(conn)
|
||||||
resp = retry(post)
|
resp = retry(post)
|
||||||
resp.read()
|
resp.read()
|
||||||
|
@@ -65,7 +65,7 @@ class TestObject(unittest.TestCase):
|
|||||||
def post(url, token, parsed, conn):
|
def post(url, token, parsed, conn):
|
||||||
conn.request('POST', parsed.path + '/' + self.container, '',
|
conn.request('POST', parsed.path + '/' + self.container, '',
|
||||||
{'X-Auth-Token': token,
|
{'X-Auth-Token': token,
|
||||||
'X-Container-Read': '.ref:any'})
|
'X-Container-Read': '.r:*'})
|
||||||
return check_response(conn)
|
return check_response(conn)
|
||||||
resp = retry(post)
|
resp = retry(post)
|
||||||
resp.read()
|
resp.read()
|
||||||
|
@@ -21,56 +21,71 @@ from swift.common.middleware import acl
|
|||||||
class TestACL(unittest.TestCase):
|
class TestACL(unittest.TestCase):
|
||||||
|
|
||||||
def test_clean_acl(self):
|
def test_clean_acl(self):
|
||||||
value = acl.clean_acl('header', '.ref:any')
|
value = acl.clean_acl('header', '.r:*')
|
||||||
self.assertEquals(value, '.ref:any')
|
self.assertEquals(value, '.r:*')
|
||||||
value = acl.clean_acl('header', '.ref:specific.host')
|
value = acl.clean_acl('header', '.r:specific.host')
|
||||||
self.assertEquals(value, '.ref:specific.host')
|
self.assertEquals(value, '.r:specific.host')
|
||||||
value = acl.clean_acl('header', '.ref:.ending.with')
|
value = acl.clean_acl('header', '.r:.ending.with')
|
||||||
self.assertEquals(value, '.ref:.ending.with')
|
self.assertEquals(value, '.r:.ending.with')
|
||||||
value = acl.clean_acl('header', '.ref:one,.ref:two')
|
value = acl.clean_acl('header', '.r:*.ending.with')
|
||||||
self.assertEquals(value, '.ref:one,.ref:two')
|
self.assertEquals(value, '.r:.ending.with')
|
||||||
value = acl.clean_acl('header', '.ref:any,.ref:-specific.host')
|
value = acl.clean_acl('header', '.r:-*.ending.with')
|
||||||
self.assertEquals(value, '.ref:any,.ref:-specific.host')
|
self.assertEquals(value, '.r:-.ending.with')
|
||||||
value = acl.clean_acl('header', '.ref:any,.ref:-.ending.with')
|
value = acl.clean_acl('header', '.r:one,.r:two')
|
||||||
self.assertEquals(value, '.ref:any,.ref:-.ending.with')
|
self.assertEquals(value, '.r:one,.r:two')
|
||||||
value = acl.clean_acl('header', '.ref:one,.ref:-two')
|
value = acl.clean_acl('header', '.r:*,.r:-specific.host')
|
||||||
self.assertEquals(value, '.ref:one,.ref:-two')
|
self.assertEquals(value, '.r:*,.r:-specific.host')
|
||||||
value = acl.clean_acl('header',
|
value = acl.clean_acl('header', '.r:*,.r:-.ending.with')
|
||||||
'.ref:one,.ref:-two,account,account:user')
|
self.assertEquals(value, '.r:*,.r:-.ending.with')
|
||||||
self.assertEquals(value, '.ref:one,.ref:-two,account,account:user')
|
value = acl.clean_acl('header', '.r:one,.r:-two')
|
||||||
|
self.assertEquals(value, '.r:one,.r:-two')
|
||||||
|
value = acl.clean_acl('header', '.r:one,.r:-two,account,account:user')
|
||||||
|
self.assertEquals(value, '.r:one,.r:-two,account,account:user')
|
||||||
|
value = acl.clean_acl('header', 'TEST_account')
|
||||||
|
self.assertEquals(value, 'TEST_account')
|
||||||
|
value = acl.clean_acl('header', '.ref:*')
|
||||||
|
self.assertEquals(value, '.r:*')
|
||||||
|
value = acl.clean_acl('header', '.referer:*')
|
||||||
|
self.assertEquals(value, '.r:*')
|
||||||
|
value = acl.clean_acl('header', '.referrer:*')
|
||||||
|
self.assertEquals(value, '.r:*')
|
||||||
value = acl.clean_acl('header',
|
value = acl.clean_acl('header',
|
||||||
' .ref : one , ,, .ref:two , .ref : - three ')
|
' .r : one , ,, .r:two , .r : - three ')
|
||||||
self.assertEquals(value, '.ref:one,.ref:two,.ref:-three')
|
self.assertEquals(value, '.r:one,.r:two,.r:-three')
|
||||||
self.assertRaises(ValueError, acl.clean_acl, 'header', '.ref:')
|
self.assertRaises(ValueError, acl.clean_acl, 'header', '.unknown:test')
|
||||||
self.assertRaises(ValueError, acl.clean_acl, 'header', ' .ref : ')
|
self.assertRaises(ValueError, acl.clean_acl, 'header', '.r:')
|
||||||
|
self.assertRaises(ValueError, acl.clean_acl, 'header', '.r:*.')
|
||||||
|
self.assertRaises(ValueError, acl.clean_acl, 'header', '.r : * . ')
|
||||||
|
self.assertRaises(ValueError, acl.clean_acl, 'header', '.r:-*.')
|
||||||
|
self.assertRaises(ValueError, acl.clean_acl, 'header', '.r : - * . ')
|
||||||
|
self.assertRaises(ValueError, acl.clean_acl, 'header', ' .r : ')
|
||||||
|
self.assertRaises(ValueError, acl.clean_acl, 'header', 'user , .r : ')
|
||||||
|
self.assertRaises(ValueError, acl.clean_acl, 'header', '.r:-')
|
||||||
|
self.assertRaises(ValueError, acl.clean_acl, 'header', ' .r : - ')
|
||||||
self.assertRaises(ValueError, acl.clean_acl, 'header',
|
self.assertRaises(ValueError, acl.clean_acl, 'header',
|
||||||
'user , .ref : ')
|
'user , .r : - ')
|
||||||
self.assertRaises(ValueError, acl.clean_acl, 'header', '.ref:-')
|
self.assertRaises(ValueError, acl.clean_acl, 'write-header', '.r:r')
|
||||||
self.assertRaises(ValueError, acl.clean_acl, 'header', ' .ref : - ')
|
|
||||||
self.assertRaises(ValueError, acl.clean_acl, 'header',
|
|
||||||
'user , .ref : - ')
|
|
||||||
self.assertRaises(ValueError, acl.clean_acl, 'write-header', '.ref:r')
|
|
||||||
|
|
||||||
def test_parse_acl(self):
|
def test_parse_acl(self):
|
||||||
self.assertEquals(acl.parse_acl(None), ([], []))
|
self.assertEquals(acl.parse_acl(None), ([], []))
|
||||||
self.assertEquals(acl.parse_acl(''), ([], []))
|
self.assertEquals(acl.parse_acl(''), ([], []))
|
||||||
self.assertEquals(acl.parse_acl('.ref:ref1'), (['ref1'], []))
|
self.assertEquals(acl.parse_acl('.r:ref1'), (['ref1'], []))
|
||||||
self.assertEquals(acl.parse_acl('.ref:-ref1'), (['-ref1'], []))
|
self.assertEquals(acl.parse_acl('.r:-ref1'), (['-ref1'], []))
|
||||||
self.assertEquals(acl.parse_acl('account:user'),
|
self.assertEquals(acl.parse_acl('account:user'),
|
||||||
([], ['account:user']))
|
([], ['account:user']))
|
||||||
self.assertEquals(acl.parse_acl('account'), ([], ['account']))
|
self.assertEquals(acl.parse_acl('account'), ([], ['account']))
|
||||||
self.assertEquals(acl.parse_acl('acc1,acc2:usr2,.ref:ref3,.ref:-ref4'),
|
self.assertEquals(acl.parse_acl('acc1,acc2:usr2,.r:ref3,.r:-ref4'),
|
||||||
(['ref3', '-ref4'], ['acc1', 'acc2:usr2']))
|
(['ref3', '-ref4'], ['acc1', 'acc2:usr2']))
|
||||||
self.assertEquals(acl.parse_acl(
|
self.assertEquals(acl.parse_acl(
|
||||||
'acc1,acc2:usr2,.ref:ref3,acc3,acc4:usr4,.ref:ref5,.ref:-ref6'),
|
'acc1,acc2:usr2,.r:ref3,acc3,acc4:usr4,.r:ref5,.r:-ref6'),
|
||||||
(['ref3', 'ref5', '-ref6'],
|
(['ref3', 'ref5', '-ref6'],
|
||||||
['acc1', 'acc2:usr2', 'acc3', 'acc4:usr4']))
|
['acc1', 'acc2:usr2', 'acc3', 'acc4:usr4']))
|
||||||
|
|
||||||
def test_referrer_allowed(self):
|
def test_referrer_allowed(self):
|
||||||
self.assert_(not acl.referrer_allowed('host', None))
|
self.assert_(not acl.referrer_allowed('host', None))
|
||||||
self.assert_(not acl.referrer_allowed('host', []))
|
self.assert_(not acl.referrer_allowed('host', []))
|
||||||
self.assert_(acl.referrer_allowed(None, ['any']))
|
self.assert_(acl.referrer_allowed(None, ['*']))
|
||||||
self.assert_(acl.referrer_allowed('', ['any']))
|
self.assert_(acl.referrer_allowed('', ['*']))
|
||||||
self.assert_(not acl.referrer_allowed(None, ['specific.host']))
|
self.assert_(not acl.referrer_allowed(None, ['specific.host']))
|
||||||
self.assert_(not acl.referrer_allowed('', ['specific.host']))
|
self.assert_(not acl.referrer_allowed('', ['specific.host']))
|
||||||
self.assert_(acl.referrer_allowed('http://www.example.com/index.html',
|
self.assert_(acl.referrer_allowed('http://www.example.com/index.html',
|
||||||
@@ -93,7 +108,7 @@ class TestACL(unittest.TestCase):
|
|||||||
self.assert_(not acl.referrer_allowed('http://thief.example.com',
|
self.assert_(not acl.referrer_allowed('http://thief.example.com',
|
||||||
['.example.com', '-thief.example.com']))
|
['.example.com', '-thief.example.com']))
|
||||||
self.assert_(not acl.referrer_allowed('http://thief.example.com',
|
self.assert_(not acl.referrer_allowed('http://thief.example.com',
|
||||||
['any', '-thief.example.com']))
|
['*', '-thief.example.com']))
|
||||||
self.assert_(acl.referrer_allowed('http://www.example.com',
|
self.assert_(acl.referrer_allowed('http://www.example.com',
|
||||||
['.other.com', 'www.example.com']))
|
['.other.com', 'www.example.com']))
|
||||||
self.assert_(acl.referrer_allowed('http://www.example.com',
|
self.assert_(acl.referrer_allowed('http://www.example.com',
|
||||||
@@ -104,7 +119,7 @@ class TestACL(unittest.TestCase):
|
|||||||
['.example.com']))
|
['.example.com']))
|
||||||
self.assert_(not acl.referrer_allowed('../index.html',
|
self.assert_(not acl.referrer_allowed('../index.html',
|
||||||
['.example.com']))
|
['.example.com']))
|
||||||
self.assert_(acl.referrer_allowed('www.example.com', ['any']))
|
self.assert_(acl.referrer_allowed('www.example.com', ['*']))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@@ -253,31 +253,31 @@ class TestAuth(unittest.TestCase):
|
|||||||
self.assert_(resp.startswith('403'), resp)
|
self.assert_(resp.startswith('403'), resp)
|
||||||
req = Request.blank('/v1/cfa')
|
req = Request.blank('/v1/cfa')
|
||||||
req.remote_user = 'act:usr,act'
|
req.remote_user = 'act:usr,act'
|
||||||
req.acl = '.ref:any'
|
req.acl = '.r:*'
|
||||||
self.assertEquals(self.test_auth.authorize(req), None)
|
self.assertEquals(self.test_auth.authorize(req), None)
|
||||||
req = Request.blank('/v1/cfa')
|
req = Request.blank('/v1/cfa')
|
||||||
req.remote_user = 'act:usr,act'
|
req.remote_user = 'act:usr,act'
|
||||||
req.acl = '.ref:.example.com'
|
req.acl = '.r:.example.com'
|
||||||
resp = str(self.test_auth.authorize(req))
|
resp = str(self.test_auth.authorize(req))
|
||||||
self.assert_(resp.startswith('403'), resp)
|
self.assert_(resp.startswith('403'), resp)
|
||||||
req = Request.blank('/v1/cfa')
|
req = Request.blank('/v1/cfa')
|
||||||
req.remote_user = 'act:usr,act'
|
req.remote_user = 'act:usr,act'
|
||||||
req.referrer = 'http://www.example.com/index.html'
|
req.referer = 'http://www.example.com/index.html'
|
||||||
req.acl = '.ref:.example.com'
|
req.acl = '.r:.example.com'
|
||||||
self.assertEquals(self.test_auth.authorize(req), None)
|
self.assertEquals(self.test_auth.authorize(req), None)
|
||||||
req = Request.blank('/v1/cfa')
|
req = Request.blank('/v1/cfa')
|
||||||
resp = str(self.test_auth.authorize(req))
|
resp = str(self.test_auth.authorize(req))
|
||||||
self.assert_(resp.startswith('401'), resp)
|
self.assert_(resp.startswith('401'), resp)
|
||||||
req = Request.blank('/v1/cfa')
|
req = Request.blank('/v1/cfa')
|
||||||
req.acl = '.ref:any'
|
req.acl = '.r:*'
|
||||||
self.assertEquals(self.test_auth.authorize(req), None)
|
self.assertEquals(self.test_auth.authorize(req), None)
|
||||||
req = Request.blank('/v1/cfa')
|
req = Request.blank('/v1/cfa')
|
||||||
req.acl = '.ref:.example.com'
|
req.acl = '.r:.example.com'
|
||||||
resp = str(self.test_auth.authorize(req))
|
resp = str(self.test_auth.authorize(req))
|
||||||
self.assert_(resp.startswith('401'), resp)
|
self.assert_(resp.startswith('401'), resp)
|
||||||
req = Request.blank('/v1/cfa')
|
req = Request.blank('/v1/cfa')
|
||||||
req.referrer = 'http://www.example.com/index.html'
|
req.referer = 'http://www.example.com/index.html'
|
||||||
req.acl = '.ref:.example.com'
|
req.acl = '.r:.example.com'
|
||||||
self.assertEquals(self.test_auth.authorize(req), None)
|
self.assertEquals(self.test_auth.authorize(req), None)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -67,14 +67,13 @@ class TestContainerController(unittest.TestCase):
|
|||||||
self.assert_('x-container-write' not in response.headers)
|
self.assert_('x-container-write' not in response.headers)
|
||||||
# Ensure POSTing acls works
|
# Ensure POSTing acls works
|
||||||
req = Request.blank('/sda1/p/a/c', environ={'REQUEST_METHOD': 'POST'},
|
req = Request.blank('/sda1/p/a/c', environ={'REQUEST_METHOD': 'POST'},
|
||||||
headers={'X-Timestamp': '1', 'X-Container-Read': '.ref:any',
|
headers={'X-Timestamp': '1', 'X-Container-Read': '.r:*',
|
||||||
'X-Container-Write': 'account:user'})
|
'X-Container-Write': 'account:user'})
|
||||||
self.controller.POST(req)
|
self.controller.POST(req)
|
||||||
req = Request.blank('/sda1/p/a/c', environ={'REQUEST_METHOD': 'HEAD'})
|
req = Request.blank('/sda1/p/a/c', environ={'REQUEST_METHOD': 'HEAD'})
|
||||||
response = self.controller.HEAD(req)
|
response = self.controller.HEAD(req)
|
||||||
self.assert_(response.status.startswith('204'))
|
self.assert_(response.status.startswith('204'))
|
||||||
self.assertEquals(response.headers.get('x-container-read'),
|
self.assertEquals(response.headers.get('x-container-read'), '.r:*')
|
||||||
'.ref:any')
|
|
||||||
self.assertEquals(response.headers.get('x-container-write'),
|
self.assertEquals(response.headers.get('x-container-write'),
|
||||||
'account:user')
|
'account:user')
|
||||||
# Ensure we can clear acls on POST
|
# Ensure we can clear acls on POST
|
||||||
@@ -89,14 +88,13 @@ class TestContainerController(unittest.TestCase):
|
|||||||
self.assert_('x-container-write' not in response.headers)
|
self.assert_('x-container-write' not in response.headers)
|
||||||
# Ensure PUTing acls works
|
# Ensure PUTing acls works
|
||||||
req = Request.blank('/sda1/p/a/c2', environ={'REQUEST_METHOD': 'PUT'},
|
req = Request.blank('/sda1/p/a/c2', environ={'REQUEST_METHOD': 'PUT'},
|
||||||
headers={'X-Timestamp': '4', 'X-Container-Read': '.ref:any',
|
headers={'X-Timestamp': '4', 'X-Container-Read': '.r:*',
|
||||||
'X-Container-Write': 'account:user'})
|
'X-Container-Write': 'account:user'})
|
||||||
self.controller.PUT(req)
|
self.controller.PUT(req)
|
||||||
req = Request.blank('/sda1/p/a/c2', environ={'REQUEST_METHOD': 'HEAD'})
|
req = Request.blank('/sda1/p/a/c2', environ={'REQUEST_METHOD': 'HEAD'})
|
||||||
response = self.controller.HEAD(req)
|
response = self.controller.HEAD(req)
|
||||||
self.assert_(response.status.startswith('204'))
|
self.assert_(response.status.startswith('204'))
|
||||||
self.assertEquals(response.headers.get('x-container-read'),
|
self.assertEquals(response.headers.get('x-container-read'), '.r:*')
|
||||||
'.ref:any')
|
|
||||||
self.assertEquals(response.headers.get('x-container-write'),
|
self.assertEquals(response.headers.get('x-container-write'),
|
||||||
'account:user')
|
'account:user')
|
||||||
|
|
||||||
|
@@ -1962,7 +1962,7 @@ class TestContainerController(unittest.TestCase):
|
|||||||
controller = proxy_server.ContainerController(self.app, 'account',
|
controller = proxy_server.ContainerController(self.app, 'account',
|
||||||
'container')
|
'container')
|
||||||
req = Request.blank('/a/c', environ={'REQUEST_METHOD': 'POST'},
|
req = Request.blank('/a/c', environ={'REQUEST_METHOD': 'POST'},
|
||||||
headers={'X-Container-Read': '.ref:any'})
|
headers={'X-Container-Read': '.r:*'})
|
||||||
req.environ['swift.clean_acl'] = clean_acl
|
req.environ['swift.clean_acl'] = clean_acl
|
||||||
self.app.update_request(req)
|
self.app.update_request(req)
|
||||||
res = controller.POST(req)
|
res = controller.POST(req)
|
||||||
@@ -1973,7 +1973,7 @@ class TestContainerController(unittest.TestCase):
|
|||||||
controller = proxy_server.ContainerController(self.app, 'account',
|
controller = proxy_server.ContainerController(self.app, 'account',
|
||||||
'container')
|
'container')
|
||||||
req = Request.blank('/a/c', environ={'REQUEST_METHOD': 'POST'},
|
req = Request.blank('/a/c', environ={'REQUEST_METHOD': 'POST'},
|
||||||
headers={'X-Container-Write': '.ref:any'})
|
headers={'X-Container-Write': '.r:*'})
|
||||||
req.environ['swift.clean_acl'] = clean_acl
|
req.environ['swift.clean_acl'] = clean_acl
|
||||||
self.app.update_request(req)
|
self.app.update_request(req)
|
||||||
res = controller.POST(req)
|
res = controller.POST(req)
|
||||||
@@ -1989,7 +1989,7 @@ class TestContainerController(unittest.TestCase):
|
|||||||
controller = proxy_server.ContainerController(self.app, 'account',
|
controller = proxy_server.ContainerController(self.app, 'account',
|
||||||
'container')
|
'container')
|
||||||
req = Request.blank('/a/c', environ={'REQUEST_METHOD': 'PUT'},
|
req = Request.blank('/a/c', environ={'REQUEST_METHOD': 'PUT'},
|
||||||
headers={'X-Container-Read': '.ref:any'})
|
headers={'X-Container-Read': '.r:*'})
|
||||||
req.environ['swift.clean_acl'] = clean_acl
|
req.environ['swift.clean_acl'] = clean_acl
|
||||||
self.app.update_request(req)
|
self.app.update_request(req)
|
||||||
res = controller.PUT(req)
|
res = controller.PUT(req)
|
||||||
@@ -2000,7 +2000,7 @@ class TestContainerController(unittest.TestCase):
|
|||||||
controller = proxy_server.ContainerController(self.app, 'account',
|
controller = proxy_server.ContainerController(self.app, 'account',
|
||||||
'container')
|
'container')
|
||||||
req = Request.blank('/a/c', environ={'REQUEST_METHOD': 'PUT'},
|
req = Request.blank('/a/c', environ={'REQUEST_METHOD': 'PUT'},
|
||||||
headers={'X-Container-Write': '.ref:any'})
|
headers={'X-Container-Write': '.r:*'})
|
||||||
req.environ['swift.clean_acl'] = clean_acl
|
req.environ['swift.clean_acl'] = clean_acl
|
||||||
self.app.update_request(req)
|
self.app.update_request(req)
|
||||||
res = controller.PUT(req)
|
res = controller.PUT(req)
|
||||||
|
Reference in New Issue
Block a user