diff options
author | gholt <gholt@rackspace.com> | 2010-09-03 22:33:41 -0700 |
---|---|---|
committer | gholt <gholt@rackspace.com> | 2010-09-03 22:33:41 -0700 |
commit | 65eb19f103df7df89c12556bbee71fe04e035ef3 (patch) | |
tree | 68e9cae00fee8a39a0d3417397bb8ad0f35548e0 /swift/common/middleware/acl.py | |
parent | bb01c2244051f653c0f226ae01dd0371d369c1ee (diff) | |
download | swift-65eb19f103df7df89c12556bbee71fe04e035ef3.tar.gz |
Documentation of the new auth and acls middleware modules and bugfixes
Diffstat (limited to 'swift/common/middleware/acl.py')
-rw-r--r-- | swift/common/middleware/acl.py | 120 |
1 files changed, 99 insertions, 21 deletions
diff --git a/swift/common/middleware/acl.py b/swift/common/middleware/acl.py index bfa88b810..bf3148a16 100644 --- a/swift/common/middleware/acl.py +++ b/swift/common/middleware/acl.py @@ -14,37 +14,101 @@ # limitations under the License. def clean_acl(name, value): + """ + Returns a cleaned ACL header value, validating that it meets the formatting + requirements for standard Swift ACL strings. + + The ACL format is:: + + [item[,item...]] + + Each item can be a group name to give access to or a referrer designation + to grant or deny based on the HTTP Referer header. + + The referrer designation format is:: + + .ref:[-]value + + The value can be "any" to specify any referrer host is allowed access, a + specific host name like "www.example.com", or if it has a leading period + "." it is a domain name specification, like ".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, + .ref:.example.com,.ref:-thief.example.com would allow all hosts ending with + .example.com except for the specific host thief.example.com. + + Example valid ACLs:: + + .ref:any + .ref:any,.ref:-.thief.com + .ref:any,.ref:-.thief.com,bobs_account,sues_account:sue + bobs_account,sues_account:sue + + Example invalid ACLs:: + + .ref: + .ref:- + + Also, .ref designations aren't allowed in headers whose names include the + word 'write'. + + ACLs that are "messy" will be cleaned up. Examples: + + ====================== ====================== + Original Cleaned + ---------------------- ---------------------- + bob, sue bob,sue + bob , sue bob,sue + bob,,,sue bob,sue + .ref : any .ref:any + ====================== ====================== + + :param name: The name of the header being cleaned, such as X-Container-Read + or X-Container-Write. + :param value: The value of the header being cleaned. + :returns: The value, cleaned of extraneous formatting. + :raises ValueError: If the value does not meet the ACL formatting + requirements; the error message will indicate why. + """ values = [] for raw_value in value.lower().split(','): raw_value = raw_value.strip() if raw_value: - if ':' in raw_value: + if ':' not in raw_value: + values.append(raw_value) + else: first, second = (v.strip() for v in raw_value.split(':', 1)) - if not first: - raise ValueError('No value before colon in %s' % - repr(raw_value)) - if first == '.ref' and 'write' in name: + if first != '.ref': + values.append(raw_value) + elif 'write' in name: raise ValueError('Referrers not allowed in write ACLs: %s' % repr(raw_value)) - if second: - if first == '.ref' and second[0] == '-': + elif not second: + raise ValueError('No value after referrer designation in ' + '%s' % repr(raw_value)) + else: + if second[0] == '-': second = second[1:].strip() if not second: raise ValueError('No value after referrer deny ' 'designation in %s' % repr(raw_value)) second = '-' + second values.append('%s:%s' % (first, second)) - elif first == '.ref': - raise ValueError('No value after referrer designation in ' - '%s' % repr(raw_value)) - else: - values.append(first) - else: - values.append(raw_value) return ','.join(values) def parse_acl(acl_string): + """ + Parses a standard Swift ACL string into a referrers list and groups list. + + See :func:`clean_acl` for documentation of the standard Swift ACL format. + + :param acl_string: The standard Swift ACL string to parse. + :returns: A tuple of (referrers, groups) where referrers is a list of + referrer designations (without the leading .ref:) and groups is a + list of groups to allow access. + """ referrers = [] groups = [] if acl_string: @@ -56,15 +120,29 @@ def parse_acl(acl_string): return referrers, groups -def referrer_allowed(req, referrers): +def referrer_allowed(referrer, referrer_acl): + """ + Returns True if the referrer should be allowed based on the referrer_acl + list (as returned by :func:`parse_acl`). + + See :func:`clean_acl` for documentation of the standard Swift ACL format. + + :param referrer: The value of the HTTP Referer header. + :param referrer_acl: The list of referrer designations as returned by + :func:`parse_acl`. + :returns: True if the referrer should be allowed; False if not. + """ allow = False - if referrers: - parts = req.referer.split('//', 1) - if len(parts) == 2: - rhost = parts[1].split('/', 1)[0].split(':', 1)[0].lower() - else: + if referrer_acl: + if not referrer: rhost = 'unknown' - for mhost in referrers: + else: + parts = referrer.split('//', 1) + if len(parts) == 2: + rhost = parts[1].split('/', 1)[0].split(':', 1)[0].lower() + else: + rhost = 'unknown' + for mhost in referrer_acl: if mhost[0] == '-': mhost = mhost[1:] if mhost == rhost or \ |